KB-66E2

Lifecycle DDL Ratification · 01 DDL Provenance Map

8 min read Revision 1
dot-iu-cutterv0.5lifecycle-ddl-ratificationprovenance-mapg1-passdieu442026-05-20

dot-iu-cutter v0.5 — Lifecycle DDL Ratification · Provenance Map

doc 1 of 6 · 2026-05-20 · ratification of M3a Bundles A..E into repo

phase               : G1 — DDL provenance trace
outcome             : PASS  (4/4 function md5(prosrc) byte-equal to live)
production_mutation : NONE this phase (read-only PG + read KB)

1. Source-of-truth chain

The lifecycle substrate live in directus PG was applied during the M3a-retry macro on 2026-05-20. The repo runbook just committed mirrors that substrate exactly, with two source streams cross-checked:

authoring_KB:
  - knowledge/dev/laws/dieu44-trien-khai/v0.5-lifecycle-enactment-implementation-authoring/
    docs 01..06; bundles fully designed
execution_KB:
  - knowledge/dev/laws/dieu44-trien-khai/v0.5-lifecycle-enactment-execution-m3a-retry/
    docs 00..07; bundles applied; fingerprints recorded
live_pg:
  - directus  PG; pg_proc.prosrc / pg_trigger / pg_class read on 2026-05-20
  - role: context_pack_readonly (read-only)
ground_truth_for_runbook_bodies:
  - live pg_proc.prosrc (decoded from base64-utf8); md5 verified against
    M3a-retry post-apply pins

2. Bundle inventory

bundle_A_vocab_and_log:
  txn       : 1
  objects:
    - public.iu_lifecycle_vocab (table + 4-row seed)
    - public.iu_lifecycle_log   (table + 5 indexes + FK + grants/revoke)
  ddl_kind  : CREATE TABLE / INSERT ON CONFLICT / CREATE INDEX / GRANT / REVOKE
  source    : authoring KB doc 02 (verbatim, no body normalization needed)

bundle_B_immutability:
  txn       : 2
  objects:
    - public.fn_iu_enacted_immut()  (LANGUAGE plpgsql, trigger fn)
    - public.fn_uv_enacted_immut()  (LANGUAGE plpgsql, trigger fn)
    - trg_iu_enacted_immut          (BEFORE UPDATE OR DELETE)
    - trg_uv_enacted_immut          (BEFORE UPDATE OR DELETE)
  ddl_kind  : CREATE OR REPLACE FUNCTION / DROP+CREATE TRIGGER
  source    : live pg_proc.prosrc + authoring KB header
  body_origin : LIVE PG  (authoring SQL had decorative comments that PG
                          stripped; using LIVE body preserves md5 equality)

bundle_C_fn_iu_enact:
  txn       : 3
  objects:
    - public.fn_iu_enact(text,text,uuid,text,uuid,text,text,boolean) → jsonb
  ddl_kind  : CREATE OR REPLACE FUNCTION (SECURITY DEFINER, search_path pinned)
  source    : live pg_proc.prosrc + authoring KB signature + comment
  body_origin : LIVE PG  (same reason as Bundle B)

bundle_D_gateway_and_grants:
  txn       : 4
  objects:
    - UPDATE public.dot_config gateway allowed_marker_values
    - INSERT 8 iu_enact.* keys (ON CONFLICT DO UPDATE)
    - REVOKE EXECUTE on fn_iu_enact FROM PUBLIC
    - GRANT  EXECUTE on fn_iu_enact TO cutter_exec
  ddl_kind  : UPDATE / INSERT ON CONFLICT / REVOKE / GRANT
  source    : authoring KB doc 02 (verbatim)

bundle_E_fn_iu_apply_edit_draft_patch:
  txn       : 5
  objects:
    - public.fn_iu_apply_edit_draft(uuid,text,text DEFAULT NULL::text) → jsonb
  ddl_kind  : CREATE OR REPLACE FUNCTION (SECURITY DEFINER, search_path pinned)
  source    : live pg_proc.prosrc + M3a-retry doc 02 signature spec
  body_origin : LIVE PG  (narrow patch; preserves p_review_note default)

3. Fingerprint verification (md5(prosrc) byte-equality)

Verified by re-extracting bodies from the committed repo SQL files (sql/lifecycle/bundle_*.sql) between $tag$…$tag$ markers and computing md5 against the live PG md5(prosrc) values:

