IU-0 Pack 2A — Legal/Tooling Preflight Discovery Report
IU-0 Pack 2A — Legal/Tooling Preflight Discovery Report
Date: 2026-05-04 Scope: Read-only discovery only. No writes performed. No DOT executed. Author: Claude Code (Opus 4.7) per dispatch from User/GPT after legal recheck blocker. Trigger doc:
knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-legal-recheck-pack2a-dot-gateway-risk-2026-05-04.md
Executive Summary
Verdict — abundant legal tooling already exists. Collection birth/registration and trigger governance both have governed DOT tools registered in dot_tools AND deployed at /opt/incomex/dot/bin/. There is NO need for raw SQL INSERT into collection_registry. There is NO need for ADMIN fallback unless a specific tool gap is identified after design. Direct INSERT would violate Đ4 §2, Đ2, Đ35, Đ36, and the §6 9-step DOT-COLLECTION-CREATE protocol.
Recommendation: Pack 2B/2C must use dot-collection-register (and optionally dot-collection-create if PG tables had not been created) — never raw SQL — to register information_unit + unit_version. ADMIN fallback path is available but not justified; no tool gap discovered.
Q1 — Collection registration tooling
LEGAL tools exist on filesystem AND in dot_tools registry.
| Tool (filesystem) | dot_tools code | Tier | Paired | Coverage | Description (truncated) |
|---|---|---|---|---|---|
/opt/incomex/dot/bin/dot-collection-create |
DOT-COL-CREATE |
B | DOT-COL-HEALTH |
complete | v2.0.0 — Multi-step collection creation. CREATE TABLE + Directus + birth + meta_catalog + species + permissions. |
/opt/incomex/dot/bin/dot-collection-create |
DOT_COLLECTION_CREATE |
B | DOT-HEALTH-DOT |
— | Tạo collection trong Directus kèm fields, FK, permissions, đăng ký species. (Vietnamese mirror entry; same script.) |
/opt/incomex/dot/bin/dot-collection-register |
DOT_COLLECTION_REGISTER |
B | DOT-HEALTH-DOT |
— | Đăng ký collection vào collection_registry. v1.1.0 supports --update upsert. CHECKED-NO-DUPLICATE in header. |
/opt/incomex/dot/bin/dot-collection-field-sync |
DOT_COLLECTION_FIELD_SYNC |
B | DOT-HEALTH-DOT |
— | Field drift detection between code defs and Directus. |
/opt/incomex/dot/bin/dot-collection-health |
DOT-COL-HEALTH / DOT_COLLECTION_HEALTH |
A | — | complete | v2.0.0 — Collection integrity HC, self-healing, 13+ checks. Đ36 GP8.1. |
/opt/incomex/dot/bin/dot-schema-registry-collections-ensure |
DOT_SCHEMA_REGISTRY_COLLECTIONS_ENSURE |
B | DOT-HEALTH-DOT |
— | Ensures dot_tools, ui_pages, collection_registry, agents exist in Directus. |
/opt/incomex/dot/bin/dot-schema-birth-registry-ensure |
DOT_SCHEMA_BIRTH_REGISTRY_ENSURE |
B | DOT-HEALTH-DOT |
— | Birth registry schema ensure (Đ0-G). |
/opt/incomex/dot/bin/dot-birth-trigger-setup |
DOT_BIRTH_TRIGGER_SETUP |
B | DOT-HEALTH-DOT |
— | Deploys AFTER INSERT triggers per governed collection → auto-inserts birth_registry. v1.0.0. |
/opt/incomex/dot/bin/dot-birth-backfill |
DOT_BIRTH_BACKFILL |
B | DOT-HEALTH-DOT |
— | Backfill birth_registry for legacy entities. |
/opt/incomex/dot/bin/dot-dot-register |
DOT-REGISTER |
B | DOT-HEALTH-DOT |
complete | Register a new DOT into dot_tools with domain/version/kb_path. |
/opt/incomex/dot/bin/dot-species-register |
(not separately indexed in this query) | — | — | — | Species registration (paired with collection birth). |
Status field convention: dot_tools.status is text; relevant rows use active. Some rows (e.g. DOT-COL-CREATE) have empty status but coverage_status=complete.
Key write-capable governance gateway = dot-collection-register (Đ4 §2 birth-process tool of record for IU-0 use case, since the IU PG tables already exist — only the catalog/registry registration remains).
Q2 — Trigger / DDL / Audit governance tooling
LEGAL tools exist. Trigger governance is governed by Đ36 collection protocol + a multi-layer enforcement system:
| Tool | dot_tools code | Tier | Description |
|---|---|---|---|
dot-trigger-guard |
(DOT-316 per source header; not seen in dot_tools query — VERIFY before execute) |
A (per header) | Tầng 1 PG event trigger (real-time) + Tầng 2 DOT cron (enforcement). NT-11 exceptions-only. Reads trigger_guard_exceptions, writes trigger_guard_alerts. |
dot-pg-triggers-ensure |
(not in this query result) | B | Deploys sequences + functions + triggers for 16 atom collections; idempotent. v1.0.0. |
dot-schema-trigger-registry-ensure |
DOT_SCHEMA_TRIGGER_REGISTRY_ENSURE |
B | Ensures trigger_registry PG table, populates from pg_trigger, registers in meta_catalog, creates sync function. v1.0.0. |
dot-pg-audit-ensure |
(not in this slice) | — | v2.0.0 — audit_relationships + audit_dead_links + run_audit_to_issues() — audit functions for DOT scanning. |
dot-label-trigger-setup |
— | — | Auto-label provenance trigger setup. |
dot-metadata-audit |
— | — | Audit metadata coverage (description/note/group) across Directus. |
dot-layer-integrity-audit / dot-layer3-audit |
— | — | Layer integrity scans. |
dot-id-collision-check |
— | — | ID collision audit. |
Live event triggers in PG:
evt_trigger_guard_ddl→ fires onddl_command_end, enabledO(origin).evt_trigger_guard_drop→ fires onsql_drop, enabledO.
Whitelist/exceptions mechanism: YES — trigger_guard_exceptions table with temporary_until column drives NT-11 exceptions-only model (empty table = "all triggers ON"). Companion trigger_guard_alerts records violations. dot-trigger-guard self-checks that 2/2 event triggers are enabled and auto-removes expired exceptions.
trigger_registry is real and populated: 107 rows. Schema includes code, trigger_name, table_name, trigger_type, function_name, fires_on, timing, enabled, _dot_origin, status. Has birth_trigger_trigger_registry, trg_auto_code_trigger_registry, trg_before_birth_gate_trigger_registry.
Q3 — collection_registry current state
Schema (PG):
- ID/audit:
id, status, sort, user_created, date_created, user_updated, date_updated, code(UNIQUE). - Identity:
name, name_en, description, classification, owner. - Collection:
collection_name(NOT NULL, the PG table being registered),group(FK →collection_groups.code),icon, field_count, has_note, purpose. - Governance:
_dot_origin, storage_role, governance_role, source_kind, migration_state, species_code.
Triggers on collection_registry (full enforcement chain):
trg_before_birth_gate_collection_registry→fn_birth_gate()(BEFORE INSERT)trg_auto_code_collection_registry→gen_code_collection_registry()(BEFORE INSERT, auto code COL-NNN)trg_desc_guard_collection_registry→fn_description_birth_guard()(BEFORE INSERT/UPDATE description) — auto-fills empty desc from template + enforces minimum length per gov_role.trg_birth_collection_registry+birth_trigger_collection_registry→fn_birth_registry_auto('code')(AFTER INSERT, auto-writes birth_registry)trg_desc_provenance_collection_registry→fn_auto_label_provenance()(AFTER INSERT)trg_label_assign_collection_registry→fn_auto_label_assignment()trg_validate_dot_origin_collection_registry→fn_validate_dot_origin()(BEFORE INSERT/UPDATE_dot_origin)trg_refresh_collection_count,trg_refresh_orphan_col→ view refresh triggers.
Convention values currently in use (DISTINCT live values):
governance_role:governed,observed,excluded,locked,law_artifact.migration_state:unclassified,pilot,classified,registered.source_kind:pg_table,native,derived,policy,registry,infrastructure,aggregation,<empty>.
IU rows: information_unit and unit_version are NOT in collection_registry (0 rows).
Q4 — IU presence in other registries
| Registry | information_unit |
unit_version |
|---|---|---|
pg_tables (raw PG) |
EXISTS | EXISTS (also tac_unit_version exists separately) |
collection_registry |
MISSING | MISSING |
birth_registry |
MISSING (0 rows) | MISSING (0 rows) |
meta_catalog |
MISSING | MISSING |
directus_collections |
MISSING | MISSING |
→ The two PG tables are completely outside catalog/registry governance. This is the audit gap Pack 2A is meant to close. Must be closed via DOT, not raw SQL.
Q5 — TRIGGER-GUARD mechanism
It is NOT just log-WARNING. Architecture is whitelist-by-exception (NT-11):
- Tầng 1 (real-time): PG event triggers
evt_trigger_guard_ddl(ddl_command_end) andevt_trigger_guard_drop(sql_drop) — both currently enabled. They fire automatically on schema change events. - Tầng 2 (cron enforcement):
dot-trigger-guardscript runs periodically; readspg_event_triggerself-check (must have ≥2 active), enforcestrigger_guard_exceptions(withtemporary_untilexpiry), writes alerts totrigger_guard_alerts. - Convention: empty
trigger_guard_exceptions⇒ ALL triggers must be ON. Exceptions are temporary and auto-expire.
The event-trigger function bodies (fn_trigger_guard_ddl, fn_trigger_guard_drop) were not extracted in this read-only pass — recommend a follow-up read of the function definitions before any future trigger work that might touch the DDL guard. But the existence of trigger_guard_exceptions + alerts table + the cron tool establishes that this is a real registry-driven governance layer, not just logging.
Additional active gates on registry tables:
fn_birth_gate()— BEFORE INSERT on collection_registry/meta_catalog/trigger_registry. Has KILL SWITCH (app.bypass_birth_gate) and mode (warningdefault vsblocking). Callsfn_pre_birth_check(table, code, name, origin)→ 5 birth checks; failures either WARNING or BLOCKED depending on mode.fn_description_birth_guard()— auto-fills description fromdot_configtemplates (4-tier: per-table+level → per-table → per-level → default) forgovernedrows when empty; enforces description min-length policy per gov_role (Đ4 §2.1).fn_validate_dot_origin()— validates_dot_originvalue (DOT name vs DIRECTUS vs ADMIN).
Q6 — Admin fallback infrastructure
Fully exists and is governed.
admin_fallback_log schema (PG):
id, dot_code (NOT NULL), reason, backup_path, patch_diff, verify_evidence (jsonb), approved_by (default 'president'), session_code, statusstatusCHECK ∈ {applied,retroactive_documented,audit_overdue,rolled_back}retroactive_apr_idFK →approval_requests(id)retroactive_deadlinedefaultnow() + 24h- Trigger
trg_auto_apr_on_fallbackAFTER INSERT →fn_auto_apr_on_fallback()(auto-creates linked APR draft).
approval_requests schema (PG): full table — id, code, request_type, entity_type, entity_code, title, current_state(jsonb), proposed_action(jsonb), alternative_actions(jsonb), evidence, source, priority, status, reviewed_by, reviewed_at, review_note, applied_at, action, target_collection, target_entity_code, source_context.
→ ADMIN fallback flow is wired and audited per Đ35 v5.2: fallback INSERT → auto APR draft → 24h retroactive deadline → cron flips to audit_overdue if not documented.
Q7 — Options for IU-0 (register information_unit + unit_version)
| # | Option | Verdict | Notes |
|---|---|---|---|
| A | Use dot-collection-register (write mode, no --dry-run) for both information_unit and unit_version, supplying explicit --storage_role / --governance_role / --source_kind / --migration_state / --description per Đ36 v4.0. |
LEGAL — preferred. | Goes through Đ4 §2 birth-process tool. All BEFORE/AFTER triggers (fn_birth_gate, fn_description_birth_guard, gen_code_collection_registry, fn_birth_registry_auto) fire automatically — auto-populates birth_registry. Tool is registered in dot_tools (DOT_COLLECTION_REGISTER, status=active, paired with DOT-HEALTH-DOT). Verify with dot-collection-health afterward. |
| B | Run the full 9-step dot-collection-create flow if/when a fresh IU collection is needed and Directus exposure (file 09 §6.2 step 7) must also happen. |
LEGAL — but check first whether PG tables already exist. | The PG tables already exist; running create on existing tables may need an --existing mode. If unavailable, B is stronger than A only when Directus collection registration must happen in same protocol. Confirm with current state of dot-collection-create source before dispatch. |
| C | After A: run dot-schema-trigger-registry-ensure + dot-trigger-guard to backfill any IU triggers into trigger_registry and validate the trigger-guard layer. |
LEGAL — recommended follow-up. | Closes Q4/Q5 gap for IU-derived triggers (e.g., birth_trigger_information_unit, if/when birth-trigger-setup deploys for governed IU rows). |
| D | Backfill via dot-birth-backfill for any pre-existing rows in information_unit/unit_version so they appear in birth_registry. |
LEGAL — recommended follow-up. | Đ0-G compliance. |
| E | Raw SQL INSERT INTO collection_registry ... |
BLOCKED. | Violates Đ4 §2 (must use DOT/script), Đ2 (registry/tooling principle), Đ35 (DOT-first), Đ36 (collection protocol), file 09 §6 (DOT-COLLECTION-CREATE 9-step). No tool gap justifies this — dot-collection-register exists, is active, and is paired. |
| F | ADMIN fallback (insert admin_fallback_log row with reason "tool failure", patch raw, retroactive APR within 24h). |
LEGAL IF APPROVED — but unjustified now. | Prereq per Đ35 v5.2: dot_code of failing tool, reason, backup_path, patch_diff, verify_evidence, explicit User/GPT approval. None of those preconditions are met because no tool failure has been demonstrated. Do NOT preemptively choose F. |
| G | Build a new DOT (e.g., DOT-IU-REGISTER) before registering. | UNKNOWN — only if A/B/C-D prove insufficient after design. | Per Đ20 design-before-execute, this would require a written design + approval. Premature given existing tools. |
Final recommendation
Default path = Option A + Option C + Option D, in that order.
Pack 2B prompt should:
dot-collection-register information_unit --storage_role <X> --governance_role <Y> --source_kind <Z> --migration_state <W> --description "..." --cloud- Same for
unit_version. - Verify by querying
collection_registry+birth_registry(auto-populated by triggers). - Run
dot-collection-health --cloudto confirm Đ36 GP8.1 HC-REG/HC-SCHEMA passes. - Run
dot-schema-trigger-registry-ensure --cloud+dot-trigger-guard --cloudto capture any IU triggers. - Run
dot-birth-backfill --cloudif pre-existing IU rows lack birth_registry entries.
If any step fails with a tool-side defect, that is the moment to choose between F (ADMIN fallback with full prereqs) or G (build proper tool) — never preemptively raw-SQL.
Read-only commands actually executed (audit trail)
All commands ran on VPS 38.242.240.89 via ssh contabo. No DDL, no INSERT/UPDATE/DELETE. No DOT executed.
ssh contabo "ls /opt/incomex/dot/bin/ | grep -iE 'col|register|trigger|ddl|audit|guard|birth'"
ssh contabo "ls /opt/incomex/scripts/ | grep -iE 'col|register|trigger|ddl|audit|guard|birth'"
ssh contabo "head -40 /opt/incomex/dot/bin/<each candidate>"
docker exec postgres psql -U directus -d directus -c "\d dot_tools"
docker exec postgres psql -U directus -d directus -c "SELECT code,status,tier,paired_dot,coverage_status,description FROM dot_tools WHERE code ~* '(col|trigger|register|audit|guard|ddl|birth)' ORDER BY code;"
docker exec postgres psql -U directus -d directus -c "\d collection_registry / \d birth_registry / \d meta_catalog / \d admin_fallback_log / \d trigger_registry / \d approval_requests"
docker exec postgres psql -U directus -d directus -c "SELECT ... FROM collection_registry WHERE collection_name IN ('information_unit','unit_version');" -- 0 rows
docker exec postgres psql -U directus -d directus -c "SELECT ... FROM birth_registry WHERE collection_name IN (...);" -- 0 rows
docker exec postgres psql -U directus -d directus -c "SELECT ... FROM meta_catalog WHERE source_model IN (...);" -- 0 rows
docker exec postgres psql -U directus -d directus -c "SELECT collection FROM directus_collections WHERE collection IN (...);" -- 0 rows
docker exec postgres psql -U directus -d directus -c "SELECT tablename FROM pg_tables WHERE ...;"
docker exec postgres psql -U directus -d directus -c "SELECT evtname, evtenabled, evtevent FROM pg_event_trigger;"
docker exec postgres psql -U directus -d directus -c "SELECT DISTINCT governance_role / migration_state / source_kind FROM collection_registry;"
docker exec postgres psql -U directus -d directus -c "SELECT count(*) FROM trigger_registry;" -- 107
docker exec postgres psql -U directus -d directus -c "SELECT proname, pg_get_functiondef(oid) FROM pg_proc WHERE proname IN ('fn_birth_gate','fn_description_birth_guard');"
HARD STOP
Per dispatch directive: report uploaded. No writes. No Pack 2B/2C. Awaiting User/GPT decision on Option A path.