KB-122D

dot-iu-cutter v0.4 PG-backed Dry-run — Design Master (2026-05-17)

9 min read Revision 1
dot-iu-cutterv0.4db-adapterdry-rundesigndieu44

dot-iu-cutter v0.4 — PG-backed Dry-run DESIGN MASTER

Date: 2026-05-17 · Phase: v0.4 PG-backed dry-run DESIGN / COMMAND-REVIEW ONLY (nothing executed) Subject code: RealPostgresAdapter @ accepted commit 56d3732cb74d07546c938242180a434ed1067a9a (FINAL CODE PASS, defects_found=false, 92/92). Boundaries: no dry-run execution, no production connection, no production secret read, no .env edit, no code commit, no production row writes, no CUT/VERIFY in production, no deploy, no self-advance.

1. Purpose

Prepare (not run) the first PostgreSQL-backed dry-run that exercises the accepted RealPostgresAdapter against a restored, isolated copy of the production schema, proving the adapter behaves correctly over a real psycopg3 connection without ever touching production, secrets, or the live runtime.

2. Environment topology (proposed)

Component Proposal Rationale / boundary
Isolated DB container pg-dry-run-v0.4-db-adapter-2026-05-17, image postgres:16 matches prod PG 16.13; unique name (collision-free vs the 3 protected prior dry-run containers pg-dry-run-v0.2-p0-2-2026-05-16, pg-dry-run-v0.2-phase-alpha-2026-05-16, pg-dry-run-hb05-2026-05-15)
Network dedicated user bridge dr-net-v0.4-2026-05-17 NO -p host port published (boundary honoured); harness reaches DB by container DNS on this net only
Superuser pw POSTGRES_PASSWORD = random dry-run-only value generated in-env never a production value, never printed
DB name directus (restored) identity assertion + adapter DOT_CUTTER_DB_NAME parity
Source data fresh logical backup of prod directus via pg_dump (read-only) run inside the prod postgres container as workflow_admin (rolsuper; directus role insufficient — prior-cycle fact) pg_dump is read-only; prod never written/restarted
Roles plain pg_dump omits CREATE ROLE (Note-N1 pattern, v0.2/v0.3). Create dry-run-equivalent cutter_exec / cutter_verify fresh in-env with dry-run-only passwords + reapply the exact frozen privilege matrix no prod SCRAM/secret imported; role names identical so the adapter's SELECT current_user identity assertion passes
sysid gate assert pg_control_system().system_identifier of DR env ≠ PROD 7611578671664259111 before any harness write logical restore keeps the container's own (fresh) sysid → naturally distinct
Disk ~2 GB footprint; host has 32 GB free (68% used) pre-restore df gate

3. psycopg3 strategy

  • Install only in a throwaway context: ephemeral python:3.12-slim harness container on dr-net-v0.4 (preferred) or a disposable host venv under the throwaway work dir. Pin psycopg[binary]==<pinned> (recorded in command-review); not vendored, not installed into incomex-directus/incomex-agent-data/host site-packages, no service restart.
  • VPS host has python 3.12.3 + venv + pip 24.0 (verified) — feasible. Disposed entirely at teardown.

4. Runtime wiring (minimal harness — NO production binding)

  • Dry-run-only artefact dr_harness_v0_4.py (sha-gated, lives in throwaway work dir, NOT committed to the iu-cutter package; phases.py / db_adapter.py UNCHANGED).
  • It imports the accepted cutter_agent package read-only via sys.path from /opt/incomex/dot/iu-cutter, constructs two RealPostgresAdapter instances (cutter_exec, cutter_verify) with an explicit dry-run env= mapping (passed as a dict — so no real .env/prod os.environ is read) and the default psycopg3 provider, and drives the MARK→REVIEW→CUT→VERIFY ledger sequence through the already-accepted, adapter-agnostic LedgerWriter (mirroring phases.py logic).
  • CutterRuntime (InMemory-bound) is not used; no service, no deploy, no persistent code change.

5. Test scenario catalogue (the 12 required + verification)

