Pre-Birth Pilot Rehearsal — 05 dot_tools Permit BEFORE Gate
05 — Workstream D: dot_tools Permit-Consuming BEFORE Gate Rehearsal
Result: PROVEN. The pilot rule — "no active valid permit for dot_tools + entity_code → INSERT blocked" — was rehearsed end-to-end on an exact temp clone of dot_tools (CREATE TEMP TABLE dt_copy (LIKE public.dot_tools INCLUDING DEFAULTS)), with the gate attached as a temp BEFORE-INSERT trigger.
Why a temp clone, not a live trigger on dot_tools
Attaching a trigger to production dot_tools — even inside a rolled-back transaction — takes an ACCESS EXCLUSIVE lock on the table for the duration of the txn, which would block concurrent governed DOT operations. The macro explicitly permits the temp-table equivalent. dt_copy mirrors dot_tools column-for-column, so the gate logic is validated against the real schema with zero lock on the production table. This is the one rehearsal limitation, by design (prod safety > trigger-binding fidelity, which was separately proven OID-stable in doc 04).
Pilot gate design (does NOT touch fn_birth_gate)
The pilot gate is a separate, pilot-specific function attached only to the pilot family. The global advisory fn_birth_gate is left entirely unchanged — no global flip. The permit gate is additive and removable.
CREATE FUNCTION fn_dot_tools_permit_gate() RETURNS trigger LANGUAGE plpgsql AS $$
DECLARE v_id uuid; v_exp timestamptz;
BEGIN
SELECT permit_id, expires_at INTO v_id, v_exp
FROM birth_admission_permit
WHERE collection_name='dot_tools' AND entity_code=NEW.code
AND status IN ('REQUESTED','RESERVED')
ORDER BY requested_at DESC LIMIT 1;
IF v_id IS NULL THEN RAISE EXCEPTION 'PERMIT_GATE: no active permit for dot_tools/%', NEW.code; END IF;
IF v_exp <= now() THEN RAISE EXCEPTION 'PERMIT_GATE: permit % expired for %', v_id, NEW.code; END IF;
UPDATE birth_admission_permit SET status='CONSUMED', consumed_at=now() WHERE permit_id=v_id;
RETURN NEW;
END $$;
CREATE TRIGGER trg_dt_permit_gate BEFORE INSERT ON dot_tools
FOR EACH ROW EXECUTE FUNCTION fn_dot_tools_permit_gate();
For the real apply, a policy-driven branch is recommended over a hard pilot-only function so the gate is registry-driven rather than family-hardcoded: the gate checks a per-family flag (birth_admission_required) from collection_registry/policy, enforcing permits only where set — dot_tools first. Avoids re-introducing the hardcoded-family anti-pattern.
Test battery & live results
| # | Scenario | Expected | Result |
|---|---|---|---|
| D.1 | INSERT DOT-NOPERMIT with no permit |
blocked | PASS — no active permit for dot_tools/DOT-NOPERMIT |
| D.2 | INSERT DOT-EXP-001 with an expired permit |
blocked | PASS — permit … expired for DOT-EXP-001 |
| D.3 | Create valid permit, INSERT DOT-VALID-001 |
success + permit CONSUMED | PASS — row inserted; permit CONSUMED, consumed_at set |
Interaction with the existing pipeline
On real dot_tools, BEFORE-INSERT triggers fire alphabetically by name. The permit gate must run after trg_auto_code_dot_tools (which generates code) so NEW.code is populated. Name it accordingly (e.g. trg_zz_dot_tools_permit_gate). The existing advisory trg_before_birth_gate_dot_tools stays as-is; the permit gate is an additional enforcement layer.
Rollback proof
After ROLLBACK: dt_copy absent; fn_dot_tools_permit_gate count = 0; production dot_tools triggers fingerprint unchanged (c77f1a4c62d5ee3480b09280475058b3, doc 11).
Decision
DOT_TOOLS_GATE = PROVEN. Blocks missing/expired permits, consumes a valid one, without modifying fn_birth_gate or locking prod dot_tools. Production apply should use the policy-driven (registry-flag) form. Gated by owner approval + prerequisite permit table (doc 02) and composite migration (doc 03).