KB-27CC

25000x · 02 — Migration 033 substrate (Auto-Instantiate-From-Event: +1 tbl +2 view +2 fn +1 cfg +1 evt)

6 min read Revision 1
iu-corev0.625000xmigration-033auto-instantiatesidecar-designddlproductization

25000x · 02 — Migration 033 substrate (Auto-Instantiate-From-Event)

Authored artifacts

Path Purpose
sql/iu-core/033_auto_instantiate_from_event.sql forward DDL (additive)
sql/iu-core/rollback/033_auto_instantiate_from_event.rollback.sql rollback w/ REFUSED guard
ops/25000x-event-automation-real-product-scaleout-ui-ops-finalization/02_auto_instantiate_productization_proof.sql 12 bounded BEGIN/ROLLBACK probes
ops/25000x-event-automation-real-product-scaleout-ui-ops-finalization/03_durable_auto_instantiate_event.sql one durable proof event
ops/25000x-event-automation-real-product-scaleout-ui-ops-finalization/05_bulk_scaleout_via_event_orchestrator.sql 12-instance bulk scaleout

Surface additions

Sidecar table (+1)

public.iu_auto_instantiate_event_log (
  instance_collection_id  uuid PRIMARY KEY
      REFERENCES iu_collection_template_instance_lineage(instance_collection_id)
      ON DELETE CASCADE,
  template_collection_id  uuid NOT NULL REFERENCES iu_piece_collection(id),
  event_id                uuid NOT NULL,
  event_type              text NOT NULL,
  idempotency_key         text NOT NULL,
  emit_mode               text NOT NULL CHECK (emit_mode IN ('dry_run','live')),
  triggered_by            text NOT NULL,
  created_at              timestamptz NOT NULL DEFAULT now(),
  UNIQUE (idempotency_key)
);

Plus 3 indices: idempotency_key UNIQUE, event_id, triggered_by, template_collection_id.

Views (+2)

  • v_iu_auto_instantiate_event_log — per-row event log joined to template + instance collection for digest match comparison.
  • v_iu_auto_instantiate_event_summary — per-template, per-mode rollup with instances_last_hour + instances_last_day recency windows.

Functions (+2)

  • fn_iu_auto_instantiate_from_event(p_event_id, p_event_type, p_template_collection_id, p_instance_key_suffix, p_emit_mode, p_actor, p_note) — SECURITY DEFINER, returns jsonb with status.
    • Validates input + emit_mode + checks iu_core.auto_instantiate_enabled for live mode + checks fn_iu_composer_enabled() always.
    • Validates template exists + is marked (iu_collection_template_registry.is_template=true).
    • Computes idempotency_key = md5(event_id || ':' || template_id || ':' || instance_key_suffix).
    • On idempotent replay returns {"status":"idempotent_replay","instance_collection_id":…} without re-composing.
    • Collects active pieces from the template (joined via iu_piece_membership).
    • Composes the instance via fn_iu_compose with instance key tpl-inst:auto:<suffix>.
    • Records lineage via fn_iu_collection_record_template_instance.
    • Writes sidecar log row.
  • fn_iu_auto_instantiate_rollback_by_actor(p_actor, p_dry_run boolean DEFAULT true) — actor-scoped cleanup. dry_run=true reports; dry_run=false deletes sidecar log + lineage + instance collection + membership.

Config gate (+1)

  • iu_core.auto_instantiate_enabled default false — LIVE-mode gate. DRY_RUN bypasses; LIVE refuses with {"status":"live_gate_closed"} if false.

Event type (+1)

  • iu.template.instance_auto_composed registered with event_stream='update', delivery_lane='delayed', active=true. No route attached — event exists for downstream consumers but is not auto-delivered (constitutional).

Sidecar design rationale

Two existing sidecars already key on iu_piece_collection.id (mig 031 registry, mig 032 version). Adding a third sidecar keyed on iu_collection_template_instance_lineage.instance_collection_id (the lineage row PK) instead of iu_piece_collection.id keeps:

  • manual-vs-auto axis cleanly separable (a manually composed instance has lineage but no auto-instantiate log row);
  • idempotency UNIQUE constraint scoped to the auto path only;
  • actor-scoped rollback DELETE traversable: sidecar log → lineage → instance collection → membership all reachable from one column;
  • rollback row counts separable per migration.

Safety contract

  • Fully additive: no existing column / view / function / trigger / route touched.
  • No production corpus mutated.
  • No Qdrant interaction.
  • live mode requires BOTH iu_core.composer_enabled=true AND iu_core.auto_instantiate_enabled=true; both default false ⇒ substrate ships inert.
  • dry_run mode requires composer_enabled=true (because compose mints rows) but bypasses the auto-instantiate gate.

Reversibility

  • rollback/033_*.rollback.sql:
    • Drops the two views first.
    • Drops the two functions.
    • Deletes the event_type_registry row.
    • Deletes the dot_config row.
    • Refuses to drop the log table while rows exist unless iu_core.force_rollback_033=true is set in the session.
  • In-place actor-scoped rollback via fn_iu_auto_instantiate_rollback_by_actor does not require dropping the substrate.

D9 deltas (174 → 181)

Class Before After Delta
table 28 29 +1
view 28 30 +2
function 63 65 +2
trigger 6 6 0
config 12 13 +1
event_type 21 22 +1
route 16 16 0
total 174 181 +7

Pinning tests bumped in same commit (16 sites). sql/iu-core/runtime/110_iu_core_dot_conformance_scan.sql SSOT updated; D9 re-run confirms 7/7 PASS at 181.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-25000x-event-automation-real-product-scaleout-ui-ops-open-goal/02-migration-033-substrate.md