KB-2EAA rev 7

P3D — Birth System B3-A2 Blocker Resolution Design

8 min read Revision 7
p3dbirth-systemb3a2blockerresolutiondesign

P3D — Birth System B3-A2 Blocker Resolution Design

Date: 2026-05-12 Mode: DESIGN ONLY — no mutation, no trigger install Source: B3-A readiness rerun report (PARTIAL_ACCEPTED)


A. birth_registry self-birth risk

Problem

birth_registry = bảng sổ khai sinh. Nếu gắn trg_birth_birth_registry → fn_birth_registry_auto → INSERT birth_registry → trigger fires again → infinite recursive loop. PG sẽ hit max trigger recursion depth rồi error, hoặc tệ hơn, chạy n lần trước khi PG kill.

birth_registry hiện có 2 trigger khác (trg_birth_auto_certify, trg_birth_change_flag_matrix) — nhưng KHÔNG có contract trigger fn_birth_registry_auto. Hiện tại an toàn. Nguy hiểm nếu B3-A cắm trigger mù.

3 options

Option Description Pro Con Recommendation
1. EXEMPT (SYSTEM-MANAGED REASON) Mark birth_registry coverage_status='BIRTH_EXEMPT_SYSTEM_LOG_OR_AUDIT' and keep coverage_scope_status within the existing CHECK constraint (normally 'IN_SCOPE' unless live policy design adds a new allowed value). Use coverage_exemption_reason to state SYSTEM_MANAGED semantics. Simple, no code change, birth_registry is the system itself, compatible with existing B3-P CHECK constraints Loses birth-of-birth tracking RECOMMENDED
2. Self-birth guard in function Add IF TG_TABLE_NAME = 'birth_registry' THEN RETURN NEW; END IF; to fn_birth_registry_auto Allows trigger on birth_registry (for uniformity) Modifies contract function — risky, hardcodes table name Not recommended
3. pg_trigger_depth() guard Add IF pg_trigger_depth() > 1 THEN RETURN NEW; END IF; Generic, no table name hardcode Suppresses ALL nested triggers, not just birth_registry recursion. Could mask bugs. Not recommended

Recommendation: Option 1 — EXEMPT

birth_registry IS the birth system. It doesn't need to birth itself. Nôm na: sổ khai sinh không cần khai sinh chính nó. Nó TỒN TẠI để ghi khai sinh cho người khác.

Policy storage impact: UPDATE collection_registry SET coverage_status='BIRTH_EXEMPT_SYSTEM_LOG_OR_AUDIT', keep coverage_scope_status within the live allowed set from chk_collection_registry_coverage_scope_status (current allowed values from B3-P DDL: IN_SCOPE, USER_EXCLUDED, FUTURE_SCOPE, ORPHAN_REGISTRY; recommended current value = IN_SCOPE), and set coverage_exemption_reason='SYSTEM_MANAGED: self-referential birth system table — recursive trigger risk' WHERE collection_name='birth_registry'. Do not write literal SYSTEM_MANAGED into coverage_scope_status unless a separate DDL/design first extends the CHECK constraint.

Boundary: birth_registry NEVER gets fn_birth_registry_auto trigger. Existing 2 triggers (auto_certify, change_flag_matrix) stay.


B. Variant function bindings (3 collections)

Situation

Collection Trigger Function OID
governance_relations trg_birth_governance_relations fn_birth_registry_auto_id 66750
law_dot_enforcement trg_birth_law_dot_enforcement fn_birth_registry_auto_id 66750
law_jurisdiction trg_birth_law_jurisdiction fn_birth_registry_auto_id 66750

These tables HAVE birth triggers — they ARE birthing. But through a variant function (fn_birth_registry_auto_id), not the contract function (fn_birth_registry_auto, OID 39232).

Why the variant may exist

The _id suffix may indicate a PK-shape adaptation, but this must not be accepted from naming alone. Before the whitelist becomes executable policy, B3-A2 must run a read-only source/equivalence probe using pg_get_functiondef() for both fn_birth_registry_auto and fn_birth_registry_auto_id, plus sample birth rows from the 3 variant-bound tables. If the variant differs in semantics beyond entity-id extraction, GPT must review again before any validator accepts it as a contract sibling.

