IU Mutation-Safety Foundation for d/e/f-enable — Live Apply (2026-05-28)
IU Mutation-Safety Foundation for d / e / f-enable — Live Apply (2026-05-28)
Macro:
IU_MUTATION_SAFETY_FOUNDATION_FOR_D_E_AND_F_ENABLE_LIVE_APPLY_150000XExecution class: mixed C4 + C5 (live gate-protocol implementation + substrate-readiness assessment). Builds the reusable mutation-safety layer that every mutating IU test (d, e, f-enable) depends on. No split/merge, no compose, no event emission, no inbound capture, no link enable, no gate left open. Apply channel: SSHworkflow_admin→docker exec -i postgres psql -U workflow_admin -d directus. Read-proof channel: MCPquery_pg(rolecontext_pack_readonly). Companion appendix:iu-mutation-safety-foundation-for-d-e-f-enable-live-apply-appendix-2026-05-28.md. Precursors:iu-b-c-f-additive-dot-wrapper-and-harness-live-apply-2026-05-28.md,iu-b-to-f-execution-readiness-refactor-2026-05-28/(Prompt 4 = M-D).
1. Final status — PASS
- Branch A — Bounded gate protocol: IMPLEMENTED + self-tested live. PASS.
- Branch B — Review-decision readiness: VERIFIED + correctly DEFERRED (no object needed; split/merge already wired). Author-ready Prompt for test d.
- Branch C — Event-contract readiness: VERIFIED + correctly DEFERRED (registration unvalidatable without emit; delivery already route-scoped/fail-closed). Author-ready Prompt for test e.
- Branch D — Rollback / fail-closed: PROVEN for every live object; the rollback's own fail-closed guard demonstrated.
- Branch E — Next execution prompts: 3 paste-ready prompts (§13).
PASS rationale: the one branch that is safe to apply now (the gate protocol) was implemented and proven; the two branches that cannot be safely applied without crossing a forbidden line (fabricating a governance review_decision; registering unexercisable event types) are precisely classified and handed off author-ready. No gate is open; both never-flip keys remain false; no forbidden action taken.
2. Source matrix
| # | Source | Found | Used for |
|---|---|---|---|
| S1 | iu-b-c-f-additive-dot-wrapper-and-harness-live-apply-2026-05-28.md + appendix |
local | Baseline (catalog 47 / run 55 / schema 1,617,882 B); the fail-closed logger contract; channel pattern |
| S2 | iu-b-to-f-execution-readiness-refactor-2026-05-28/02,03,04 |
local | M-D spec (Prompt 4), gate/law matrix, 8-gate inventory + never-flip rule, the 6 authority prompts |
| S3 | Live DB directus — dot_config, pg_proc bodies, cutter_governance, event_type_registry, route layer |
live | The real substrate (corrected several prompt assumptions — see §14) |
| S4 | Master Design Rev5; laws Hiến pháp / Đ0-G / Đ7 / Đ30 / Đ31 / Đ32 / Đ35 / Đ38-39 / Đ45 | KB/auto-memory | Owner-law mapping, never-flip absolutes, refs-only payload, register-before-emit |
| S5 | Prompt standard 100000x v1.3 | auto-memory | PASS/PARTIAL/BLOCKED, underload rule, evidence requirements |
Source gaps (non-blocking): items 3 (iu-bcf-dot-pass-gpt-next-mutation-safety-foundation-2026-05-28.md) and 4 (…command-pack…/08-bounded-gate-protocol.md) of the mission read-list were not present at the literal local paths; the bounded-gate baseline they carry is reproduced in the refactor pack 02/04 (M-D spec) and auto-memory. Laws live under iu-cutter-build/repo/iu-cutter/knowledge/dev/laws/ (not top-level knowledge/dev/laws/); their content was carried in auto-memory and the gate-law matrix. No gate/authority decision depended on a missing copy.
3. Hard Gate 0 — result (PASS)
| Check | Result |
|---|---|
| Host | contabo VPS (ssh contabo reaches host; container postgres Up 5 weeks (healthy)) |
| Container | postgres |
| Database | directus |
| Read channel | query_pg = context_pack_readonly @ directus, 172.19.0.3/32, PG 16.13 |
| Write channel (SELECT-first) | docker exec -i postgres psql -U workflow_admin -d directus → current_user=workflow_admin, current_database=directus |
| Write probe (BEGIN/ROLLBACK) | UPDATE dot_config SET value='true' WHERE key='iu_core.composer_enabled' → in-TX true → ROLLBACK → false (write + reversibility proven on the real target table, persisting nothing) |
| Rollback path writable | /tmp/*.sql authored before apply; pg_dump --schema-only works |
| Snapshot taken | gates, catalog/run counts, event_type_registry, review-decision tables, split/merge tables, route/DLQ tables — §4 |
| Rollback prepared before change | /tmp/rollback_gate_protocol.sql authored before apply |
No no-go condition triggered.
4. Live baseline snapshot (pre-apply)
Gates (dot_config) — all at safe defaults:
| Gate | Value | Class |
|---|---|---|
| iu_core.composer_enabled | false | governable |
| iu_core.structure_ops_enabled | false | governable |
| iu_core.delivery_enabled | false | governable |
| iu_core.three_axis_auto_refresh_enabled | false | governable |
| iu_core.operator_runtime_enabled | false | governable |
| queue.job_substrate.enabled | false | governable |
| queue.dlq.replay_enabled | false | governable |
| iu_enact.allow_no_review_decision | false | NEVER-FLIP |
| iu_core.vector_sync_enabled | false | NEVER-FLIP |
Also observed (delivery scoping): iu_core.delivery_live_routes = "" (empty), iu_core.routes_master_enabled=true, iu_core.route_worker_enabled=true, piece_event_runtime.emit_enabled=false, piece_event_runtime.dry_run_only=true.
Counts: dot_iu_command_catalog=47, dot_iu_command_run=55, event_type_registry=31 (16 domain iu, 6 piece, 5 staging, 4 system), cutter_governance.review_decision=4, iu_split_set=0, iu_merge_set=0, iu_route_dead_letter=0, iu_outbound_route=15, iu_sql_link=3 (all enabled=false). Schema pg_dump --schema-only = 1,617,882 bytes.
5. Branch A — Bounded gate protocol (IMPLEMENTED, PASS)
Gap found: the DB had STABLE reader functions (fn_iu_composer_enabled, fn_iu_structure_ops_enabled, fn_iu_delivery_enabled, fn_iu_vector_sync_enabled, …) but no open/close/verify/watchdog writer protocol and no gate-transition ledger. That is exactly the M-D primitive every mutating test needs.
Installed (additive footprint):
| Object | Kind | Notes |
|---|---|---|
public.iu_gate_transition |
table (+1 index) | ledger: gate_key, action∈{open,close,watchdog_close}, prev/new value, approval_id, ttl_seconds, expires_at, actor, reason, run_id, created_at |
fn_iu_gate_open(gate,approval_id,actor,reason,ttl) |
VOLATILE | opens ONE governable gate for a bounded TTL; fail-closed |
fn_iu_gate_close(gate,actor,reason) |
VOLATILE | forces a gate to safe default false |
fn_iu_gate_verify_closed(gate?) |
STABLE (read) | reports every governable+never-flip gate; all_safe proof |
fn_iu_gate_watchdog(actor) |
VOLATILE | force-closes any governable gate whose open window expired/orphaned |
catalog dot_iu_gate_open/close/watchdog |
rows | category=health, mutating=true, reversible=true |
catalog dot_iu_gate_verify_closed |
row | category=read, mutating=false, reversible=true |
Fail-closed semantics (enforced in code, proven in self-test):
- Never-flip refusal —
iu_enact.allow_no_review_decisionandiu_core.vector_sync_enabledraiseinsufficient_privilege; the gate is never touched. Error text: "supply a real review_decision_id instead of bypassing review." - Non-governable deny — any key not in the 7-gate whitelist is refused (unknown → deny, not allow).
- Approval required (Điều 32) —
NULL approval_idraisescheck_violation; no mutating gate opens without one. - TTL bound —
ttl_seconds ∈ (0, 3600]; every open recordsexpires_at. - Watchdog — any governable gate left
truepast its window is force-closed; safety net for a crashed test. - Verify-closed — single read returns
all_safeover all 9 gates; mandatory macro-end proof.
Audit (Điều 31 via Điều 35): every open/close/watchdog writes both an iu_gate_transition row and a dot_iu_command_run row via canonical fail-closed logger fn_dot_iu_command_log (mutating=true). verify_closed is read-only and writes nothing.
Self-test (BEGIN/ROLLBACK — appendix A5): opened composer (approved) → verified governed-not-closed → refused both never-flip keys (values stayed false) → refused non-governable key → refused null-approval → closed composer → watchdog force-closed an expired delivery window → final all_safe=true → ROLLBACK → ledger_rows=0, gates false, run_count=55. Every effect reverted; the exercise persisted nothing while the protocol persists.
Committed end-state: fn_iu_gate_verify_closed() → all_safe=true, all_governed_closed=true, never_flip_intact=true. Protocol installed but dormant (iu_gate_transition=0 rows, dot_iu_command_run=55 unchanged): no gate opened in persisted state.
6. Branch B — Review-decision readiness (VERIFIED + DEFERRED)
Where review decisions live: cutter_governance.review_decision (RO role denied column/row visibility — read via workflow_admin). 4 rows exist. PK = review_decision_id (uuid).
Shape (heavy governance object — 17 NOT-NULL columns): governance_event_kind, manifest_id (FK→manifest_envelope.envelope_id), manifest_version, review_scope, status, verdict, findings (jsonb), reviewer_class, reviewer_identity (jsonb), risk_class_assessment, decision_at, decided_by, cross_signed_by_dot_verifier (bool), version, created_at, updated_at; plus FK (manifest_id, manifest_unit_local_id) → manifest_unit_block.
Is the wiring already there? — YES. fn_iu_piece_split and fn_iu_piece_merge (both SECURITY DEFINER, with p_dry_run) already:
- reject a NULL
p_review_decision_id(status=invalid_input … next_action=record_review_decision_first); - FK-probe
cutter_governance.review_decisionfor existence (status=review_decision_not_foundif absent); - do not consult
allow_no_review_decisionat all — the id is hard-required unconditionally.
Conclusion: No function wiring is missing. The "row-builder never committed" (TD-P1) is precisely: a valid review_decision is manifest-bound (FK to manifest_envelope + manifest_unit_block) and is a Điều 32 approval artifact (verdict + reviewer identity + cross-sign). Fabricating one is a governed-mutation act, out of scope for a safety-foundation macro (forbidden: no split/merge; fabricating governance approvals is itself unsafe). Therefore no object was created here — a privileged helper with no consumer (split already probes internally) would be unjustified surface.
Safe path for test d (Prompt 5, §13.1): under workflow_admin, create a test manifest_envelope + manifest_unit_block + review_decision bound to cloned test IUs, then pass that real review_decision_id to fn_iu_piece_split/merge — never flip allow_no_review_decision.
7. Branch C — Event-contract readiness (VERIFIED + DEFERRED)
event_type_registry shape (corrected): columns event_domain, event_type, event_stream, delivery_lane, default_severity, description, active, created_at. No JSON-schema column and no compat_mode column (the Prompt-6 assumption of "JSON schema, compat_mode=forward" does not match the live table). Types keyed by (event_domain, event_type), not a dotted single string.
Already registered (trigger-out for structure ops needs nothing new): 16 iu-domain types incl. structure_piece_split, structure_pieces_merged, structure_op_applied, structure_child_added, piece_added_to_collection, piece_removed_from_collection, piece_reordered; 6 piece-domain (created/updated/split/merged/retired/superseded).
Emission is multi-gated + fail-closed (from fn_iu_emit_event / fn_iu_piece_emit_event): (1) master gate fn_iu_core_routes_enabled(); (2) runtime gate piece_event_runtime.emit_enabled (false) + dry_run_only; (3) registry lookup — unknown/inactive (domain,type) returns NULL; (4) trigger trg_event_outbox_type_validate rejects any (domain,type) absent/inactive and requires event_stream/delivery_lane to MATCH the registry exactly.
Delivery is triple-gated + route-scoped (from fn_iu_route_deliver): (1) fn_iu_delivery_enabled() master kill-switch; (2) route must be registered in iu_outbound_route (15 rows); (3) per-route allowlist dot_config.iu_core.delivery_live_routes (currently EMPTY) — a route_code missing from this CSV is refused; this is the route-scoping mechanism (answers Prompt-6 R-B). With the allowlist empty, even an open delivery_enabled delivers nothing; (4) only ONE internal target supported (sql_function / fn_iu_structure_consumer); every external/network target refused.
Conclusion: registration could be applied (additive + reversible), but the lifecycle types the prompt names (route.delivered, route.failed, a trigger-in type) have no emitter in live code (fn_iu_route_deliver returns void and does not emit a delivery event). Registering rows that cannot be exercised in a no-emit macro is speculative. Deferred to Prompt 6 with the exact live contract documented. Trigger-out for d-structure events is already registered; what remains for test e is the trigger-in capture event + (optionally) route lifecycle events, to be registered and immediately exercised under Prompt 6's bounded delivery gate.
8. Rollback / fail-closed proof (Branch D)
| Object | Backup | Rollback script | Verified |
|---|---|---|---|
iu_gate_transition + index |
pg_dump --schema-only (1,617,882 B pre) |
DROP TABLE in /tmp/rollback_gate_protocol.sql |
dry-run |
| 4 gate functions | schema dump | DROP FUNCTION … (exact signatures) |
dry-run |
| 4 catalog rows | row snapshot | DELETE … WHERE command_name IN (…) |
dry-run |
| any audit rows | n/a (0 persisted) | DELETE FROM dot_iu_command_run WHERE command_name IN (…) |
✓ |
- Rollback dry-run (COMMIT→ROLLBACK):
DELETE 0(run) +DELETE 4(catalog) + 4DROP FUNCTION+DROP TABLE+ assertcatalog=47 / 0 fns / no table→ ROLLBACK. Protocol confirmed still installed afterward (catalog=51, gatefns=4). Reverts to the exact baseline. - Rollback fail-closed guard: refuses to run if any governable gate is open. Proven: opened
structure_opsin-TX → guard detected1 gate(s) open→ would REFUSE → ROLLBACK left itfalse. You cannot accidentally drop the watchdog while a gate is open. - Failed-branch safety: Branches B and C deliberately created nothing — zero unsafe state to roll back.
9. Before/after object diff
| Before | After | Δ | |
|---|---|---|---|
| Tables (public) | — | iu_gate_transition |
+1 (+1 index, +1 comment) |
| Functions (gate protocol) | 0 | fn_iu_gate_open (v), fn_iu_gate_close (v), fn_iu_gate_verify_closed (s), fn_iu_gate_watchdog (v) |
+4 |
dot_iu_command_catalog rows |
47 | 51 | +4 |
pg_dump --schema-only bytes |
1,617,882 | 1,628,568 | +10,686 |
Nothing else changed. No existing object altered (reader functions, split/merge, emit, route layer untouched).
10. Before/after row-count delta
| Table | Before | After | Δ |
|---|---|---|---|
| information_unit | 216 | 216 | 0 |
| iu_three_axis_envelope | 216 | 216 | 0 |
| iu_metadata_tag | 536 | 536 | 0 |
| iu_split_set | 0 | 0 | 0 |
| iu_merge_set | 0 | 0 | 0 |
| iu_sql_link | 3 | 3 | 0 |
| event_type_registry | 31 | 31 | 0 |
| event_outbox | (unchanged) | (unchanged) | 0 |
| iu_route_attempt / iu_route_dead_letter | 68 / 0 | 68 / 0 | 0 |
| cutter_governance.review_decision | 4 | 4 | 0 |
| dot_iu_command_catalog | 47 | 51 | +4 |
| dot_iu_command_run | 55 | 55 | 0 (self-test rolled back; protocol dormant) |
| iu_gate_transition | (new) | 0 | 0 rows |
Every IU-data / governance / event / route table delta = 0. Only persisted change is the additive gate-protocol footprint.
11. Changed objects list
Created (persisted): public.iu_gate_transition (+ index ix_iu_gate_transition_gate + comment); public.fn_iu_gate_open, fn_iu_gate_close, fn_iu_gate_verify_closed, fn_iu_gate_watchdog; catalog rows dot_iu_gate_open, dot_iu_gate_close, dot_iu_gate_watchdog, dot_iu_gate_verify_closed.
Artifacts: migration /tmp/mig_gate_protocol.sql md5 be980c7e3ef77886494e532905811925; rollback /tmp/rollback_gate_protocol.sql md5 2d62a732884b238ea49d62e7763eb9da; self-test /tmp/selftest_gate_protocol.sql md5 0d7a7845758e65f29e9977c8dc53b2ef.
12. Branches applied vs deferred
| Branch | Verdict | Why |
|---|---|---|
| A — bounded gate protocol | APPLIED (live, self-tested) | safe additive C4; reversible; proven fail-closed |
| B — review_decision readiness | DEFERRED (author-ready) | already wired in split/merge; only a manifest-bound Đ32 artifact is missing — creating it is governed-mutation, out of scope |
| C — event-contract readiness | DEFERRED (author-ready) | registry shape verified; delivery already route-scoped/fail-closed; lifecycle types unexercisable without emit (forbidden here) |
| D — rollback / fail-closed | APPLIED (proven) | for the one live object set |
| E — next prompts | DELIVERED | §13 |
13. Next three paste-ready execution prompts (Branch E)
All three build on the live gate protocol (
fn_iu_gate_open/close/verify_closed/watchdog) and the corrected substrate findings in §6–§7. Shared channel:ssh contabo \"docker exec -i postgres psql -U workflow_admin -d directus -v ON_ERROR_STOP=1\" < /tmp/mig_NNN.sql(stdin pipe; container/tmp≠ host/tmp; macOS md5 =openssl md5). MCPquery_pgis read-only. 4 Mothers stays BLOCKED in all three.
13.1 — IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X
# MISSION: IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X
Effort: xhigh. Class: C3 GOVERNED_MUTATION_TEST. Mutating + governed.
PRECONDITION: bounded gate protocol live (fn_iu_gate_open/close/verify_closed/watchdog present; verify_closed all_safe=true). If absent, STOP.
## Goal
Run IU test d (d1 compose / d2 add / d3 remove / d4 reorder / d5 split / d6 merge / d7 render) on CLONED test IUs (lifecycle=testing), under bounded gates, with a REAL manifest-bound review_decision_id for d5/d6 — never bypassing review.
## Host / channel
contabo VPS, container postgres, db directus. Write: SSH workflow_admin stdin-pipe. Read: query_pg.
## Hard Gate 0
SSH workflow_admin BEGIN/ROLLBACK probe; pg_dump backup; Dependency Closure: confirm fn_iu_piece_split/merge (already require p_review_decision_id + FK-probe cutter_governance.review_decision), fn_iu_structure_op_apply/rollback, iu_split_set/iu_merge_set, the 9 d-commands; PRIVILEGED read of cutter_governance.review_decision shape (RO denied). If review_decision shape unreadable -> BLOCKED.
## Required approvals
- A real review_decision_id for d5/d6: create a TEST manifest_envelope + manifest_unit_block + review_decision (verdict=approved) bound to the cloned test IUs, under workflow_admin. (review_decision is manifest-bound: FK manifest_id->manifest_envelope, (manifest_id,unit_local_id)->manifest_unit_block.)
- An approval_id for every gate open (fn_iu_gate_open requires it).
## Gates (open via protocol ONLY: fn_iu_gate_open with approval_id + short ttl; close via fn_iu_gate_close; assert with fn_iu_gate_verify_closed)
- iu_core.composer_enabled (compose/add/remove/reorder/render)
- iu_core.structure_ops_enabled (split/merge/reparent)
## Rollback
fn_iu_structure_op_rollback per op; retire/mark test IUs; fn_iu_gate_close every opened gate + fn_iu_gate_verify_closed all_safe=true at end; pre-run pg_dump. If d5/d6 traverse the cut state machine, land U5 (IU_CUT_STATE_MACHINE_ROLLBACK_AFTER_APPROVAL_POLICY) FIRST.
## Forbidden
allow_no_review_decision flip (supply a real id); vector_sync flip; split/merge production law IUs (clones only); leaving any gate open; running split/merge without a review_decision_id; 4 Mothers; Nuxt/UI; secret logging.
## PASS/PARTIAL/BLOCKED
PASS: d1-d7 on test IUs, d5/d6 with a real review_decision_id producing durable iu_split_set/iu_merge_set rows, rollback proven, all gates closed (verify_closed all_safe=true), audit rows present.
PARTIAL: d1-d4/d7 pass; d5/d6 blocked on U5 state-machine edge (named); no unsafe state; gates closed.
BLOCKED: gate protocol absent, or review_decision shape unreadable, or channel down.
## Self-check
Real review_decision_id (not bypass)? Cloned IUs only? All opened gates closed via protocol? Rollback proven? 4 Mothers untouched?
13.2 — IU_TEST_E_TRIGGER_IN_OUT_GOVERNED_LIVE_TEST_60000X
# MISSION: IU_TEST_E_TRIGGER_IN_OUT_GOVERNED_LIVE_TEST_60000X
Effort: xhigh. Class: C2 (event-type registration) + C3 (bounded delivery) + C4 (delivery gate via protocol).
PRECONDITION: bounded gate protocol live. If absent, STOP.
## Goal
Define + exercise the per-IU trigger event contract: register the MISSING trigger-in / route-lifecycle event types (register-before-emit, refs-only), then prove a TEST IU can receive a trigger-in (fn_iu_sql_link_inbound_capture), emit a trigger-out (fn_iu_piece_emit_event -> event_outbox), route a forced failure to iu_route_dead_letter — all under a bounded, route-scoped delivery gate that cannot reach any of the 15 real routes.
## Host / channel
contabo VPS, container postgres, db directus. SSH workflow_admin / query_pg.
## Hard Gate 0 + corrected substrate facts (verified 2026-05-28)
- event_type_registry has NO json-schema/compat_mode columns; key = (event_domain,event_type); stream/lane MUST match registry (trg_event_outbox_type_validate). Source stream/lane from the registry, never hardcode.
- Trigger-OUT for structure ops is ALREADY registered (iu domain: structure_piece_split, structure_pieces_merged, ...). Register only what is genuinely missing (trigger-in capture type; route.delivered/route.failed IF you also add their emitter).
- Delivery is route-scoped by dot_config.iu_core.delivery_live_routes (CSV allowlist, currently EMPTY). A route not in the CSV is refused. The ONLY supported target is sql_function/fn_iu_structure_consumer; external targets refused. Master gate fn_iu_delivery_enabled.
- Confirm: fn_iu_emit_event, fn_iu_piece_emit_event, fn_iu_route_deliver, fn_iu_route_worker_run, fn_iu_route_dead_letter_replay; inventory the 15 iu_outbound_route rows.
## Required approvals
approval_id for fn_iu_gate_open on iu_core.delivery_enabled. Add ONLY a dedicated TEST route_code to iu_core.delivery_live_routes for the window; remove it on close. Never add any of the 15 real route_codes.
## Gates (protocol only)
iu_core.delivery_enabled — open via fn_iu_gate_open (approval_id, short ttl), close via fn_iu_gate_close, assert fn_iu_gate_verify_closed all_safe=true at end. fn_iu_gate_watchdog as the safety net.
## Rollback
Remove test route from allowlist + retire test route/IU/event rows; DELETE any newly-registered event types if the contract changes; gate close + verify_closed; pre-run pg_dump.
## Forbidden
Emitting unregistered events; delivering to ANY of the 15 real routes; leaving delivery_enabled open OR the test route in the allowlist; payload carrying body/secret/vector (refs-only, MP-D8 deny-list); allow_no_review_decision / vector_sync flip; 4 Mothers; secret logging.
## PASS/PARTIAL/BLOCKED
PASS: missing event types registered (refs-only); trigger-in captured for a test IU; trigger-out emits an outbox row; forced failure lands in iu_route_dead_letter (first population); delivery_enabled=false + allowlist empty at end; no real route touched.
PARTIAL: types registered (C2) but delivery test deferred because isolation/route-scoping cannot be fully proven; no unsafe state.
BLOCKED: gate protocol absent, or cannot guarantee the 15 real routes inert.
## Self-check
Register before emit? Any payload body/secret/vector (must be NO)? Could the flip reach a real route (must be NO — empty allowlist + only test route)? delivery_enabled=false + allowlist empty at end?
13.3 — IU_F_SQL_LINK_ENABLE_CAPTURE_GOVERNED_TEST_60000X
# MISSION: IU_F_SQL_LINK_ENABLE_CAPTURE_GOVERNED_TEST_60000X
Effort: xhigh. Class: C3 GOVERNED_MUTATION_TEST (flips iu_sql_link.enabled + runs inbound capture).
PRECONDITION: bounded gate protocol live; f-read proof already PASS. If gate protocol absent, STOP.
## Goal
Prove the WRITE half of test f: enabling a SQL link and running inbound capture on a TEST link/IU only — validate->enable->capture->resolve->disable->rollback — without touching the 3 real iu_sql_link rows live and without leaving any link enabled.
## Host / channel
contabo VPS, container postgres, db directus. SSH workflow_admin / query_pg.
## Hard Gate 0 + facts
- iu_sql_link has 3 real rows, all enabled=false. enabled=false suppresses runtime delivery/capture; validate/resolve read paths already PASS (prior macro).
- fn_iu_sql_link_inbound_capture() is the capture path (trigger-style). Confirm its exact contract + which dot_config gate(s) it honors before any enable.
- Inbound capture may emit/route — keep delivery route-scoped (delivery_live_routes empty + only a test route), reuse Branch C/Prompt-6 contract.
- Create a dedicated TEST iu_sql_link row pointing at a sandbox/test source; never enable a real link.
## Required approvals
approval_id for any gate open via fn_iu_gate_open (delivery/operator_runtime as the capture path requires); a recorded reason for the enable window.
## Gates (protocol only)
Whatever the capture path requires (likely iu_core.delivery_enabled and/or iu_core.operator_runtime_enabled) — open via fn_iu_gate_open, close via fn_iu_gate_close, assert fn_iu_gate_verify_closed all_safe=true at end; watchdog as safety net. Enable the TEST link inside the window; disable before close.
## Rollback
Set the test link enabled=false; delete the test link row + any captured rows; gate close + verify_closed; pre-run pg_dump.
## Forbidden
Enabling any of the 3 REAL iu_sql_link rows; leaving any link enabled; leaving any gate open; delivering to a real route; allow_no_review_decision / vector_sync flip; 4 Mothers; secret logging.
## PASS/PARTIAL/BLOCKED
PASS: a TEST link enabled inside a bounded window, capture demonstrated, resolve consistent, link disabled, gates closed (all_safe=true), real links untouched (still 3, all enabled=false).
PARTIAL: validate/resolve re-proven but capture deferred because the capture contract/gate cannot be safely bounded; no unsafe state.
BLOCKED: gate protocol absent, capture path cannot be isolated from real links/routes, or channel down.
## Self-check
Only a TEST link enabled (never the 3 real)? All links enabled=false at end? Capture isolated from real routes? All gates closed via protocol?
14. Law / gate / no-double-ownership review
- Branch A owns the gate-protocol operation under Điều 35 (DOT catalog pairs) and the approval requirement under Điều 32 (
approval_idmandatory on open; never-flip enforced). Audit (dot_iu_command_run+iu_gate_transition) satisfies Điều 31 as a cross-cutting integrity property — not a second owner. Reversibility satisfies Điều 30 — a property, not an owner. No double ownership. - Branch B is Điều 32 (review_decision) + Điều 38/39 (structure ops) territory — left for the governed test; the safety macro touches neither.
- Branch C is Điều 45 (event/queue: register-before-emit, route-scoping, DLQ) — event-type registration is a Đ45 concern, not Đ35. Left for the delivery test.
- Never-flip absolutes upheld:
iu_enact.allow_no_review_decisionandiu_core.vector_sync_enabledare coded into the protocol refusal list and remainedfalsethroughout (self-test T3/T3b + committedverify_closed). - No-double-ownership: each operation maps to exactly one owner law; Đ30/Đ31 appear only as cross-cutting requirements. The only new owner (4 Mothers / future Điều XX) stays BLOCKED.
15. Forbidden-compliance statement
No actual split/merge. No compose/add/remove/reorder/render. No event emission. No inbound SQL capture. No iu_sql_link.enabled flip. No persistent gate left open (committed verify_closed.all_safe=true). No iu_enact.allow_no_review_decision=true (coded refusal + stayed false). No iu_core.vector_sync_enabled=true (coded refusal + stayed false). No Qdrant/vector write. No Directus mutation. No 4 Mothers work. No Nuxt/UI. No schema/table/template/collection creation beyond the explicitly-justified additive safety objects (1 ledger table + 4 functions + 4 catalog rows). No final OSS selection. No law enactment. Only persisted writes: the gate-protocol DDL + 4 catalog rows; the self-test (which flipped gates) ran inside BEGIN/ROLLBACK and persisted nothing (dot_iu_command_run unchanged at 55). Plus these KB documents.
16. Underload self-check
- Inspect gate substrate? Yes — found reader-only functions, no writer/ledger; built the missing protocol.
- Inspect review-decision substrate? Yes — read full
cutter_governance.review_decisionshape + split/merge bodies; proved wiring already exists; classified the real gap (manifest-bound Đ32 artifact). - Inspect event-contract substrate? Yes — read registry shape, emit + route-deliver bodies; found delivery already route-scoped/fail-closed; corrected the prompt's schema/compat_mode assumption.
- Inspect rollback/fail-closed paths? Yes — dry-ran the rollback; proved its open-gate refusal guard.
- Apply all safe additive pieces? Yes — the gate protocol (the only branch safe to apply without crossing a forbidden line).
- Produce next d/e/f-enable prompts? Yes — §13, all three building on the live protocol + corrected facts.
- Prove no gate left open? Yes — committed
verify_closed.all_safe=true; ledger 0 rows. - Keep 4 Mothers blocked? Yes — untouched; reaffirmed in all three next prompts.
Final verdict: PASS. The mutation-safety foundation is live: a fail-closed, approval-aware, watchdog-backed bounded gate protocol with a verify-closed proof — the single primitive d / e / f-enable depend on — plus precise author-ready hand-offs for the two branches that must stay governed.
17. Next recommended macro
IU_TEST_D_COMPOSE_STRUCTURE_OPS_GOVERNED_LIVE_TEST_60000X (§13.1) — the first governed mutating test, now unblocked by the live gate protocol. It needs a real manifest-bound review_decision_id (for cloned test IUs) and, if d5/d6 traverse the cut state machine, the U5 rollback edge first. Run d before e/f-enable. 4 Mothers remains BLOCKED until b–f + Wave-5 readiness close.