BLOCKER E - Rollback Evidence Binding Fix
06 - BLOCKER E: Rollback Source Evidence-ID Binding (in-blueprint via forward-only)
Codex recheck-2 finding (doc 05)
writer_repoint_manifest #27 carries source hashes but no evidence_id FK;
evidence_registry uniqueness is composite (UNIQUE(storage_class_item_id, artifact_uri, artifact_sha256)), so artifact_sha256 alone cannot select the authoritative artifact. Restore must
fail closed on zero or multiple matching valid artifacts. Codex's options: define an existing approved
relation/path binding exact evidence_id to object identity + #27 hash, or classify a design
amendment.
The fix — rollback is forward-only; its source is the prior immutable manifest version + a unique rollback_evidence_id
Two cases, both resolved by existing approved bindings without a new #27 column:
-
Manifest-object rollback (the new
qt001_cpwriter/gateway/repoint). Per the approved forward-only model (CP-01 §2.4: "Rollback is a new candidate with prior payload, new version/epoch/quorum/evidence; no old row is edited or deleted"), rollback re-activates the prior immutable sealed manifest version. The source bodies are already sealed in that prior version's payload (payload_sha256+ per-itemitem_sha256) and its bound evidence — the prior version is immutable and never deleted (§2.1). So there is no loose hash-only artifact lookup: the restore source is the prior sealed version itself, uniquely identified by itsmanifest_id. The#27 rollback_stub_source_sha256is the post-rollback verification hash, not a restore pointer. -
Legacy owner/ACL rollback. The legacy rollback source is the S14 pre-cutover ownership/ACL snapshot artifact, which IS uniquely bound:
manifest_activationcarriesrollback_evidence_id uuid NOT NULL REFERENCES evidence_registry(evidence_id)— a single approved FK to the snapshot'sevidence_id(its primary key). This selects exactly oneevidence_registryrow, not a non-uniqueartifact_sha256match. Restore replays that snapshot (owner + full ACL) and fails closed if the bound evidence row is missing, revoked, or expired.
So the unique evidence_id binding Codex required already exists for the rollback source that
matters (the S14 snapshot, via manifest_activation.rollback_evidence_id), and the manifest-object
rollback uses the prior immutable version rather than a body-restore-by-hash.
The residual that rides on blocker C
The only rollback source still lacking a unique evidence_id binding is the STUB_FAIL_CLOSED
legacy body restore — and that is part of the blocker-C amendment (doc 04):
- Under Option β (recommended):
STUB_FAIL_CLOSEDis eliminated (owner-isolation + REVOKE reaches effective-EXECUTE = 0 without a body change), so there is no legacy body to restore — E is fully moot for legacy. - Under Option α: the amendment adds a unique per-object
evidence_idbinding for the legacy body, and restore fails closed on zero/multiple matches.
Either way, the blueprint forbids any body change whose source is not uniquely evidence_id-bound and
read-back-verified; absent that, the object is owner-isolated + revoked only (no body change).
PG-native, no new surface
Uses the approved forward-only manifest lifecycle and the existing
manifest_activation.rollback_evidence_id FK to evidence_registry.evidence_id. No new #27 column,
no new surface.
Self-check
PASS only if every rollback source is uniquely bound (not a non-unique hash) and body changes are
forbidden without a unique read-back-verified source. PASS for manifest objects (prior immutable
sealed version) and legacy owner/ACL (S14 snapshot via rollback_evidence_id); the legacy STUB body
case is eliminated (β) or amended (α) under blocker C.