KB-30D0

dot-iu-cutter v0.5 WS-Q5 Registry Substrate — Verification Plan (catalog-level; authoring only)

10 min read Revision 1
dot-iu-cutterv0.5ws-q5registry-substrateverification-plancatalog-levelauthoring-onlydieu442026-05-18

dot-iu-cutter v0.5 WS-Q5 Registry Substrate — Verification Plan

Phase: v0_5_WS_Q5_registry_substrate_DDL_authoring · Nature: executable_DDL_authoring_only__no_execution · Date: 2026-05-18 Verifies: …-WS-Q5-registry-substrate-DDL-draft-2026-05-18.sql.md

⚠️ GATING BANNER

phase: executable_DDL_authoring_only
verification_executed: false       # this is the PLAN of the checks, NOT a run
checks_run: 0
verification_method: catalog-level ONLY  (information_schema / pg_catalog)
rendered_string_equality: FORBIDDEN  (carry C-07 / v0.3 false-negative lesson)
execution_authorized: false
self_advance: PROHIBITED

Every check below is a catalog-level structural assertion (system catalogs / information_schema), never pg_get_*def() rendered-string equality. Outcome vocabulary: PASS | FAIL(detail). Nothing is run here (QG4).


1. Pre-apply baseline (capture before any future apply)

B-1  cutter_governance has exactly its existing 12 tables; the 12 WS-Q5 names
      are ABSENT (pg_class/pg_namespace). [negative precondition]
B-2  record production sysid + existing PK/FK counts (12 PK / 19 FK) for
      before==after comparison.
B-3  no role/privilege baseline change expected (no GRANT authored).

2. Table existence (catalog)

TV-1  exactly 12 NEW tables present in schema cutter_governance:
        matcher_config_registry, address_template_registry, grammar_profile,
        grammar_profile_level, grammar_profile_status_marker,
        source_family_registry, source_document_registry,
        source_document_version_registry, entity_kind_registry,
        entity_reference_registry, authority_override, metadata_key_registry
      (pg_class JOIN pg_namespace WHERE nspname='cutter_governance').
TV-2  each new table relkind='r' (ordinary table), not view/matview/partition.
TV-3  cutter_governance total table count = previous 12 + 12 = 24 (no more, no less).

3. Columns / types / nullability (catalog — information_schema.columns)

CV-1  each table's column SET matches the DDL draft exactly (no extra/missing
      column) — compare column NAME set per table from information_schema.columns.
CV-2  data_type per column matches intent: text -> 'text', timestamptz ->
      'timestamp with time zone', jsonb -> 'jsonb', boolean -> 'boolean',
      integer -> 'integer' (information_schema.columns.data_type; NOT a DDL
      string compare).
CV-3  is_nullable correctness (spot-set, catalog-driven):
        NOT NULL: all PK cols; matcher_config_registry.matcher_definition;
          *_registry.registered_by/registered_at; lifecycle cols;
          authority_override.scope/authority_role/set_by/set_at;
          metadata_key_registry.key_namespace/key_type/cardinality_policy/
          mutability_policy/index_policy/owner_role/created_by/created_at;
          address_template_registry.{template_pattern,docprefix_separator,
          level_separator,encodes_status}.
        NULLABLE (DEFERRED/optional): entity_reference_registry.
          permission_policy_ref, snapshot_policy_ref; authority_override.
          iu_id, span_ref, reason, provenance;
          source_document_version_registry.{source_format,authoritative_version,
          version_status,provenance}; display_*/description cols.
CV-4  NO column has a DEFAULT (information_schema.columns.column_default IS NULL
      for all new columns) — additive-discipline assertion.

4. Constraints — PK / FK / UNIQUE (catalog — pg_constraint)

KC-1  exactly 12 PRIMARY KEY constraints, deterministic names pk_<table>,
      each on the intended column(s):
        pk_grammar_profile_level (grammar_profile_ref, level_seq),
        pk_grammar_profile_status_marker (grammar_profile_ref, marker),
        others single-column as drafted.
KC-2  exactly 8 FOREIGN KEY constraints, exact names + exact referenced
      table/column, compared via pg_constraint (conrelid/confrelid/conkey/
      confkey resolved to names — STRUCTURAL, not pg_get_constraintdef text):
        fk_grammar_profile_address_template_ref -> address_template_registry
        fk_grammar_profile_level_profile        -> grammar_profile
        fk_grammar_profile_level_matcher        -> matcher_config_registry
        fk_gpsm_profile                         -> grammar_profile
        fk_source_family_registry_grammar_profile -> grammar_profile
        fk_source_document_registry_family      -> source_family_registry
        fk_sdvr_source_document                 -> source_document_registry
        fk_entity_reference_registry_kind       -> entity_kind_registry
KC-3  every FK is schema-qualified to cutter_governance on BOTH sides
      (confrelid namespace = cutter_governance) — explicitly assert the
      schema, since the C-07 false-negative arose from an unqualified compare.
