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).