KB-19FB

RS3B-08 — Trigger Side-Effect Inventory and Closed-at-Registration Proof — 2026-06-21

7 min read Revision 1
rs3btriggersside-effectspg-notifyclosed-at-registrationcontext-packread-only2026-06-21

RS3B-08 — Trigger Side-Effect Inventory and Closed-at-Registration Proof — 2026-06-21

Macro: RS3B-REGISTRAR-HARDENING-DESIGN (read-only / KB-design) Deliverable: 08 of 10 · Trigger side-effect + closed-at-registration (Mục tiêu H) Date: 2026-06-21 · 0 mutations · NO_CODEX_LIVE_READ Deliverable status: TRIGGER_SIDE_EFFECT_INVENTORIED with one activation-signal side-effect (trg_context_pack_dot_registerpg_notify) that must be fenced by the closed-at-registration proof.

Method note: information_schema.triggers is privilege-blind for the read-only role (returns 0). The full set below was read via pg_catalog.pg_trigger + pg_get_triggerdef (source-tier). Trigger enable flags: O=enabled, D=disabled.


1. dot_tools trigger inventory (14 triggers; 13 enabled, 1 disabled)

Trigger Timing / event Function Side effect Activates? Notifies automation? Birth/context-pack effect?
trg_before_birth_gate_dot_tools BEFORE INSERT fn_birth_gate() may block insert (gate) no no gate (fail-closed-friendly)
trg_auto_code_dot_tools BEFORE INSERT gen_code_dot_tools() auto-generate code no no no
trg_normalize_dot_filepath BEFORE INSERT/UPDATE OF file_path fn_normalize_dot_filepath() normalize file_path no no no
trg_desc_guard_dot_tools BEFORE INSERT/UPDATE OF description fn_description_birth_guard() description guard no no no
trg_validate_dot_origin_dot_tools BEFORE INSERT/UPDATE OF _dot_origin fn_validate_dot_origin() validate _dot_origin no no origin gate
birth_trigger_dot_tools AFTER INSERT fn_birth_registry_auto('code') create birth-registry row no no birth side-effect
trg_birth_dot_tools AFTER INSERT fn_birth_registry_auto('code') duplicate of above no no birth side-effect (dup)
trg_desc_provenance_dot_tools AFTER INSERT fn_auto_label_provenance() auto provenance label no no no
trg_label_assign_dot_tools AFTER INSERT/UPDATE OF name,description fn_auto_label_assignment() auto label no no no
trg_context_pack_dot_register AFTER INSERT OR UPDATE OF status, tier fn_context_pack_on_dot_register() pg_notify('context_pack_event', …) potential YES context-pack
trg_refresh_dot_count AFTER INSERT/DELETE/UPDATE OF status (statement) fn_refresh_dot_count() refresh count no no no
trg_refresh_orphan_dot AFTER INSERT/DELETE/UPDATE (statement) trg_fn_refresh_orphan_dot() refresh orphan view no no no
trg_count_dot_tools AFTER … (statement) refresh_registry_count() count refresh no no DISABLED (D)

The one activation-signal trigger (verbatim function body, source-tier)

fn_context_pack_on_dot_register():
  SELECT value::jsonb INTO v_tiers FROM dot_config WHERE key='context_pack_dot_register_watch_tiers';
  IF v_tiers IS NULL OR jsonb_array_length(v_tiers)=0 THEN RETURN NEW; END IF;
  IF EXISTS (SELECT 1 FROM jsonb_array_elements_text(v_tiers) t WHERE t=COALESCE(NEW.tier,''))
     AND NEW.status='active' THEN
    PERFORM pg_notify('context_pack_event',
      json_build_object('kind','dot_register','code',NEW.code,'tier',NEW.tier,'op',TG_OP)::text);
  END IF;
  RETURN NEW;

Live config: dot_config.context_pack_dot_register_watch_tiers = ["A","B","C"]. DOT-REGISTER and DOT-015 are tier B. ⇒ inserting/updating a tier-A/B/C dot_tools row to status='active' fires a pg_notify('context_pack_event', {kind:dot_register, code, tier, op}) that downstream context-pack automation may consume. The notify is a signal only (no row write), but it is an automation activation surface.

2. Adjacent surfaces

  • dot_config (119 rows): trg_dot_config_touch BEFORE UPDATE (fn_dot_config_touch); trg_sync_cp_patterns AFTER INSERT/UPDATE OF value (fn_sync_cp_patterns_to_meta). Gates here (process_dot_runtime.real_run, iu_core.operator_runtime) are closed; registration must not touch them.
  • law_dot_enforcement (272 rows): trg_birth_law_dot_enforcement AFTER INSERT (fn_birth_registry_auto_id); trg_enforcement_validate_dot_code BEFORE INSERT/UPDATE (fn_enforcement_validate_dot). Not written by registration.
  • Audit sinks (RS3B-06): event_outbox has trg_event_outbox_type_validate BEFORE INSERT (type validation, no immutability); registry_changelog has birth/label triggers + DISABLED count trigger (no immutability, mutable resolve columns); governance_audit_log, context_pack_manifest, iu_route_attempt have no triggers.

3. Closed-at-Registration Proof Obligations

For the hardened registrar to prove registration is closed (registers without activating):

  1. No activation status. The registration INSERT must not set status='active' for a watch-tier (A/B/C) DOT, so trg_context_pack_dot_register does not fire pg_notify. Register a closed/inert status; activation is a separate, Owner-gated UPDATE with its own authority nonce (RS3B-03 §6, RS3B-05). Reject ACTIVATION_AT_REGISTRATION / WOULD_OPEN_GATE.
  2. If a notify is unavoidable, prove the consumer is inert. If any registration path must set a watch-tier row active, the proof must show the context_pack_event consumer performs no auto-activation / no birth pipeline / no gate flip (currently context_pack_mode = warn). Until proven, treat the notify as an activation risk → fail-closed.
  3. Account for birth side-effects. birth_trigger_dot_tools + trg_birth_dot_tools (duplicate) auto-create a birth-registry row on INSERT; fn_birth_gate may block. The contract must treat birth auto-creation as expected, idempotent, and non-activating; the duplicate birth trigger must not double-effect in a way the verifier misreads.
  4. Gates stay closed. Post-commit verifier (RS3B-03 §5) must confirm: dot_config runtime gates unchanged (real_run=false, operator_runtime=false), dot_agent_api_contract not wired, no law_dot_enforcement write, status not active.
  5. No durable activation via audit sink. Writing the failure/audit envelope to event_outbox (RS3B-06) must not emit an event on a delivery_lane/event_type that triggers downstream execution.

4. Status block

  • Deliverable status: TRIGGER_SIDE_EFFECT_INVENTORIED
  • Activation surface = trg_context_pack_dot_registerpg_notify('context_pack_event') on watch-tier + status='active'; fenced by obligation #1
  • 14 dot_tools triggers accounted (1 disabled); no immutability triggers on any audit sink (RS3B-06)
  • Registration gate: REGISTRATION_HOLD · REGISTRATION_CAN_PROCEED = NO · 0 mutations
Back to Knowledge Hub knowledge/dev/laws-new/reports/rs3b/08-trigger-side-effect-inventory-and-closed-registration-proof-2026-06-21.md