What the API step needs from the operator

The operator step is complete. This is the contract the api/ component builds on.

Objects and fields the API reads and writes

Object The API writes The API reads
Baseline spec on connect and promote: application, workspace, source (git url, ref, path, kind, secretRef, helm values, pollInterval), entrypoint, inline services overrides, imageRegistry status.phase, status.source (commit, resolvedAt, renderedAt), status.resolvedServices, status.renderWarnings, status.routes, status.baselineHost, conditions Ready, RoutingReady, IngressTLS, SourceResolved, Rendered
Environment spec.baselineRef, owner, workspace, ref, overrides[], ttl (extend = raise it), sleepAfterIdle, sharers, terminal status.phase (Pending, Deploying, Ready, Sleeping, Expired, Failed), namespace, previewURL, headerRule, services[] with mode copy or shared, expiresAt, deleteAt, lastActivity, sleptAt, conditions Ready, TTL
Policy all of spec: workspaces, maxEnvironmentsPerUser, maxEnvironmentsPerWorkspace, quota, defaultRequests, defaultLimits, defaultTTL, maxTTL, sleepAfterIdle, expiredGracePeriod, allowedRegistries, requireRegistryMirror, terminalEnabled, allowedSourceKinds nothing yet

Git credentials are Secrets in the application namespace with keys token/username, ssh-privatekey/known_hosts/passphrase, ca.crt. The API must label them nazeel.sa/git-credentials=true; the operator's RBAC covers only labelled Secrets and reports a clear condition when the label is missing.

Admission errors to render

Environment writes rejected by the webhook return HTTP 422 with details.causes[]. Each cause has field and message = <key> <json params>. Render with api/v1alpha1.Messages[key] in the caller's language, interpolating {param}; the helper internal/admission.Render shows the exact algorithm. Keys: nazeel.env.baseline.notFound, nazeel.env.baseline.notRendered, nazeel.env.override.unknownService, nazeel.env.override.sharedService, nazeel.env.override.registryNotAllowed, nazeel.env.ttl.exceedsMax, nazeel.env.ttl.invalid, nazeel.env.sleepAfterIdle.invalid, nazeel.env.quota.perUser, nazeel.env.quota.perWorkspace, nazeel.env.terminal.disabledByPolicy, nazeel.env.field.immutable.

Events to ingest into the audit log

Watch events.k8s.io/v1 Events with reportingController nazeel.sa/operator or nazeel.sa/router. Every lifecycle transition is one Event with its own timestamp:

Regarding Reason Type
Environment Expired, ExpiryExtended, TTLCapped, ExpiredDeleted, Sleeping, Woken, WakeTimeout Normal / Warning
Baseline UnknownEnvironment (a request named an environment that does not exist) Warning

The note carries the human-readable detail; action is stable (Expire, ExtendTTL, CapTTL, Delete, Sleep, Wake, Route). Hash-chain them in the API's append-only log.

Rules the API must own

Operational facts the API should expose

Not in the operator (follow-ups)

Supporting objects rendered from git (ConfigMaps, Secrets, volumes, probes, sidecars); inferring the environment from the caller's pod IP when no header is propagated; drift detection between the baseline commit and the tracked branch; cross-namespace quotas.