KB-21B0

06 - Read-only / Live Dry-run Smoke Result (O6B)

5 min read Revision 1
dot-iu-cutterv0.6O6BG6dryrunreadonlysmokesub-gap

06 - Read-only / Live Dry-run Smoke Result

O6B · doc 6 of 8 · 2026-05-21 · Gate G6 — read-only live dry-run smoke. No production mutation. No execution_enabled flip. Honest partial result with one clearly-scoped sub-gap (no fake PASS).

1. G6a — orchestrator Mode.DRYRUN path (proven via tests)

evidence:  the 366/366 Contabo unittest run (doc 05 §5) includes
             tests/test_orchestrator_o3_live_readonly.py
             tests/test_orchestrator_o4_live_dryrun.py
behaviour: these exercise the orchestrator in Mode.DRYRUN end-to-end
           (SG1 pause -> resume -> SG2 pause -> resume -> closeout)
           against the InMemoryDiscoverer test seam.
verdict:   orchestrator Mode.DRYRUN code path PASS on Contabo Python 3.12.3

2. G6b — live read-only DB reachability (executed, safe)

Channel: the sanctioned query_pg MCP — structurally read-only by construction (AST-validated, executed in a READ ONLY transaction as a read-only role, statement_timeout 5s, hard LIMIT 500, no writes/DDL). No DSN value was ever read or logged by this macro.

database:        directus
connected_role:  context_pack_readonly   (the designated read-only role)
txn_mode:        READ ONLY   (tool-enforced)
mutation:        STRUCTURALLY IMPOSSIBLE via this channel

substrate probed (read-only counts):
  public.iu_lifecycle_log    : 60 rows
  public.iu_lifecycle_vocab  :  4 rows
  public.law_registry        : 47 rows
  (public schema also exposes law_catalog, law_jurisdiction,
   law_dot_enforcement, kg_source_authority, context_trigger_sources,
   iu_notification_event/read, law_version_verification_log)

privilege finding:
  cutter_governance schema is INVISIBLE to context_pack_readonly
  (information_schema reports 0 schemas / 0 tables for it). The schema
  IS provisioned (O5/O6 surveys) — the read-only role simply lacks
  USAGE on it. The orchestrator's governance-record discovery would
  need a differently-privileged read-only DSN.

verdict:  live substrate reachable read-only, zero mutation -> PASS

3. G6c — full orchestrator-driven dry-run vs the LIVE production DB

status:  NOT RUN — reported as a scoped sub-gap (SUBGAP-O6B-LIVEDRYRUN)
reason:  running the v0.6 orchestrator's LiveDryRunDiscoverer against the
         real directus production DB was judged UNSAFE / out-of-mandate
         for O6B, for four concrete reasons:

  1. NO CLI surface: cli.py at 6625f76 has no `orchestrate` subcommand
     (doc 05 §7). Driving the orchestrator against a live DB would
     require AUTHORING an unreviewed Python driver script — outside the
     O6B mandate and adjacent to the "no source reconstruction" rule.

  2. SECRET DSN required: LiveDryRunDiscoverer needs a real production
     DB DSN. Reading it risks secret exposure; the macro forbids logging
     secrets AND forbids asking the User to supply secrets. The safe
     read-only channel actually used (query_pg MCP) never exposes a DSN.

  3. GOVERNANCE ROLE GAP: the read-only role reachable safely
     (context_pack_readonly) cannot see cutter_governance (§2). A full
     orchestrator discovery needs governance-table read access — a
     separate, differently-privileged credential.

  4. TARGET DOCUMENT selection is an O7/O8-class decision, not O6B's.

why_not_a_fake_pass: |
  G6 PASS criteria explicitly say "read-only live dry-run smoke PASS if
  safe; if not safe, report the sub-gap clearly but do NOT fake PASS."
  The full live-DB orchestrator dry-run was not safe to run here, so it
  is reported, not faked. The safe portion (G6a + G6b) genuinely passed.

note:  this smoke needed NEITHER mutation NOR execution_enabled — so it
       does NOT trip the macro's BLOCKED triggers. It is a conditional
       G6 sub-gap, routed to GPT/User, to be closed by macro O7.

4. Non-mutation guarantee for the whole gate

production_mutation:  NONE
  - query_pg channel is READ ONLY by construction
  - only SELECT statements issued (counts + information_schema)
  - no INSERT/UPDATE/DELETE, no DDL, no fn_iu_create/fn_iu_enact
Mode.LIVE:            still structurally refused (execution_enabled=False)
execution_enabled:    False throughout

5. Result

G6_verdict:  PARTIAL PASS (honest split, no fake PASS)
  G6a orchestrator Mode.DRYRUN path .......... PASS (via O3/O4 tests)
  G6b live read-only DB reachability ......... PASS (query_pg, READ ONLY)
  G6c orchestrator dry-run vs live prod DB ... SUB-GAP (SUBGAP-O6B-LIVEDRYRUN)
sub_gap_owner:  macro O7 (post-deploy live dry-run on Contabo)
proceed_to:     G7 rollback/disable proof
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-o6b-devhost-deploy-postdeploy-smoke/06-readonly-dryrun-smoke-result-2026-05-21.md