function                       len   md5(extracted)                    md5(live)                         verdict
-----------------------------+------+----------------------------------+----------------------------------+--------
fn_iu_enacted_immut          1631   aeb3fa4fdb225f6ba6b7073582caa454  aeb3fa4fdb225f6ba6b7073582caa454  OK
fn_uv_enacted_immut          2415   03f035a23cbc79a9e811a6da6f5266ba  03f035a23cbc79a9e811a6da6f5266ba  OK
fn_iu_enact                  8674   6ca9bc39e2d2be93dd8a71739fa80dc4  6ca9bc39e2d2be93dd8a71739fa80dc4  OK
fn_iu_apply_edit_draft       4826   42e96b6c9e81a2d0a28b30644d178a26  42e96b6c9e81a2d0a28b30644d178a26  OK

All 4 lifecycle function bodies in the repo SQL files are byte-equal to the live function bodies stored in PG. Re-applying any of these bundles in a fresh PG environment will produce md5(prosrc) values that match these pins (assuming PG ≥ 16 stores prosrc unchanged from CREATE OR REPLACE source, which it does).

4. Body-extraction technique (audit trail)

extraction_query :
  SELECT proname,
         length(prosrc) AS body_len,
         md5(prosrc) AS body_md5,
         encode(convert_to(prosrc, 'UTF8'), 'base64') AS body_b64
    FROM pg_proc
   WHERE pronamespace = 'public'::regnamespace
     AND proname IN ('fn_iu_enact','fn_iu_apply_edit_draft',
                     'fn_iu_enacted_immut','fn_uv_enacted_immut');

decode_step :
  base64 → bytes → utf-8 decode → write to /tmp/live_bodies/<name>.txt

dollar_quote_check :
  Verified no body contains literal '$$' before embedding;
  used unique per-function dollar tags ($iuim$, $uvim$, $enact$, $apply$)
  so the embedded body is never escaped or re-flowed.

5. Authoring vs live divergence — surfaced

discovery:
  authoring_SQL_in_KB_doc_02 had inline `-- step N` comments and used
  UTF-8 arrow characters (→) in RAISE EXCEPTION messages.
live_pg_storage:
  PG stripped the inline `--` comments from prosrc and replaced the
  UTF-8 arrows with ASCII '->' during M3a-retry apply (the actual
  sidecar SQL applied was a stripped/normalized form, not the authoring
  doc copy verbatim).
implication:
  Authoring docs are NOT byte-for-byte the same as live prosrc.
  The runbook commits the LIVE bodies to preserve fingerprint equality
  for future re-apply / recovery scenarios.
KB_note:
  This divergence is documented here, not as a defect — the authoring
  docs remain readable for design intent, and the runbook SQL files
  remain re-applicable for substrate reproduction.

6. Static dependencies surfaced (must exist before re-apply)

pre_existing_objects_required :
  - public.information_unit (table)
  - public.unit_version    (table)
  - public.unit_edit_draft (table)         # Bundle E callers
  - public.unit_edit_comment (table)       # Bundle E callers
  - public.dot_config (table)              # Bundle D updates
  - public.fn_iu_verify_invariants(text) → jsonb   (used by Bundle C + E)
  - public.fn_content_hash(text) → text             (used by Bundle E)
  - cutter_governance.review_decision (table) with SELECT visible to directus
  - cutter_governance.cut_change_set  (table) with SELECT visible to directus
  - role cutter_exec                       (GRANT EXECUTE target)
  - role context_pack_readonly, cutter_verify, workflow_admin (read grants)
  - role directus                          (SECDEF principal at apply time)

7. Gate disposition

G1_KB_source_traced               : PASS  (authoring + execution KB read)
G1_live_PG_bodies_extracted       : PASS  (4 × base64 → utf-8)
G1_md5_byte_equality              : PASS  (4/4 byte-equal to live md5)
G1_dollar_quote_safety            : PASS  (no body contains $$, unique tags chosen)
G1_authoring_vs_live_divergence   : SURFACED + documented (authoring comments
                                            stripped; arrows normalized)
G1_dependencies_listed            : PASS
G1_no_invention                   : PASS  (no DDL fabricated from memory)

8. STOP

Provenance map complete. Proceed to doc 02 (repo placement decision).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.5-lifecycle-ddl-ratification-runbook/01-ddl-provenance-map-2026-05-20.md