12

Publish an Immutable Release

Turn an approved preview into a traceable release without rebuilding or silently changing the artifact.

Run it in the public monorepo

This course is built around the public Zheta Kubernetes Lab monorepo. The excerpt below is runnable source, not pseudocode.

Source: services/control_plane/domain.py

def retire(self, project: Project, actor: str) -> None:
        self._owner(project, actor)
        project.status = "retired"
        with self.repository.transaction():
            self.repository.save(project)
            self._audit(project, actor, "project.retired")
        self.runtime.delete(project.organization_id, project.project_id)

    def delete(self, project: Project, actor: str) -> None:
        self._owner(project, actor)
        if project.status != "retired":
            raise ValueError("retire project before deletion")

Code to reality

Declared intent
Enforce the product lifecycle so published runtime state is retired before durable deletion.
Interpreter
The injected Forge model applies ownership and state-machine rules independently of HTTP or storage technology.
Software effect
Retirement removes the hosted runtime and records status before deletion can tombstone control-plane state.
Hardware effect
Runtime containers and storage can be released in order while retained evidence remains physically durable.
Observable evidence
A denied early delete, successful retirement, absent runtime, tombstoned project, and retained audit event prove order.

Start with the people and the result they need

The source tables below remain the detailed contract. Begin with these customer paths:

  • D12-UC-01
    • Person: Product owner
    • Job: Publish an approved application version to its stable domain
    • Observable result: Research Brief, Service Desk, or Field Inspection users receive the exact reviewed artifact
  • D12-UC-02
    • Person: Release manager
    • Job: Withdraw or contain a failed publication before wider exposure
    • Observable result: Traffic remains on the prior good release or moves to a safe maintenance response

Turn each customer job into a testable story

Now turn each customer job into a story with a result that an engineer can check:

  • D12-US-01
    • Story: As a product owner, I want publication to use the approved artifact digest, so that the public result cannot differ from the preview I accepted
    • Observable acceptance: Receipt proves source, digest, approval, deployment revision, domain, response, environment, timestamp, run, and trace
  • D12-US-02
    • Story: As a release manager, I want policy to stop an invalid candidate before traffic changes, so that the last known-good application remains available
    • Observable acceptance: Invalid digest or missing approval is denied and the stable domain still serves the recorded prior digest

Add real state and observable proof

Finally trace each story through the system that owns its state and the evidence that proves the outcome:

  • D12-FLOW-01
    • Trigger: Product owner selects Publish approved version
    • Responsible systems: Approval Service, Artifact Registry, Release Orchestrator, Runtime Deployer, Route Controller, generated-app Policy Evaluator
    • Authoritative state: Release Store for approved binding; Artifact Registry for digest-addressed bytes; runtime API for deployment and route
    • Owned record: ReleaseCandidate
    • Observable evidence: Release receipt with actor, resource, scope, preconditions, expected and observed digest, environment, timestamp, approval, run, deployment, and…
    • Failure signal: Signature failure, digest mismatch, deployment not ready, TLS failure, or response digest mismatch
  • D12-FLOW-02
    • Trigger: Release manager submits a candidate with a changed digest or missing approval
    • Responsible systems: Release Orchestrator, policy engine, Route Controller, probe runner
    • Authoritative state: Release Store for denied decision and current active release
    • Owned record: RuntimeRelease
    • Observable evidence: Denial reason, rejected digest, unchanged route target, prior-release response, environment, timestamp, and immutable run ID
    • Failure signal: Policy denial absent, route changed despite denial, or prior-release probe failed

The enterprise problem and today’s slice

Enterprise problem: A customer can approve a Zheta Forge preview, yet a publish pipeline that rebuilds from a mutable branch may expose different code, prompts, dependencies, or policies to end users. Whole-course context: The incoming evidence is a content-addressed artifact and provider collaborator state; today creates the local release record. Today’s slice: We bind owner authority, artifact digest, idempotency key, runtime payload, and audit action, while treating approval, signature, environment policy, DNS/TLS, and generated-app visibility as unimplemented production gates. End-of-day evidence: The restart/multi-instance test proves one release for a repeated key, and runtime plus audit records carry its artifact and release IDs; there is no live production endpoint proof. Still unsolved: Approval and promotion controls, subsequent change, rollback, and production operations remain deferred.

Customer use cases

Publication is unsafe when “latest” can change after review, because the customer cannot know what end users received. These use cases make the approved bytes and release policy explicit.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D12-UC-01Product ownerPublish an approved application version to its stable domainResearch Brief, Service Desk, or Field Inspection users receive the exact reviewed artifactPublish is denied if digest, approval, policy, or environment binding differs from the reviewed candidate
D12-UC-02Release managerWithdraw or contain a failed publication before wider exposureTraffic remains on the prior good release or moves to a safe maintenance responseFailed candidate receives no traffic; prior release positive control and release decision are preserved

Actor-centred user stories

An approval checkbox has no value if it is not bound to immutable inputs. These stories define publication as a verifiable transition rather than another build.

Story IDUse case IDsUser storyObservable acceptance conditions
D12-US-01D12-UC-01As a product owner, I want publication to use the approved artifact digest, so that the public result cannot differ from the preview I acceptedReceipt proves source, digest, approval, deployment revision, domain, response, environment, timestamp, run, and trace
D12-US-02D12-UC-02As a release manager, I want policy to stop an invalid candidate before traffic changes, so that the last known-good application remains availableInvalid digest or missing approval is denied and the stable domain still serves the recorded prior digest