KC-4  exactly 4 UNIQUE constraints, exact names + exact column set:
        uq_grammar_profile_level_name (grammar_profile_ref, level)
        uq_source_document_registry_docprefix (address_docprefix)
        uq_sdvr_doc_checksum (source_document_ref, content_checksum)
        uq_entity_reference_registry_natural (entity_kind, source_system, natural_key)
KC-5  FK confdeltype/confupdtype = 'a' (NO ACTION) for all 8 — i.e. NO
      CASCADE/SET NULL anywhere (negative check).
KC-6  ZERO CHECK constraints and ZERO trigger objects on the 12 new tables
      (pg_constraint contype='c' count = 0; pg_trigger count = 0) — confirms
      the documented "no CHECK/trigger" authoring decision.

5. Deterministic naming

NM-1  all constraint names match the deterministic patterns
      pk_<table> / fk_<table>_<ref> / uq_<table>_<cols>; no system-generated
      constraint names ($-suffixed) present (pg_constraint.conname scan).
NM-2  all object names lowercase snake_case; no quoted mixed-case identifiers.

6. Canonical-address separator policy (BR-A1 LOCKED)

AC-1  address_template_registry has columns docprefix_separator,
      level_separator, encodes_status with the nullability of CV-3 — the
      structural carrier of BR-A1 exists.
AC-2  POLICY (value-level, checked at SEED command-review, NOT here): every
      seeded address_template row MUST have docprefix_separator='/',
      level_separator='-', encodes_status=false. Flagged: enforced via
      governed seed + verification, NOT via CHECK (BATCH-1 precedent) — this
      is a declared design decision, see design-delta.
AC-3  no canonical address is computed/stored by this DDL (registries only) —
      negative assertion: no address data path created here.

7. No-hardcode policy

NH-1  matcher rule lives in matcher_config_registry.matcher_definition (jsonb
      column exists) — i.e. the schema FORCES matcher-as-data, no inline-regex
      column shape that would invite literals.
NH-2  vocab-like keys (source_family, entity_kind, metadata_key, matcher_ref,
      grammar_profile_ref, address_template_ref) are PRIMARY KEYS of their own
      registry tables -> resolvable only via registry, never a code literal
      (structural anti-hardcode assertion).
NH-3  no enum type created (pg_type typtype='e' count for new objects = 0);
      controlled vocabularies are text + documented values (BATCH-1 pattern),
      not PG enums -> additive + evolvable without enum migration.

8. No unintended objects / additive-only

AO-1  diff(cutter_governance objects, baseline B-1) = EXACTLY the 12 tables +
      their 12 PK + 8 FK + 4 UNIQUE constraints — nothing else
      (no view, sequence, function, type, index beyond constraint-backed).
AO-2  the existing 12 tables: column sets, PKs, FKs UNCHANGED vs B-2
      (no ALTER side-effect). [negative check]
AO-3  no DROP/ALTER on any pre-existing object occurred (additive-only).
AO-4  production sysid B-2 == post (registry apply does not touch identity).
AO-5  zero rows in all 12 new tables immediately post-apply (no DML seed in
      this package) — registries are empty until a separate seed cycle.

9. Negative checks (must FAIL the apply if true)

NG-1  any of the 12 names already existed pre-apply with a DIFFERENT shape
      -> FAIL (plain CREATE TABLE aborts; conflict surfaced, not hidden).
NG-2  any FK resolves to a table OUTSIDE cutter_governance -> FAIL
      (no cross-schema FK permitted — v0.2 doctrine).
NG-3  any CASCADE / SET NULL / SET DEFAULT referential action present -> FAIL.
NG-4  any CHECK, trigger, DEFAULT, sequence, or enum type created -> FAIL
      (out of authored scope).
NG-5  any GRANT / role / ownership change detected -> FAIL (privilege model is
      a separate sovereign cycle; none authored).
NG-6  any row present in a new table post-apply -> FAIL (no seed authorized).
NG-7  any ALTER to an existing cutter_governance table -> FAIL.

10. Statements

  • QG4: every check is catalog-level (pg_catalog / information_schema), zero pg_get_*def() rendered-string equality; negative checks included (§9). QG2: nothing executed — this is the plan only.
  • KC-3 explicitly hard-codes the schema-qualified comparison to prevent recurrence of the C-07 / v0.3 false-negative.
  • No repo/VPS access in this session. code_changed: false, commit_made: false.
  • Self-advance PROHIBITED — doc 3 of 5; STOP after package complete → route GPT/User.

Companion files: DDL-draft, rollback-draft, design-delta-and-open-decisions, DDL-authoring-report.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.5-ws-q5-registry-substrate-ddl-authoring/dot-iu-cutter-v0.5-WS-Q5-registry-substrate-verification-plan-2026-05-18.md