KB-519D

dot-iu-cutter v0.4 — Credential Dry-Run Rollback Draft

8 min read Revision 1
dot-iu-cutterv0.4credential-authoringrollback-draftdieu44

dot-iu-cutter v0.4 — Credential Dry-Run Rollback Draft

document_path: knowledge/dev/laws/dieu44-trien-khai/v0.4-credential-authoring/dot-iu-cutter-v0.4-credential-dry-run-rollback-draft-2026-05-16.md
revision: r1
date_authored: 2026-05-17
cycle_date_label: 2026-05-16
author: Agent (Claude Code CLI, Opus 4.7 1M)
phase: v0.4 — credential-cycle DRY-RUN AUTHORING (rollback draft)
status: authoring_only_not_executed_pending_gpt_review

⛔ AUTHORING ONLY. Not executed. This is the EXACT-INVERSE rollback the dry-run cycle runs inside the isolated env only. No CASCADE anywhere. DROP ROLE only behind a memberless + owns-nothing + no-privilege gate. cutter_ro, the 12 views, the 12 base tables, Directus, RLS: NEVER touched.


§1 — Rollback Principles

- credential rollback is a ROLE/GRANT-only operation: never a base table,
  view, cutter_ro, Directus object, or any data row.
- EXACT INVERSE of the SQL draft §3 grant set — never a blanket REVOKE ALL.
- NO CASCADE on any REVOKE or DROP (carries the v0.2/v0.3 no-CASCADE rule).
- every step GATED: precondition asserted before it runs; abort+escalate on
  any gate miss (a role that owns something or has members is NOT force-dropped).
- idempotent intent: REVOKE is safe if a grant was never applied (partial-
  abort path still converges); DROP is gated by RB-4.

§2 — The Rollback Artefact (verbatim; NOT executed)

-- ============================================================================
-- dot-iu-cutter v0.4 — credential dry-run ROLLBACK DRAFT (r1, NOT EXECUTED)
-- Apply target: ISOLATED ephemeral env ONLY. Exact inverse of SQL draft §3.
-- ============================================================================

-- ---- RB-1  e-stop (fast containment; reversible; no privilege change) -------
ALTER ROLE cutter_exec   NOLOGIN;
ALTER ROLE cutter_verify NOLOGIN;

-- ---- RB-2  terminate live writer backends so REVOKE/DROP is not blocked -----
SELECT pg_terminate_backend(pid)
  FROM pg_stat_activity
 WHERE usename IN ('cutter_exec','cutter_verify')
   AND pid <> pg_backend_pid();

BEGIN;

-- ---- RB-3  REVOKE the EXACT grant set (inverse of SQL draft §3) -------------

-- cutter_exec column-scoped UPDATEs
REVOKE UPDATE (status) ON cutter_governance.decision_backlog_entry FROM cutter_exec;
REVOKE UPDATE (superseded_by_review_decision_id)
                       ON cutter_governance.review_decision         FROM cutter_exec;
-- cutter_exec table privileges
REVOKE SELECT, INSERT ON cutter_governance.decision_backlog_entry     FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.decision_backlog_history    FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.decision_backlog_dependency FROM cutter_exec;
REVOKE INSERT         ON cutter_governance.decision_backlog_sweep_log  FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.manifest_envelope          FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.manifest_unit_block        FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.review_decision            FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.cut_change_set             FROM cutter_exec;
REVOKE INSERT         ON cutter_governance.cut_change_set_affected_row FROM cutter_exec;
REVOKE SELECT, INSERT ON cutter_governance.dot_pair_signature         FROM cutter_exec;

