KB-6275

dot-iu-cutter v0.4 — DB Adapter Error & Rollback Design (design only)

11 min read Revision 1
dot-iu-cutterdieu44v0.4db-adapterdesign-onlyerror-handlingrollbacksqlstate

dot-iu-cutter v0.4 — DB Adapter Error & Rollback Design

document_path: knowledge/dev/laws/dieu44-trien-khai/v0.4-db-adapter-design/dot-iu-cutter-v0.4-db-adapter-error-and-rollback-design-2026-05-17.md
revision: r1
date: 2026-05-17
author: Agent (Claude Code CLI, Opus 4.7 1M)
phase: v0.4 — REAL DB ADAPTER DESIGN (companion to design-master)
status: design_only_pending_gpt_review

⛔ DESIGN ONLY. No connection, no error actually raised, no rollback run. The SQLSTATE policy below is a target classification, not executed.


§1 — Failure Taxonomy → Disposition (authoritative)

SQLSTATE / condition          class        disposition
─────────────────────────────────────────────────────────────────────────────
42501 insufficient_privilege  PRIVILEGE    STOP immediately. ROLLBACK whole
                                            phase. Emit a high-severity signal
                                            (local/test signal channel, doc:
                                            skeleton OD-4). NEVER retry. NEVER
                                            attempt privilege escalation /
                                            alternate role / GRANT. This means
                                            the agent tried a write outside the
                                            matrix → routing/design bug
                                            (principal-routing doc R-3). Human/
                                            GPT must fix the adapter, not the
                                            grants-at-runtime.
23505 unique_violation        IDEMPOTENCY  Treat as CONVERGENCE, not failure
  (on an idempotency/natural   COLLISION   IF the colliding key is a known
   key)                                     idempotency key: ROLLBACK, then
                                            SELECT the existing row and RETURN
                                            it (dedup / resume). Phase outcome =
                                            success (no duplicate, no double-
                                            apply). If the unique collision is
                                            NOT on a recognised idempotency key
                                            → treat as design bug → STOP.
23503 foreign_key_violation   STRUCTURAL   STOP. ROLLBACK whole phase. This is
23502 not_null_violation      DESIGN BUG   a design bug or invalid input
23514 check_violation         / BAD INPUT  (no CHECK exists in schema, but
22xxx data_exception                        defensive). NO retry. NEEDS_HUMAN
                                            escalation. Do NOT auto-mutate
                                            input to "make it fit".
40001 serialization_failure   TRANSIENT    Bounded retry of the WHOLE phase
40P01 deadlock_detected       (RETRYABLE)  txn (idempotent → safe). Exponential
55P03 lock_not_available                    backoff + jitter; max_attempts
57014 query_canceled (timeout)              configurable; attempt_no recorded
                                            in existing payload/body column.
                                            On exhaustion → escalate (see §4).
53300 too_many_connections    BACKPRESSURE Bounded retry with longer backoff
53400 conn limit reached                    (respect CONNECTION_LIMIT 2; never
                                            open a 3rd). On exhaustion →
                                            escalate; do NOT widen the limit.
08xxx connection_exception     CONNECTION   The txn is already aborted server-
  (08000/08003/08006/08001/                 side → NO partial commit possible
   08004)                                    (P-7). Discard the connection,
                                            bounded retry the WHOLE phase from
                                            its last committed boundary. On
                                            persistent failure → fail closed +
                                            escalate (no half-written phase).
28P01 invalid_password        CREDENTIAL   STOP. Do NOT retry (retry won't fix
28000 invalid_authorization                 a bad/rotated credential and may
                                            lock/alarm). Fail closed, emit
                                            signal referencing the KEY NAME
                                            only (never the value). Likely a
                                            rotation/desync → human/GPT + a
                                            separate credential cycle.
missing/empty required env    CONFIG       Fail closed BEFORE any connect
  key                          (FAIL-      (doc 2 L-3). Typed ConfigMissing
                               CLOSED)      naming the missing KEY. No default,
                                            no fallback host/password. No
                                            partial work. Not retryable.
semantic verification         NEEDS_HUMAN  NOT a DB error. This is VERIFY's
  mismatch (outcome=fail)                   designed FAIL path: compensating
                                            change set + escalation entry +
                                            status verify_failed_escalated
                                            (transaction-mapping §5). A human/
                                            GPT loop owns the escalation entry.
unknown / unmapped SQLSTATE   CONSERVATIVE Treat as STOP (not retry): ROLLBACK,
                                            escalate, surface the SQLSTATE.
                                            Fail safe, never guess-retry.

§2 — STOP vs RETRY vs RESUME vs ESCALATE (decision rule)

RETRY (bounded)  : ONLY transient classes (40001/40P01/55P03/57014/53300/
                   53400/08xxx). Whole-txn replay; idempotency keys guarantee
                   convergence; bounded attempts; backoff+jitter.
