KB-6F23

BLOCKER E - Rollback Evidence Binding Fix

4 min read Revision 1

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:

  1. Manifest-object rollback (the new qt001_cp writer/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-item item_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 its manifest_id. The #27 rollback_stub_source_sha256 is the post-rollback verification hash, not a restore pointer.

  2. Legacy owner/ACL rollback. The legacy rollback source is the S14 pre-cutover ownership/ACL snapshot artifact, which IS uniquely bound: manifest_activation carries rollback_evidence_id uuid NOT NULL REFERENCES evidence_registry(evidence_id) — a single approved FK to the snapshot's evidence_id (its primary key). This selects exactly one evidence_registry row, not a non-unique artifact_sha256 match. 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_CLOSED is 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_id binding 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.

Back to Knowledge Hub knowledge/dev/reports/architecture/t1-fix7-blueprint-patch-after-codex-recheck-2-pg-authority-contract-2026-06-08/06-rollback-evidence-binding-fix.md