Contents

Deployment stage receipts

Inspect durable deployment-stage attempt observations and the evidence required before scoped QA.

Table: deployment_stage_receipts

Durable executor observations for non-QA deployment-stage attempts. Events do not substitute for this authority.

id INTEGER PRIMARY KEY
run_id TEXT NOT NULL REFERENCES deployment_runs(id)
stage_name TEXT NOT NULL
attempt_number INTEGER NOT NULL -- allocated before dispatch; increasing per run/stage
correlation_id TEXT NOT NULL -- idempotency key for one dispatch
target_kind TEXT NOT NULL -- persistent_environment | run_preview
target_name TEXT -- required when ready
status TEXT NOT NULL -- pending | ready | failed | cancelled
observed_url TEXT
observed_release_lineage TEXT -- required when ready; exact run candidate
observed_artifact_identity TEXT -- must match when the run pins an artifact
executor TEXT NOT NULL
executor_receipt TEXT
failure_reason TEXT -- required when failed or cancelled
created_at TEXT NOT NULL
completed_at TEXT -- required when ready
UNIQUE(run_id, stage_name, attempt_number)
UNIQUE(run_id, stage_name, correlation_id)

The attempt number, rather than row insertion order, determines the current observation. A repeated correlation is accepted only with identical immutable dispatch inputs, and a terminal callback cannot change its evidence. Scoped QA consumes only the latest ready attempt from the QA target's earlier source_stage, with the exact target and release lineage and, when the run pins one, the exact artifact identity. A delayed older success cannot override a newer failure, and a superseded receipt cannot revalidate an accepted execution or later-stage prerequisite. Run-preview readiness requires an observed URL; command-only persistent environments do not.

Who fills those observed columns is a per-target-kind decision, registered in deploy_pipeline_stage_receipt_producers.RECEIPT_PRODUCERS. Each producer takes one ProducerContext (the stage, its QA target, the run and stage names, the project, the dispatch correlation id and the dispatch callable) and returns a StageObservation: target name, observed release lineage, optionally an observed URL and artifact identity. The step runner's diagnostic travels to executor_receipt instead, so a producer that reads a served URL and commit back reports them structurally rather than encoding them in one string. An empty observed-identity column is not a gap to fill with whatever string is at hand — the store compares observed against pinned, so an invented value refuses the receipt, and a run pinning an artifact identity no producer reads back is refused before the stage dispatches. The registry's key set is the supported-target-kind list.

Release verification — how release-to-done reads both QA authorities and who observes a stage receipt — lives in release authorities. Human verdict notices reach the waiting agent; settled QA results and owner delivery notices live in release notices.

Table: deployment_run_timings

Release phase timings: the start/end Deployment start timing: records each run-scoped driver timing scope stores through deployment_runs.timings.record at each pipeline stage and when it closes. Read them with yoke deployment-runs timings RUN-ID. They are diagnostics; nothing operational reads them, and a refused write never fails the run (see deployment start).

id INTEGER PRIMARY KEY
run_id TEXT NOT NULL REFERENCES deployment_runs(id)
batch_id TEXT NOT NULL -- one driver timing scope
sequence INTEGER NOT NULL -- record order within the scope; a retried flush inserts nothing twice
step TEXT NOT NULL
phase TEXT NOT NULL -- start | end
recorded_at TIMESTAMPTZ NOT NULL -- the driver clock's record timestamp
elapsed_ms DOUBLE PRECISION -- end records only
outcome TEXT -- end records only: ok | failed
record TEXT NOT NULL -- the full JSON record as the driver wrote it
UNIQUE(batch_id, sequence)
Stage receipts · Yoke