KB-61C6

F-2 Rollback-Only Coverage Dry-Run — 02 Rollback Transaction Plan

4 min read Revision 1
one-roofphase-1f2rollback-onlytransaction-plan

02 — Rollback Transaction Plan

The exact single-transaction plan and safety rails. Full script: sql/f2_rollback.sql.

2.1 Channel & session guards

Executed once via ssh contabo → docker exec -i postgres psql -U workflow_admin -d directus, the script piped on stdin (no files staged on the server). Session guards set before BEGIN:

\set ON_ERROR_STOP on
SET statement_timeout='15s';
SET lock_timeout='3s';
SET idle_in_transaction_session_timeout='30s';

ON_ERROR_STOP on means any unexpected failure aborts the script and closes the connection ⇒ implicit ROLLBACK (fail-safe). It is toggled off only around the negative-test block (which intentionally raises errors), then back on.

2.2 Transaction shape (default ROLLBACK, never COMMIT)

PRE_CENSUS            -- read-only, before BEGIN (entry anchor)
BEGIN
  S1  wire inventory seam  (CREATE OR REPLACE VIEW v_governance_object_inventory)
  S2  wire containment seam (CREATE OR REPLACE VIEW v_governance_object_containment)
  S3  inventory output       (expect 3)
  S4  gap BEFORE ownership   (expect 18 = 3x6, F-DR-1 ceiling)
  S5  transient draft ruleset (status='draft')
  S6  candidate path: scan_run + candidate_state (FK->draft ruleset + snapshot 1)
  S7  ownership seed: 1 accountable inherited-anchor on approval_requests/policy
  S8  owner resolution      (expect direct depth0 + inherited depth1)
  S9  gap AFTER ownership    (expect 16; per-object 6/5/5)
  S10 covered proof         (the 2 object/scope no longer in gap)
  S11 conflict view (real store) (expect 0 — unique index)
  S12 conflict detector predicate on index-less probe (expect 1)
  N1..N6 negative tests      (each SAVEPOINT … failing insert … ROLLBACK TO SAVEPOINT)
  INTX_OUT_OF_SCOPE         (relations 8 / gov_emit 0 / sys_issues 198442 unchanged)
  INTX_TRANSIENT_PERSISTED  (ownership/ruleset/scan_run/cand_state = 1/1/1/1 in-txn)
ROLLBACK
POST_CENSUS           -- read-only, after ROLLBACK (exit anchor; must equal PRE)

2.3 Why DDL inside the transaction is safe

PostgreSQL DDL is transactional. CREATE OR REPLACE VIEW on the two seams is captured in the transaction and auto-restored to its prior inert (WHERE false) definition on ROLLBACK — proven in the SB-2 deferred-substrate rehearsal and re-proven here (doc 06). No DROP, no migration, no out-of-band schema edit survives.

2.4 The seam-wiring decision is rehearsed, not ratified

Wiring v_governance_object_inventory onto collection_registry for real (a COMMIT) is the F-4 step and requires L2+L4 ratification (it crosses inert→active for coverage). F-2 performs that wiring only inside a rolled-back transaction to prove the path works against the real source — it does not authorize or perform the F-4 commit.

2.5 In-flight abort gates (none fired)

ROLLBACK immediately if: result rows exceed the per-scope ceiling (18 subset); any event_outbox/system_issues/registry_changelog insert; any worker-cursor advancement; any DOT/event/handler activation; any out-of-scope table change; failed transaction state unrecoverable; idle transaction un-closable. The script's own INTX_OUT_OF_SCOPE probe and the post-rollback census confirm none of these occurred.

2.6 Rollback readiness

The default terminal statement is ROLLBACK (not COMMIT). Even on the type-mismatch failure of the first attempt (doc 06 §6.1), ON_ERROR_STOP closed the connection mid-BEGIN ⇒ implicit ROLLBACK ⇒ zero residue (verified). No separate restore script is needed because nothing is ever committed; the SB-2 inert seam definitions live in one-roof-phase1-test-mode-deferred-substrate-completion-2026-06-02/sql/sb2_views_ddl.sql should a manual restore ever be required.

Back to Knowledge Hub knowledge/dev/reports/architecture/one-roof-phase1-coverage-dry-run-f2-rollback-only-2026-06-02/02-rollback-transaction-plan.md