KB-23B7

F-3 Consolidation Rollback-Only Coverage Dry-Run — 03 Transaction Plan & SQL

6 min read Revision 1
one-roofphase-1f3transaction-planrollback-onlysqlf2-1-cast

03 — F-3 Transaction Plan & SQL

The exact single-transaction plan and safety rails. Full script: sql/f3_consolidation_rollback.sql (executed once, on stdin, default ROLLBACK).

3.1 Channel & session guards

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

ON_ERROR_STOP on ⇒ 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. The terminal statement is ROLLBACK; there is no COMMIT anywhere in the script.

3.2 Transaction shape (default ROLLBACK, never COMMIT)

PRE_CENSUS                       -- read-only, before BEGIN (entry anchor)
BEGIN
  -- PHASE A: full-35 ceiling proof (bounded, real view)
  A1  wire inventory seam over ALL governed BIRTH_REQUIRED (CREATE OR REPLACE VIEW)
  A2  inventory count            (expect 35)
  A3  gap BEFORE ownership full  (expect 210 = 35×6; ABORT GATE if >210)
  -- PHASE B: narrow to 10-subset + REAL acyclic containment
  B1  re-wire inventory seam → 10-collection subset
  B2  wire containment seam from REAL collection_registry."group"
  B3  inventory output           (expect 10)
  B4  containment edges          (expect 10 edges → 3 groups)
  B5  acyclicity / max-depth     (expect max_depth=1, no cycle guard hit)
  B6  gap BEFORE ownership subset (expect 60 = 10×6)
  -- PHASE C: transient ruleset + candidate path (fail-closed FK chain)
  C1  draft ruleset (status='draft')
  C2  scan_run + candidate_state (FK→draft ruleset + snapshot 1)
  -- PHASE D: ownership seeds
  D1  GROUP anchor   GRP-GOVERNANCE/policy accountable GOV-COUNCIL anchor=true
  D2  DIRECT owner   workflows/policy       accountable GOV-DOT    anchor=false
  -- PHASE E: resolution / gap / covered / conflict at broader scope
  E1  owner resolution            (expect 6: 2 direct + 4 inherited)
  E2  resolution on inventory only (expect 5: 1 direct + 4 inherited)
  E3  gap AFTER by object         (5 for 5 covered, 6 for 5 uncovered)
  E4  gap AFTER total             (expect 55)
  E5  covered proof               (5 inventory/policy pairs)
  E6  conflict view real store    (expect 0 — unique index)
  E7  conflict detector predicate (expect 1 — index-less probe)
  -- PHASE F: negative tests (savepoints; expected errors)
  N1..N7                          (UNIQUE / 2×FK / 3×CHECK / candidate ruleset FK)
  -- PHASE G: out-of-scope + transient-persisted probes
  INTX_OUT_OF_SCOPE               (relations 8 / gov_emit 0 / sys_issues 198442)
  INTX_TRANSIENT_PERSISTED        (ownership 2 / ruleset 1 / scan_run 1 / cand_state 1)
ROLLBACK
POST_CENSUS                      -- read-only, after ROLLBACK (exit anchor; must equal PRE)

3.3 Why this is broader than F-2 yet still safe

  • Two seams over real sources. Inventory over collection_registry (35 then 10 rows); containment over collection_registry."group" (10 real edges). Both CREATE OR REPLACE VIEW — transactional, auto-restored to inert WHERE false on ROLLBACK.
  • Bounded by construction. Full inventory = 35 rows; full gap = 210 rows (abort gate). Subset = 10 rows / 60 gap. No object-grain, no birth_registry sweep, no cursor.
  • Group-level inheritance is real, not fabricated. The anchor sits on a genuine folder-group node (GRP-GOVERNANCE); the 4 child edges come from the live group column. No hardcoded parent/child pairs.
  • All writes trigger-free. The 4 governance write tables have 0 triggers (doc 01 §1.3); collection_registry (with 11 triggers) is read-only here.

3.4 The F2-1 corrected cast (carried)

Both seam DDLs cast the varchar source column to text:

SELECT 'collection'::text AS object_type,
       cr.collection_name::text AS object_ref, ...

Without ::text, CREATE OR REPLACE VIEW errors with "cannot change data type of view column" (live cols are text; collection_name is varchar(255)). This is the single load-bearing DDL correction folded into the F-4 spec (doc 08).

3.5 In-flight abort gates (none fired)

ROLLBACK immediately if: full gap > 210 or subset gap > 60 (A3/B6 ceilings); containment depth ≥ 64 / cycle guard hit (B5); any event_outbox/system_issues/registry_changelog insert; any worker-cursor advance; any DOT/event/handler activation; any out-of-scope table change; unrecoverable failed-txn state; un-closable idle transaction. The script's INTX_OUT_OF_SCOPE probe + the post-rollback census (doc 07) confirm none occurred.

3.6 Rollback readiness

Default terminal statement is ROLLBACK. Nothing is ever committed, so no restore script is needed; should a manual restore of the inert seam definitions ever be required, they live in one-roof-phase1-test-mode-deferred-substrate-completion-2026-06-02/sql/sb2_views_ddl.sql. The independent query_pg check after the run confirmed both seams are back to WHERE false (doc 07 §7.3).

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