dot-iu-cutter v0.4 PG-backed Dry-run — Design Master (2026-05-17)
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-slimharness container ondr-net-v0.4(preferred) or a disposable host venv under the throwaway work dir. Pinpsycopg[binary]==<pinned>(recorded in command-review); not vendored, not installed intoincomex-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_agentpackage read-only viasys.pathfrom/opt/incomex/dot/iu-cutter, constructs twoRealPostgresAdapterinstances (cutter_exec,cutter_verify) with an explicit dry-runenv=mapping (passed as a dict — so no real.env/prodos.environis read) and the default psycopg3 provider, and drives the MARK→REVIEW→CUT→VERIFY ledger sequence through the already-accepted, adapter-agnosticLedgerWriter(mirroringphases.pylogic). 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_result → PrincipalCapabilityError before SQL |
| S9 | 42501 deny proof | server backstop | controlled matrix-denied raw INSERT (cutter_verify→review_decision) → server 42501 → classify=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-slimcontainer ondr-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-onlypg_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).