-- cutter_verify column-scoped UPDATE
REVOKE UPDATE (status) ON cutter_governance.decision_backlog_entry FROM cutter_verify;
-- cutter_verify table privileges
REVOKE SELECT, INSERT ON cutter_governance.decision_backlog_entry     FROM cutter_verify;
REVOKE SELECT, INSERT ON cutter_governance.decision_backlog_history    FROM cutter_verify;
REVOKE SELECT, INSERT ON cutter_governance.dot_pair_signature         FROM cutter_verify;
REVOKE SELECT, INSERT ON cutter_governance.cut_change_set             FROM cutter_verify;
REVOKE SELECT, INSERT ON cutter_governance.cut_change_set_affected_row FROM cutter_verify;
REVOKE SELECT, INSERT ON cutter_governance.verify_result              FROM cutter_verify;
REVOKE SELECT         ON cutter_governance.manifest_envelope          FROM cutter_verify;
REVOKE SELECT         ON cutter_governance.manifest_unit_block        FROM cutter_verify;
REVOKE SELECT         ON cutter_governance.review_decision            FROM cutter_verify;

-- schema usage
REVOKE USAGE ON SCHEMA cutter_governance FROM cutter_exec;
REVOKE USAGE ON SCHEMA cutter_governance FROM cutter_verify;

COMMIT;

-- ---- RB-4  GATE before DROP (assert per role; abort if ANY fails) ----------
-- (a) MEMBERLESS:
--   SELECT count(*) FROM pg_auth_members m
--     JOIN pg_roles r ON r.oid IN (m.roleid, m.member)
--    WHERE r.rolname IN ('cutter_exec','cutter_verify');           -- expect 0
-- (b) OWNS NOTHING:
--   SELECT count(*) FROM pg_shdepend s
--     JOIN pg_roles r ON r.oid = s.refobjid
--    WHERE r.rolname IN ('cutter_exec','cutter_verify')
--      AND s.deptype = 'o';                                        -- expect 0
-- (c) NO PRIVILEGE LEFT (post RB-3, aclexplode scan over all
--     cutter_governance objects + nspacl): 0 tuple for either role.
-- If (a) OR (b) OR (c) != clean  ->  STOP, DO NOT DROP, escalate.

-- ---- RB-5  DROP only if RB-4 all-pass (plain DROP; never CASCADE) ----------
DROP ROLE cutter_exec;
DROP ROLE cutter_verify;
-- NEVER: DROP ROLE ... CASCADE / DROP OWNED BY / REASSIGN OWNED.

-- ---- RB-6  post-rollback baseline assertions (run by verification §5) ------
-- (see verification plan RBV-1..RBV-6)

-- ---- RB-7  secret rollback (N/A this cycle) -------------------------------
-- In the dry-run, "secrets" are throwaway tokens destroyed with the env.
-- In a future EXECUTION cycle, the operator zeroises the corresponding .env
-- keys here; no secret value is ever logged. THIS cycle creates none.

§3 — Explicit Rollback Gates

G-RB-1 scope = credentials only (no data/table/view/cutter_ro/Directus/RLS).
G-RB-2 NO CASCADE on any REVOKE or DROP; no DROP OWNED / REASSIGN OWNED.
G-RB-3 DROP ROLE only if memberless AND owns nothing AND no privilege left
       (RB-4 (a)(b)(c) all clean) — else STOP + escalate, leave role intact.
G-RB-4 cutter_ro byte-identical before/after (v0.3 inventory §4: NOLOGIN,
       13 grants, 0 base-table grant, 0 write).
G-RB-5 prod sysid identical before/after; 0 rows unchanged; env then torn down.
G-RB-6 structural / aclexplode catalog assertions only (no bare-string
       false-negative — feedback memory pg_get_constraintdef lesson).
G-RB-7 partial-abort safe: if SQL draft aborted mid-grant, RB-3 (idempotent
       per object) + RB-4-gated RB-5 still converge to clean baseline.

§4 — Non-Scope

NOT here (and never in this cycle): executing any REVOKE/DROP/ALTER ROLE,
any .env change, any production connection, any CASCADE, any cutter_ro /
view / base-table / Directus / RLS mutation. Target runbook specification
only; executed nowhere by this document.

End of credential dry-run rollback draft (authoring only; nothing executed).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.4-credential-authoring/dot-iu-cutter-v0.4-credential-dry-run-rollback-draft-2026-05-16.md