KB-5C4E
dot-iu-cutter v0.5 — First Controlled CUT · Rollback / Compensation Plan (doc 5)
9 min read Revision 1
dot-iu-cutterv0.5first-controlled-cut-approval-packagerollbackforward-compensationno-hard-deletebackup-restore-conditiondieu442026-05-20
dot-iu-cutter v0.5 — First Controlled CUT · Rollback / Compensation Plan
doc 5 of 7 · 2026-05-20 · DESIGN ONLY. NOT executed. Mirrors the v0.4 rollback doctrine (append-only ; never physical delete) and adapts it to the UB-2 first-CUT leg-A scope.
1. Three failure regimes (mutually exclusive)
R-1 pre-connect failure : a no-connect guard (G1/G2/G3/G7), missing GRANT,
unresolved GD-1, unresolved GAP-A1, missing
backup, env-leak. ⇒ NO connect ; NO row touched ;
REFUSED at exit 2 or 3 from cutprod / wrapper.
R-2 pre-commit failure : connection opened ; guard G4/G5/G6 fails OR
birth-gate L1 raises on any IU INSERT OR FK /
UNIQUE / birth-gate L2 raises at COMMIT.
⇒ atomic ROLLBACK ; zero rows persisted.
R-3 post-commit anomaly : COMMIT succeeded but a VW-1..VW-12 row fails
(doc 4) OR an out-of-band invariant violation is
discovered later. ⇒ forward-compensation ONLY
(NEVER physical DELETE/TRUNCATE on the inserted
rows). See §3.
2. R-1 / R-2 — atomic abort / refuse (no compensation needed)
R-1 (pre-connect refused) :
- the operator receives a non-zero exit code (2 or 3) from cutprod (R1) or
the wrapper (R2) with a single STDERR line explaining the refused guard.
- the live DB is byte-identical to the pre-attempt state by construction
(no connection was opened).
- the backup taken in doc 1 §6 / doc 3 §2 is preserved for audit even
though it was not needed for recovery.
- resolve the refused gate, re-take the backup if it has aged out (≤60 min),
re-run.
R-2 (pre-commit ROLLBACK) :
- the single atomic transaction aborts ; zero rows persist on public.*.
- the adapter's allowlists & guards prevent any side-effect outside the
txn (no SAVEPOINT branching ; no autocommit ; no DDL ; no GRANT).
- the operator captures the PostgreSQL error message verbatim, the txn
start/abort timestamps, the row index that triggered the error (if known
pre-L2) or the COMMIT-time L2 / FK error context.
- re-run is gated on a sovereign post-mortem ; for L1/L2 failures, the
likely cause is a vocab key removal / SECURITY-INVOKER definition change
/ catalog drift since doc 1 §3 ; resolve at source (drift = doc 1 §3,
vocab = public.dot_config seed) before re-running.
idempotency on retry :
G-CUT-ONCE (G6) blocks any re-insert after a successful CUT ; for R-2 the
count remains 0 so a retry of the same digest is allowed. The writer_digest
is stable across retries (factory is pure) so G3 keeps passing.
3. R-3 — post-commit compensation doctrine (FORWARD-ONLY)
philosophy : the CUT writes immutable, governed birth rows. After
COMMIT, audit trails depend on those rows existing.
Therefore we NEVER physically remove inserted IU/UV rows.
Any anomaly is corrected by SUPERSEDING entries.
allowed forward-compensation actions (each requires its OWN sovereign-gated
package; NOT included in this approval ; cutter_verify has NO write privilege
on public.* in doc 2 §2 — the compensation grant is a SEPARATE later doc) :
C-1 supersede unit_version
INSERT a new public.unit_version with version_seq = current+1 ; UPDATE
the IU's anchor pair to point at the new uv ; lifecycle_status remains
'enacted' ; the previous uv row is RETAINED as historical evidence.
C-2 lifecycle_status transition on information_unit
UPDATE information_unit.lifecycle_status from 'enacted' to a governed
transition target (e.g., 'superseded', 'corrected') ; an
accompanying new unit_version is recommended ; the prior row is
RETAINED. UPDATE is column-scoped to lifecycle_status ONLY ; this would
require a NEW grant on a NEW column UPDATE allowlist — a separate
sovereign-gated GRANT package.
C-3 governed escalation
record a governed cut_change_set / decision_backlog entry through the
v0.4 production governed path (doc 6) documenting the anomaly and the
compensating action ; this is where the audit trail is canonicalized.
forbidden actions (under all R-3 scenarios) :
- DELETE any inserted public.information_unit row
- DELETE any inserted public.unit_version row
- TRUNCATE public.information_unit or public.unit_version
- UPDATE information_unit.canonical_address or any column outside an
explicitly granted column-scoped UPDATE
- any DDL on the writer-path tables
- any backup restore on the directus DB unless §4 conditions are met
- any covert / un-governed compensation (every action is governed-recorded)
4. Backup restore — ONLY under sovereign declaration of a catastrophic
breach (last resort)
when permitted :
- the live database is provably in an inconsistent, unrecoverable state
(e.g., schema corruption, mass UNIQUE/FK violation that the post-commit
forward-compensation cannot remediate, hostile mutation discovered) AND
- GPT/User explicitly issues a sovereign declaration of catastrophic
breach naming this CUT (manifest_digest 9d908a62…) as the affected
operation AND
- the v0.4 governed compensation path has been judged insufficient.
who executes :
- an authorized DB operator (NOT the Agent ; NOT cutter_exec / cutter_verify).
what restores :
- the fresh logical backup taken per doc 1 §6 / doc 3 §2 (≤60 min old,
sha-verified) of directus.public.information_unit + unit_version +
dot_config.
- the v0.4 historical disaster backstop (backup sha da4e15e6…, recorded by
the v0.4 First Controlled Production CUT package, 2026-05-17) is the
second-tier last resort if the fresh backup is itself compromised.
what is NOT restored automatically :
- the cutter_governance ledger (leg B) — its state depends on doc 6 having
run or not ; sovereign decides whether to restore alongside.
governance :
- the restore action is itself a governed event ; a separate sovereign-
gated package documents what was restored, when, by whom, with what
artefact sha256, and what governed compensation followed.
post-restore CUT re-run :
- re-run is NOT automatic ; the root cause must be eliminated first ; then
a fresh sovereign-gated approval cycle (this same 7-doc package shape) is
required before any CUT is attempted again.
5. Mapping to adapter / composer guards
R-1 enforced by : cutprod argv parser + ProdIuBirthAdapter (G1/G2/G3/G7) +
default _default_provider raising ProductionAccessNotAuthorized.
R-2 enforced by : PostgreSQL atomic-txn semantics + live birth-gate L1/L2 +
the DEFERRED FK fk_iu_version_anchor + UNIQUE
(canonical_address) + adapter allowlists (_IU_COLS / _UV_COLS
/ _ANCHOR_UPDATE_COLS) + G4 (principal) / G5 (drift) / G6
(G-CUT-ONCE).
R-3 enforced by : sovereign process (no physical delete is callable through
the doc-2 GRANTs ; cutter_exec has NO DELETE / NO TRUNCATE
on either table by construction).
6. STOP_AND_ESCALATE protocol (any R-2 or R-3)
1. STOP all retries ; do NOT self-advance.
2. Preserve evidence : exact STDERR / STDOUT / exit code ; txn start / abort
timestamps ; PostgreSQL error sqlstate ; backup artefact sha256 ; doc 1 §3
re-run of the catalog probe immediately after the failure.
3. Route to GPT/User with the evidence bundle.
4. Wait for sovereign ruling ; do NOT attempt R-3 compensation without an
explicit gated package.
5. If the operator chose Option R1 (committed entrypoint), preserve the
feature branch HEAD ; do NOT rebase / force-push.
6. Update KB with a post-mortem doc in
`knowledge/dev/laws/dieu44-trien-khai/v0.5-first-controlled-cut-postmortem-
<date>/` ; link it from this package.
7. Status
rollback_compensation_plan : DESIGN-READY · NOT EXECUTED
backup_restore : conditions specified ; gated to sovereign
hard_delete : FORBIDDEN under all regimes (R-1/R-2/R-3)
production mutation this phase : NONE
self_advance : PROHIBITED
doc 5 of 7. No production mutation. Self-advance PROHIBITED.