# Scenario Principal / phase Expected
S1 Config load success (dry-run env) exec & verify ConnectionConfig built; no connect yet
S2 Missing key fail-closed exec drop one DR key → ConfigMissing naming KEY, no socket
S3 current_user identity assertion exec/verify connect → SELECT current_user == bound principal OK; negative → ConfigMismatch, no write
S4 MARK cutter_exec / READ COMMITTED 1 txn; decision_backlog_entry+decision_backlog_history (+dependency/sweep_log per phases) inserted
S5 REVIEW cutter_exec / READ COMMITTED manifest_envelope+manifest_unit_block+review_decision; status CAS→reviewed; history
S6 CUT cutter_exec / SERIALIZABLE dot_pair_signature+cut_change_set (verifier_signature_id NULL)+cut_change_set_affected_row; status→cut_applied; history
S7 VERIFY cutter_verify / SERIALIZABLE separate connection; dot_pair_signature+verify_result(pass); status→verified_complete; history
S8 Principal mismatch refusal cross verify-bound→CUT, exec→INSERT verify_resultPrincipalCapabilityError before SQL
S9 42501 deny proof server backstop controlled matrix-denied raw INSERT (cutter_verify→review_decision) → server 42501classify=STOP → PhaseStop, rollback, no privilege escalation
S10 Idempotency replay cutter_exec replay MARK w/ same idempotency_key → read-before-write find() returns existing; no duplicate; IdempotencyResume only on PK collision (schema has NO unique idx on payload key — frozen inventory: no CHECK/trigger/DEFAULT/enum)
S11 Txn rollback on induced failure cutter_exec exception mid-phase → whole-phase ROLLBACK, table row-counts unchanged (atomicity)
S12 No DELETE/TRUNCATE/DDL/GRANT surface both delete()/truncate()AppendOnlyViolation; harness captures every executed SQL → only SET/SELECT/INSERT/UPDATE; zero DELETE/TRUNCATE/DROP/ALTER/GRANT/CREATE/COPY
V Post-run verification 12-table catalog inventory, per-scenario row-count matrix, privilege-matrix set-equality, no-prod-touch, secret-leak scan, redacted structured logs

6. Data lifecycle

Hybrid: negative/atomicity scenarios (S2, S3-neg, S8, S9, S11) roll back to zero in-txn; happy-path (S4–S7, S10) rows persist inside the isolated env for inspection, then the entire isolated env is destroyed at teardown → net-zero on host & prod. No selective DELETE/TRUNCATE (append-only invariant preserved — env destruction, not row deletion, is the cleanup).

7. Conformance to accepted design

Routing (MARK/REVIEW/CUT→cutter_exec, VERIFY→cutter_verify), isolation (RC vs SERIALIZABLE), SQLSTATE map (42501 STOP / 23505 RESUME / transient retry / unknown STOP), _Secret redaction, no-DSN discrete kwargs, fail-closed — all assertions trace to the accepted code at 56d3732 and its 47 unit tests; the PG-backed dry-run is the live confirmation of the same contracts.

8. Open decisions for GPT (DR-1 … DR-8)

  • DR-1 Role strategy: create dry-run-equivalent roles + reapply matrix (recommended) vs pg_dumpall --globals-only (rejected — imports prod SCRAM).
  • DR-2 Harness locus: ephemeral python:3.12-slim container on dr-net-v0.4 (rec) vs disposable host venv.
  • DR-3 Data lifecycle: hybrid rollback-negatives / persist-happy-then-destroy-env (rec) vs full per-scenario rollback-to-zero.
  • DR-4 Idempotency framing: confirm schema has no unique index on the payload idempotency key (frozen inventory: no CHECK/trigger/DEFAULT/enum) ⇒ dedup is find() read-before-write; 23505 path only on PK collision — GPT ack of test framing requested.
  • DR-5 42501 proof method: controlled matrix-denied raw INSERT capturing server SQLSTATE, distinct from the in-code capability guard (rec).
  • DR-6 sslmode: DR env DOT_CUTTER_DB_SSLMODE=disable (no TLS in throwaway container; equals the LIVE FR-1 value); prod-intent TLS revisited at runtime-binding — confirm acceptable for dry-run.
  • DR-7 Backup principal: workflow_admin (rolsuper) read-only pg_dump — confirm.
  • DR-8 Retention: keep sha-gated SQL + redacted logs in KB; shred dry-run env file + venv + container/volume/network — confirm.

9. Out of scope (explicit)

No production connection, no prod secret read, no .env edit, no code commit, no CUT/VERIFY in production, no deploy/restart, no runtime binding of CutterRuntime, no self-advance. Execution of this plan requires a separate explicit authorization after GPT review of this package.

Cross-refs: command-review, verification-plan, rollback-plan, risk-review, report (same folder, dated 2026-05-17).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.4-db-adapter-dry-run/dot-iu-cutter-v0.4-pg-backed-dry-run-design-master-2026-05-17.md