RESUME / DEDUP   : 23505 on a recognised idempotency/natural key → return the
                   existing row; phase succeeds without a new write.
STOP (no retry)  : 42501, 23503, 23502, 23514, 22xxx, 28xxx, ConfigMissing,
                   unknown SQLSTATE, any guard-precondition failure. ROLLBACK,
                   surface, do not loop.
ESCALATE         : retries exhausted, or a STOP that represents stuck work →
                   write an escalation decision_backlog_entry (kind=
                   'escalation', status='marked') + its history so a human/
                   GPT loop owns it. The agent NEVER silently drops work.
NEEDS_HUMAN      : semantic verify mismatch + every ESCALATE → flagged for
                   the human/GPT loop; no autonomous "fix and continue".

§3 — Rollback Semantics (two distinct layers)

DB-LEVEL (within a phase):
  - any exception inside transaction() → adapter issues ROLLBACK; the phase
    leaves ZERO trace (P-3/P-7; mirrors skeleton transaction() except-path).
  - connection loss mid-txn → server aborts the txn; client treats it as a
    clean ROLLBACK (no partial commit is physically possible — single
    BEGIN…COMMIT, no intermediate visibility).
  - the adapter NEVER issues DELETE/TRUNCATE/DDL to "clean up" — it has no
    such surface (AppendOnlyViolation, skeleton-enforced).
SEMANTIC-LEVEL (a committed CUT later judged wrong by VERIFY):
  - NO physical undo. A FORWARD compensating cut_change_set (+ affected_row)
    is INSERTed; verify_result.rollback_change_set_id_triggered points at it;
    an escalation entry is created; status → verify_failed_escalated.
  - rationale: cutter_governance is an append-only ledger — truth is "what
    happened", corrected by further recorded events, never erased.
EMERGENCY (operational, NOT an adapter action):
  - credential kill switch is the EXISTING rollback artefact from the
    credential cycle (ALTER ROLE … NOLOGIN, sha fcba5629…2b14) — an
    out-of-band ops action, NOT something the adapter performs. The adapter
    has no role-altering capability.
no_partial_commit_guarantee: because each phase is exactly one txn (txn
  doc TX-1/TX-4), a retry always restarts from a consistent committed
  boundary; there is never a "half phase" to reconcile.

§4 — Escalation Path (no silent drop)

trigger: retries exhausted | STOP-class on stuck work | semantic verify fail.
action: INSERT a decision_backlog_entry(kind='escalation', status='marked')
  + its ∅→marked history (under the principal that owns that phase per
  routing doc — VERIFY's fail-path escalation is cutter_verify, granted).
  The original entry's status moves to its *_failed / verify_failed_escalated
  state with a history row recording reason + the SQLSTATE class (NOT the
  secret, NOT raw credential text).
ownership: the escalation entry re-enters the backlog and is swept like any
  work item; a human/GPT loop decides the next move. The agent does not
  self-resolve an escalation.
signal: a typed local/test signal (skeleton OD-4 channel) is emitted for
  PRIVILEGE / CREDENTIAL / unknown-SQLSTATE / exhausted-retry so operators
  see it promptly. Signal payload carries class + entry_id, never secrets.

§5 — No-Leak Discipline In Error Paths (hard)

- exception messages, log lines, signal payloads, escalation reason text and
  history rows reference: SQLSTATE, error CLASS, table/phase, entry_id, and
  env KEY NAMES — NEVER a password value, NEVER a full DSN, NEVER connection
  string bytes.
- the adapter's repr()/str() and any captured stack frame must not render
  the password (doc 2 L-4); connect kwargs are passed discretely, not as a
  URL, so no single loggable secret token exists.
- a 28xxx credential error logs "auth failed for principal cutter_exec
  (key DOT_CUTTER_EXEC_DB_PASSWORD)" — name only.

§6 — Open Decisions (this doc)

DA-13 retry bounds defaults: max_attempts + backoff/jitter values (config,
  not hardcoded) — propose 5 attempts, base 200ms, cap 5s, full jitter.
DA-14 53300 backpressure: retry-with-long-backoff (recommended) vs immediate
  escalate — recommend bounded retry then escalate.
DA-15 escalation entry under VERIFY fail uses cutter_verify (granted) —
  confirm acceptable that the verifier creates the escalation entry (it
  CANNOT author its review/manifest, SoD intact — principal-routing SoD-3).
DA-16 unknown-SQLSTATE policy = STOP+escalate (recommended) vs one bounded
  retry then STOP.

End of DB adapter error & rollback design (design only; no error raised; no rollback run; no connection).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.4-db-adapter-design/dot-iu-cutter-v0.4-db-adapter-error-and-rollback-design-2026-05-17.md