End-to-end product flows

A release can pass CI and still serve the wrong bytes, so the flow must trace customer approval through routing to a response. The negative flow proves traffic does not move when the binding is invalid.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D12-FLOW-01D12-UC-01HappyProduct owner selects Publish approved version1. Resolve the approved candidate. 2. Verify artifact digest and signatures. 3. Evaluate environment release policy. 4. Deploy the existing artifact. 5. Shift the stable route. 6. Probe identity, generated-app authorization, and response digest.Release receipt with actor, resource, scope, preconditions, expected and observed digest, environment, timestamp, approval, run, deployment, and trace IDs
D12-FLOW-02D12-UC-02DeniedRelease manager submits a candidate with a changed digest or missing approval1. Detect binding mismatch. 2. Record policy denial. 3. Leave route on prior release. 4. Probe the prior release as positive control.Denial reason, rejected digest, unchanged route target, prior-release response, environment, timestamp, and immutable run ID

The product owner requests one clear transition: make the reviewed application available at its stable domain. The diagram does not yet assume how the platform enforces that promise.

System design derived from the flows

Publication crosses ownership boundaries, so one service must not own approval, artifact bytes, runtime routing, and application visibility. The release orchestrator coordinates these owners using immutable references.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D12-UC-01Control-plane Publish actionApproval Service, Artifact Registry, Release Orchestrator, Runtime Deployer, Route Controller, generated-app Policy EvaluatorRelease Store for approved binding; Artifact Registry for digest-addressed bytes; runtime API for deployment and routeSignature failure, digest mismatch, deployment not ready, TLS failure, or response digest mismatch
D12-UC-02Release policy gateRelease Orchestrator, policy engine, Route Controller, probe runnerRelease Store for denied decision and current active releasePolicy denial absent, route changed despite denial, or prior-release probe failed

The control plane owns approval and release policy, the runtime owns deployment and routing, and the generated application owns end-user visibility. None of those grants implies another; the release carries opaque references and each boundary independently authorises its action.

Data model and ownership

A deployment timestamp cannot prove what was published because mutable tags and reconstructed metadata can lie. Durable records bind the approved digest to the active runtime revision and customer evidence.

Generated-application database: Not created in this runnable slice — the control plane records artifact and release identities while generated-app visibility, tenant roles, and domain records remain an unimplemented application-owned boundary.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
ReleaseCandidateControl-plane Release Store, owned by Release Orchestratorrelease_candidate_idOpaque project_revision_id and artifact_digestorganization_idApproval binds exact digest, policy version, and target environmentCreate from preview, approve or reject, retain as immutable audit evidenceD12-UC-01, D12-UC-02
RuntimeReleaseHosted-runtime deployment store, owned by Runtime Deployerruntime_release_idOpaque release_candidate_id and artifact_digestruntime_tenant_idOne active route target per application and environment; artifact is digest-addressedDeploy, mark ready, activate or fail, retain for rollback, delete after retentionD12-UC-01, D12-UC-02
PublicationVisibilityGenerated-application database, owned by Policy Evaluatorvisibility_policy_idOpaque runtime_release_idapp_tenant_idVisibility change cannot grant a role or tenant not declared by the applicationDraft, activate with release, revoke, export, delete with tenant policyD12-UC-01, D12-UC-02

The immutable digest progresses through explicit release states; it is never rebuilt between approval and deployment. Route and response evidence lets a reviewer distinguish a correct publish, a denied candidate, and a runtime failure.

Promote bytes, not branch names

A branch or mutable image tag can point at different content over time, which destroys the chain from review to deployment. The current model publishes the latest content-addressed artifact with an idempotency key; it does not implement the proposed ApplicationRelease custom resource, approval receipt, signature verification, or production promotion gate. Read the exact operation in services/control_plane/domain.py.

def publish(self, project: Project, actor: str, idempotency_key: str) -> dict[str, str]:
    self._owner(project, actor)
    if not idempotency_key:
        raise ValueError("Idempotency-Key required")
    existing = next((release for release in project.releases if release["idempotency_key"] == idempotency_key), None)
    if existing:
        return existing
Effect fieldWhat happens
Declared intentRequire owner authority and a request idempotency key so a retried publish returns the same release
InterpreterPython executes Forge.publish; repository, artifact-store, runtime, and event adapters handle boundary effects
Software effectA new release points at the latest stored artifact, project status becomes published, and runtime receives the artifact source; duplicate keys return the existing release
Hardware effectLocal service CPU, network sockets, and SQLite volumes are used; no EKS node, load balancer, or AWS production resource is created
Evidencetest_restart_multi_instance_and_idempotent_publish, rel-1, artifact digest, runtime payload, and release.published event prove the implemented local behavior

Key takeaways

Publication is a policy-bound routing transition to an already reviewed immutable artifact.

  • Approval must bind digest, environment, and policy version.
  • Runtime readiness and customer response are stronger evidence than a successful pipeline.
  • A denied candidate must leave the prior release observably healthy.

Checklist

A release is publishable only when review and runtime identity remain connected.

  • [ ] Artifact is addressed by digest and signature result is recorded
  • [ ] Approval binds exact inputs and target environment
  • [ ] Provider, runtime, and generated-app authorizations remain separate
  • [ ] Positive response and denied-candidate evidence include immutable IDs