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 withinstances_last_hour+instances_last_dayrecency 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_enabledfor live mode + checksfn_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_composewith instance keytpl-inst:auto:<suffix>. - Records lineage via
fn_iu_collection_record_template_instance. - Writes sidecar log row.
- Validates input + emit_mode + checks
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_enableddefaultfalse— LIVE-mode gate. DRY_RUN bypasses; LIVE refuses with{"status":"live_gate_closed"}if false.
Event type (+1)
iu.template.instance_auto_composedregistered withevent_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.
livemode requires BOTHiu_core.composer_enabled=trueANDiu_core.auto_instantiate_enabled=true; both defaultfalse⇒ substrate ships inert.dry_runmode requirescomposer_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=trueis set in the session.
- In-place actor-scoped rollback via
fn_iu_auto_instantiate_rollback_by_actordoes 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.