3 options

Option Description Pro Con Recommendation
1. Migrate to contract DROP variant trigger + CREATE with contract function Uniformity May break if PK column differs. Needs function source investigation. Risk. Not recommended now
2. Conditional whitelist as sibling Document fn_birth_registry_auto_id as a candidate contract sibling, but validators accept both functions only after read-only source/equivalence probe PASS + GPT review. Zero code change if proven equivalent. These 3 tables keep working. Honest about reality. Two "contract" functions to maintain; unsafe if accepted without source proof RECOMMENDED, CONDITIONAL
3. Defer Keep as blocker, don't resolve No decision Blocks B3-A PASS forever Not recommended

Recommendation: Option 2 — Conditional whitelist as sibling

Recommendation is conditional, not immediately executable: whitelist fn_birth_registry_auto_id only after a read-only equivalence probe proves it is a safe contract sibling for the 3 bound tables. Until that probe is reviewed, B3-A3 must treat the 3 variant-only bindings as accepted-by-design-but-not-yet-validator-green.

Validation impact after probe PASS: B3-A trigger install prompt and onboarding gate health check may accept BOTH function OIDs as valid birth bindings:

contract_function_oids = [fn_birth_registry_auto OID, fn_birth_registry_auto_id OID]

These are discovered live (not hardcoded OIDs), by proname lookup:

SELECT oid FROM pg_proc WHERE proname IN ('fn_birth_registry_auto', 'fn_birth_registry_auto_id');

Future consolidation: If fn_birth_registry_auto is refactored to handle all PK types, the 3 variant triggers can be migrated then. Not urgent.


C. Clean trigger install candidates

After resolving A (birth_registry EXEMPT via allowed policy values) and B (variant whitelist after source/equivalence probe PASS):

From 10 missing-trigger collections:
  - birth_registry → EXEMPT (resolved in A)
  - 9 remaining = clean candidates for trigger install

9 clean candidates (from readiness rerun, as evidence — Agent must re-verify live before install):

apr_action_types
apr_approvals
apr_request_types
binding_registry
dot_domain_rules
field_type_equivalences
normative_relations
nrm_approval_rules
nrm_doc_type_config

All have: physical table ✅, species mapping ✅, coverage_status=BIRTH_REQUIRED ✅, IN_SCOPE ✅, no existing trigger (contract or variant) ✅.

B3-A3 trigger install for these 9 can proceed after GPT approves this design + resolves A and B.

B3-A3 prompt must:

  • Re-verify all conditions live (not use "9" as hardcoded count)
  • Accept BOTH contract function OIDs as valid
  • Exclude birth_registry (EXEMPT)
  • Single transaction + advisory lock
  • Verify by function OID binding
  • Report exact trigger names for rollback

D. Out-of-scope follow-ups

D1. B3-A-DUP: 18 duplicate trigger pairs

18 collections have 2 triggers both calling fn_birth_registry_auto → double birth_registry rows per INSERT. This is tech debt that may cause data quality issues (duplicate birth records).

Separate workstream. Design:

  • Identify which trigger to keep (trg_birth_* convention) and which to drop (birth_trigger_* legacy)
  • Verify no other logic differences between pairs
  • Single transaction DROP of legacy triggers
  • Verify birth counts before/after

D2. B3-DESC: 57 description_policy='unclassified'

Separate semantic classification workstream. Not a coverage_status issue. Not a B3-A blocker.

D3. Phase 5C2 / UI cutover

Still paused. Not in scope.


E. Anti-hardcode + species/layer rules

  • Species = meta-class outside 6 composition classes
  • New species must be born in entity_species before mapping
  • All counts in this design = evidence snapshots from readiness rerun, NOT execution gates
  • B3-A3 prompt must re-query live PG
  • Contract function OIDs discovered by proname, not hardcoded integers

B3-A2 Blocker Resolution Design | DESIGN ONLY | 2026-05-12

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/design/p3d-birth-system-b3a2-blocker-resolution-design.md