IU-0 Pack 2A — Description/Birth Contract Discovery (READ-ONLY)
IU-0 Pack 2A — Description/Birth Contract Discovery (READ-ONLY)
Date: 2026-05-04 Scope: Read-only runtime evidence for description/birth contract of
dot-collection-registerandcollection_registry. No INSERT/UPDATE/DELETE, no DDL, no DOT execution. VPS: 38.242.240.89 (contabo). DB: postgres container, directus database.
Pre-reads completed: law-03-metadata, dieu3-phu-luc-description-templates, law-04-birth-process, dieu35-dot-governance-law, dieu36-collection-protocol-law, dieu20-thiet-ke-truoc-trien-khai, file 12 (Pack 2A design), GPT review of file 12.
Q1. dot-collection-register contract
Raw evidence — header + usage (verbatim, lines 1–60)
#!/usr/bin/env bash
# =============================================================================
# dot-collection-register — Register a collection in collection_registry
# =============================================================================
# CHECKED-NO-DUPLICATE: [searched dot/bin/dot-*register* — no collection register tool]
# VERSION: 1.1.0
# §0-E DOT-FIRST: All governance declarations MUST go through DOT tools.
#
# CHANGELOG:
# v1.1.0 (2026-03-21): S157-A — add --update mode (upsert)
# v1.0.0: Initial — create-only, skip if exists
#
# Usage:
# dot-collection-register <collection_name> [options]
#
# Options:
# --update Update existing record (upsert mode)
# --storage_role X primary|junction|log|system
# --governance_role Y governed|observed|excluded
# --source_kind Z registry|native|derived|policy
# --migration_state W unclassified|classified|pilot|stable (default: unclassified)
# --description D Description text
# --cloud|--local Environment selection
# --dry-run Show what would be done
# --help, -h Show help
#
# Examples:
# dot-collection-register dot_tools --storage_role primary --governance_role governed
# dot-collection-register some_table # → COL-NNN, migration_state=unclassified
# dot-collection-register dot_tools --update --governance_role governed # upsert
Raw evidence — write path (POST + PATCH via Directus REST API)
INSERT (lines ~205–224):
RESP=$(curl -sS --globoff -k -X POST "${BASE_URL}/items/collection_registry" \
-H "Authorization: Bearer $DOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" -w "\n%{http_code}")
UPDATE (lines ~148–151):
PATCH_RESP=$(curl -sS --globoff -k -X PATCH "${BASE_URL}/items/collection_registry/${EX_ID}" \
-H "Authorization: Bearer $DOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$PATCH_PAYLOAD" -w "\n%{http_code}")
INSERT payload only sets these fields (lines ~204–219):
{ code, name, collection_name, status:"active", migration_state }
+ optional: description, storage_role, governance_role, source_kind
Auto-generates COL-NNN by reading ?sort=-code&limit=1 and incrementing.
Interpretation
- Accepts
--description✅,--governance_role✅,--source_kind✅,--migration_state✅,--storage_role✅. - Has
--updatemode (upsert/PATCH). - Writes via Directus REST API (
/items/collection_registry) — NOT raw SQL. Auth viaDOT_TOKEN. - Does NOT pass
species_code,_dot_origin, or any explicit provenance label — relies on triggers. - Has truncation read-back diagnostic post-write (TD-334).
Unknowns
- No
--unregister,--rollback, or--deleteflag in source. Q5 confirms no separate DOT tool either. - INSERT payload always sets
status:"active"— no flag to override.
Q2. Runtime description enforcement
Raw evidence — dot_config keys
key | value
-------------------------------------------+-------------------------------------------------------------------------------------------
description_enforcement_mode | warn
description_min_length | 30
desc_template_collection_registry | [{governance_role}] Collection {code}. Loài: {species_code}.
desc_template_default | [{status}] {_table_display_name}: {_identifier}. Lớp: {composition_level}.
desc_template_dot_config | Config key điều khiển {key}.
desc_template_dot_domains | Domain [{code}] quản lý phạm vi {name}.
desc_template_dot_operations | [{code}] Operation: {name}.
desc_template_dot_tools | [{tier}] [{domain}] {trigger_type} trigger. Operation: {operation}. Paired: {paired_dot}.
desc_template_entity_species | Loài [{code}] thuộc lớp {composition_level}.
desc_template_level_atom | [{status}] Nguyên tử {code} trong {_source_table}.
desc_template_level_compound | [{status}] Hợp chất {code} trong {_source_table}.
desc_template_level_molecule | [{status}] Phân tử {code} trong {_source_table}.
dot_tools_description_min_length | 50
hc_heal_description_basic_autofix_enabled | true
(14 rows)
No collection_registry_description_min_length row — only the global default of 30 applies to collection_registry.
Raw evidence — fn_description_birth_guard body (key excerpts)
DECLARE _mode TEXT; _gov_role TEXT; _min_len INT; _table_min INT;
_desc TEXT; _tpl TEXT; _level TEXT; _ctx jsonb;
BEGIN
SELECT governance_role INTO _gov_role
FROM collection_registry WHERE collection_name = TG_TABLE_NAME;
-- Auto-gen when description empty — fires on BOTH INSERT and UPDATE OF description.
-- NT9: only fill when empty, never overwrite non-empty. Caller's UPDATE SET desc=''
-- is an explicit regeneration request (intentional clear → auto-heal).
IF _gov_role = 'governed' THEN
_desc := btrim(COALESCE((to_jsonb(NEW)->>'description')::text, ''));
IF _desc = '' THEN
_ctx := fn_description_context(TG_TABLE_NAME, to_jsonb(NEW));
_level := _ctx->>'composition_level';
-- Đ3 §2.6: 4-tier lookup
-- 1) desc_template_<table>_<level>
-- 2) desc_template_<table>
-- 3) desc_template_level_<level>
-- 4) desc_template_default
IF _tpl IS NOT NULL THEN
NEW.description := fn_render_description_template(_tpl, _ctx);
END IF;
END IF;
END IF;
-- Original C1-C3 enforcement
SELECT value INTO _mode FROM dot_config WHERE key='description_enforcement_mode'; -- default 'warn'
SELECT value::int INTO _min_len FROM dot_config WHERE key='description_min_length'; -- default 30
SELECT value::int INTO _table_min FROM dot_config WHERE key=TG_TABLE_NAME||'_description_min_length';
IF _gov_role IS NULL THEN
-- block raises exception, warn raises warning
END IF;
IF _gov_role = 'excluded' THEN RETURN NEW; END IF;
_desc := btrim(...);
IF _desc = '' OR length(_desc) < _min_len
OR _desc ~ '^(.)\1{9,}$' OR _desc ~ '^[.\-_\s]{10,}$' THEN
IF _gov_role='governed' AND _mode='block' THEN
RAISE EXCEPTION 'Đ4 §2.1 + Đ3 §2.1: ... description >= % ký tự, không gaming.', _min_len;
END IF;
END IF;
RETURN NEW;
END;
Interpretation
- Auto-gen ONLY for
governance_role='governed'AND empty description. Uses 4-tier lookup; forcollection_registryTier 2 hitsdesc_template_collection_registry. - Mode is currently
warnglobally — empty/short descriptions WARN but do NOT block (except gaming patterns or governed+block). - Min length default 30; no per-table override for
collection_registry.dot_toolshas 50. - Fires BEFORE INSERT and BEFORE UPDATE OF description.
- Auto-heal only when
descis empty after btrim — non-empty existing descriptions are never overwritten.
Unknowns
- The auto-gen path requires
_gov_role='governed'. Forgovernance_role='observed'or NULL, empty description passes through without fill (then enforcement is just a warning). Confirms that Pack 2A must pass an explicit--descriptionfor any non-governed collection. desc_template_collection_registryreferences{species_code}— butspecies_codeis set viaspecies_collection_map, not oncollection_registrydirectly. Auto-gen rendering of{species_code}for a freshly registered collection without a species mapping is unverified in this read-only pack.
Q3. Convention — top descriptions in collection_registry
Raw evidence
collection_name | governance_role | description
------------------------------+-----------------+----------------------------------------------------------------------------
kb_documents_history | observed | Version history snapshots for KB documents. Auto-populated by PG triggers.
kb_audit_log | observed | Audit trail for all KB write operations. Auto-populated by PG triggers.
directus_fields | observed | Directus fields system table. System observed — overlay only.
entity_labels | excluded | Junction table gan nhan cho entities. Junction governed.
admin_fallback_log | law_artifact | Admin fallback log (D35 6.5) - retroactive APR tracking
law_version_verification_log | law_artifact | Law version verification log (HP) - pre-enact checks
apr_action_types | governed | Catalog of APR proposed actions (Dieu32 v1.1 §3.2)
categories | excluded | [excluded] Collection COL-032. Loài: collection.
block_cta | excluded | [excluded] Collection COL-012. Loài: collection.
contacts | observed | [observed] Collection COL-037. Loài: collection.
(10 rows)
Interpretation
- Hand-written descriptions (governed, observed, law_artifact rows at top): functional purpose + key cross-reference. Style:
{Purpose}. {Source/scope/law citation}. - Auto-generated descriptions (rows 8–10, prefix
[excluded]/[observed]): matchdesc_template_collection_registryformat[{governance_role}] Collection {code}. Loài: {species_code}.— exactly the auto-gen template output. - Convention difference governed vs observed: governed authors describe purpose ("Catalog of APR proposed actions (Dieu32 v1.1 §3.2)"); observed often describe origin/system role ("System observed — overlay only").
Unknowns
- The handwritten governed examples are short (≤80 chars). No long-form (≥150 char) examples surface in the top-10. Likely indicates no rich, prose-style governed descriptions exist yet — or none meet length cutoff that highly. (Cannot infer maximum convention without running a different query.)
law_artifactis a 4th observed governance_role value not in the--governance_roleflag whitelist (governed|observed|excluded). UNKNOWN — needs design decision whether IU-0 needs that role.
Q4. Birth trigger chain on collection_registry
Raw evidence
trigger_name | action_timing | event_manipulation | action_statement
---------------------------------------------+---------------+--------------------+-------------------------------------------------
trg_before_birth_gate_collection_registry | BEFORE | INSERT | EXECUTE FUNCTION fn_birth_gate()
trg_auto_code_collection_registry | BEFORE | INSERT | EXECUTE FUNCTION gen_code_collection_registry()
trg_desc_guard_collection_registry | BEFORE | INSERT | EXECUTE FUNCTION fn_description_birth_guard()
trg_desc_guard_collection_registry | BEFORE | UPDATE | EXECUTE FUNCTION fn_description_birth_guard()
trg_validate_dot_origin_collection_registry | BEFORE | INSERT | EXECUTE FUNCTION fn_validate_dot_origin()
trg_validate_dot_origin_collection_registry | BEFORE | UPDATE | EXECUTE FUNCTION fn_validate_dot_origin()
birth_trigger_collection_registry | AFTER | INSERT | EXECUTE FUNCTION fn_birth_registry_auto('code')
trg_birth_collection_registry | AFTER | INSERT | EXECUTE FUNCTION fn_birth_registry_auto('code')
trg_desc_provenance_collection_registry | AFTER | INSERT | EXECUTE FUNCTION fn_auto_label_provenance()
trg_label_assign_collection_registry | AFTER | INSERT | EXECUTE FUNCTION fn_auto_label_assignment()
trg_label_assign_collection_registry | AFTER | UPDATE | EXECUTE FUNCTION fn_auto_label_assignment()
trg_count_collection_registry | AFTER | INSERT | EXECUTE FUNCTION refresh_registry_count()
trg_count_collection_registry | AFTER | UPDATE | EXECUTE FUNCTION refresh_registry_count()
trg_count_collection_registry | AFTER | DELETE | EXECUTE FUNCTION refresh_registry_count()
trg_refresh_collection_count | AFTER | INSERT | EXECUTE FUNCTION fn_refresh_collection_count()
trg_refresh_collection_count | AFTER | DELETE | EXECUTE FUNCTION fn_refresh_collection_count()
trg_refresh_orphan_col | AFTER | INSERT | EXECUTE FUNCTION trg_fn_refresh_orphan_col()
trg_refresh_orphan_col | AFTER | DELETE | EXECUTE FUNCTION trg_fn_refresh_orphan_col()
(18 rows)
Interpretation — INSERT chain
- BEFORE INSERT (alphabetical order by trigger name unless explicitly ordered):
trg_auto_code_collection_registry→gen_code_collection_registry()(assigns COL-NNN if not provided)trg_before_birth_gate_collection_registry→fn_birth_gate()(Đ4 gate)trg_desc_guard_collection_registry→fn_description_birth_guard()(auto-fill from template if governed+empty; warn/block on min-length)trg_validate_dot_origin_collection_registry→fn_validate_dot_origin()(Đ0-E DOT-first)
- AFTER INSERT:
birth_trigger_collection_registryANDtrg_birth_collection_registry(DUPLICATE — both callfn_birth_registry_auto('code'))trg_desc_provenance_collection_registry→fn_auto_label_provenance()(assigns PROV-* label)trg_label_assign_collection_registry→fn_auto_label_assignment()trg_count_collection_registry,trg_refresh_collection_count,trg_refresh_orphan_col(counters/views)
Auto-gen confirmation
fn_description_birth_guardauto-fills description fromdesc_template_collection_registryIFgovernance_role='governed'AND description empty after btrim. Forobserved/excluded/NULL: NO auto-fill, just min-length warn.- The 4-tier template lookup means even if
desc_template_collection_registrywere absent, fallback todesc_template_defaultwould apply (still only for governed).
Birth record
fn_birth_registry_auto('code')will fire and create a birth record for the inserted collection_registry row itself, on key=code(i.e., COL-NNN).
Unknowns
- Duplicate AFTER INSERT triggers
birth_trigger_collection_registryandtrg_birth_collection_registryboth invoke the same function. UNKNOWN if intentional double-write or legacy artifact — needs design decision/cleanup but does not block Pack 2A. - Trigger ordering within same timing+event is alphabetical by name in PostgreSQL — so
trg_auto_coderuns beforetrg_before_birth_gateruns beforetrg_desc_guard. Cannot confirm explicit ordering directives without checking pg_trigger.tgconstrindid; ordering is consistent with name-alphabetical assumption.
Q5. Rollback tools
Raw evidence — dot_tools matching collection/unregister
code | name
----------------------------------------+----------------------------------------
DOT_COLLECTION_CREATE | dot-collection-create
DOT_COLLECTION_FIELD_SYNC | dot-collection-field-sync
DOT_COLLECTION_HEALTH | dot-collection-health
DOT_COLLECTION_REGISTER | dot-collection-register
DOT_SCHEMA_REGISTRY_COLLECTIONS_ENSURE | dot-schema-registry-collections-ensure
DOT-TAC-COLLECTION-REGISTER | TAC Collection Register
DOT-TAC-COLLECTION-VERIFY | TAC Collection Verify
(7 rows)
ls /opt/incomex/dot/bin/ | grep -i -E 'collection|register|unregister' returned no *unregister* script.
dot-collection-register --help source has no --unregister / --rollback / --delete flag (header verified verbatim, Q1).
Interpretation
- No DOT tool exists for unregistering / deleting / rolling back a collection_registry row.
- Rollback in Pack 2A must rely on either (a) a future DOT tool to be designed, or (b) raw
DELETE FROM collection_registry WHERE code='COL-NNN'— which would violate Đ0-E DOT-first.
Unknowns
- UNKNOWN — needs design decision: should Pack 2A include a
dot-collection-unregistercompanion, or is rollback explicitly out of scope (forward-only registration)? GPT review of file 12 likely flags this; deferring to law council.
Q6. Species for IU
Raw evidence — entity_species (40 rows)
code | species_code | display_name | composition_level
---------+---------------------+--------------------+-------------------
SPE-AGT | agent | Agent | atom
SPE-AIS | ai_support | Hỗ trợ AI | atom
SPE-APP | approval_request | Yeu cau phe duyet | compound
SPE-BLK | cms_block | CMS Block | atom
SPE-BZS | business_support | Hỗ trợ Kinh doanh | molecule
SPE-CAT | catalog | Danh muc he thong | atom
SPE-CKS | checkpoint_support | Hỗ trợ Checkpoint | molecule
SPE-COL | collection | Collection | molecule
SPE-CPS | checkpoint_set | Bo checkpoint | molecule
SPE-CPT | checkpoint_type | Loai checkpoint | atom
SPE-DEP | dependency | Phu thuoc | atom
SPE-DOT | dot_tool | DOT Tool | atom
SPE-DXF | directus_field | Directus Field | atom
SPE-ENF | law_enforcement | Thực thi DOT-Luật | atom
SPE-ERL | entity_rule | Quy tac thuc the | atom
SPE-FAC | label_facet | Chieu phan loai | atom
SPE-GAG | governance_agency | Cơ quan Quản trị | compound
SPE-GOV | governance_infra | Hạ tầng Giám sát | atom
SPE-GRL | governance_relation | Liên kết Quản trị | atom
SPE-HLP | help_center | Trung tâm Trợ giúp | molecule
SPE-ISS | system_issue | Van de he thong | atom
SPE-JCT | junction_table | Bảng Liên kết | atom
SPE-JUR | jurisdiction | Phạm vi Pháp lý | atom
SPE-LAW | law | Văn bản Luật | compound
SPE-LBL | entity_label | Entity Label | atom
SPE-LBR | label_rule | Quy tac gan nhan | atom
SPE-LOG | system_log | Nhật ký Hệ thống | atom
SPE-MOD | module | Module | compound
SPE-OSC | os_crm | OS CRM | compound
SPE-PGE | page | Trang UI | molecule
SPE-PGW | website_page | Trang Website | molecule
SPE-PVR | pivot_result | Ket qua Pivot | molecule
SPE-SPE | species | Loai | meta
SPE-SYS | system_backup | Hệ thống/Backup | atom
SPE-TBL | table_ui | Bang UI | molecule
SPE-TSK | task | Nhiem vu | compound
SPE-WCR | wcr | De xuat thay doi | compound
SPE-WEB | website_content | Nội dung Website | molecule
SPE-WFS | workflow_step | Buoc quy trinh | molecule
SPE-WKF | workflow | Quy trinh | compound
(40 rows)
Raw evidence — species_collection_map for IU
id | sort | ... | species_code | collection_name | is_primary | discriminator_field | ...
----+------+-----+--------------+-----------------+------------+---------------------+----
(0 rows)
Interpretation
- No species exists for
information_unitorunit_version. Closest semantic candidates: SPE-WEB (website_content, molecule) or SPE-MOD (module, compound) — but neither matches IU's intended semantics. species_collection_mapfor IU collections is empty (expected — IU not yet registered).
Unknowns
- UNKNOWN — needs design decision: must Pack 2A create a new species (e.g.,
SPE-IUNinformation_unit, level=compound or molecule) BEFORE registering the IU collections? Đ4 / Đ36 likely require species mapping for governed collections. Cannot infer composition_level for IU from existing evidence.
Q7. storage_role convention
Raw evidence
storage_role
--------------
junction
system
pg_only
log
primary
derived
(6 rows)
collection_name | storage_role | governance_role
-------------------------+--------------+-----------------
dot_domain_rules | primary | governed
field_type_equivalences | primary | governed
governance_audit_log | primary | observed
law_jurisdiction | primary | governed
pivot_results | derived | observed
dot_tools | primary | governed
governance_registry | primary | governed
governance_relations | primary | governed
law_dot_enforcement | primary | governed
normative_registry | primary | governed
(10 rows)
Interpretation
- Six storage_role values in use:
primary,junction,log,system,derived,pg_only. dot-collection-register --helpwhitelist:primary|junction|log|system— DOES NOT includederivedorpg_only. Those values entered DB by other paths (raw SQL or earlier tool versions). Tool's whitelist is narrower than DB reality.- Governed core tables →
primary. Cross-link tables →junction. Audit/log →log. Computed views →derived. PG-only gov tables →pg_only(per S178 Fix 20 M3B memory).
Unknowns
- For IU:
unit_versionlikelyprimary(orlogif append-only history).information_unit→primary. Cannot finalize without IU schema design (Pack 2C territory). - Tool whitelist gap (
derived,pg_onlymissing) is pre-existing tech debt — not blocking Pack 2A but may need flag widening if any IU child collection lands asderived.
Q8. Write path — Directus API or SQL?
Raw evidence
See Q1 raw evidence: curl -X POST/PATCH "${BASE_URL}/items/collection_registry". BASE_URL=$DIRECTUS_URL. Auth Bearer $DOT_TOKEN (DOT auth, see dot-auth).
No psql, no SQL string, no docker exec postgres anywhere in the script.
Interpretation
- Writes go through Directus REST API (
/items/collection_registry). Compliant with Đ7 ("Nghĩ PG, làm qua Directus") and Đ0-H (DOT routes through Directus where possible). - Audit trail = Directus
directus_activity(Directus auto-logs item ops by token user) + PG triggers (fn_birth_registry_auto,fn_auto_label_provenance,fn_auto_label_assignment,refresh_registry_count). - Truncation read-back diagnostic post-write (TD-334).
Unknowns
- Whether
directus_activityactually captures the DOT_TOKEN's writes with role attribution sufficient for Đ35 audit needs is not verified in this pack (out of scope).
Q9. Provenance for description
Raw evidence (first 20 collection_registry codes)
entity_code | label_code
-------------+------------
COL-001 | PROV-DOT
COL-002 | PROV-DOT
COL-003 | PROV-DOT
COL-004 | PROV-DOT
COL-005 | PROV-DOT
COL-006 | PROV-DOT
COL-007 | PROV-DOT
COL-008 | PROV-DOT
COL-009 | PROV-DOT
COL-010 | PROV-DOT
COL-011 | PROV-DOT
COL-012 | PROV-DOT
COL-013 | PROV-DOT
COL-014 | PROV-DOT
COL-015 | PROV-DOT
COL-016 | PROV-DOT
COL-017 | PROV-DOT
COL-018 | PROV-DOT
COL-019 | PROV-DOT
COL-020 | PROV-DOT
(20 rows)
Interpretation
- All 20 sampled collection_registry rows carry
PROV-DOT(and only PROV-DOT among the prov-* set). Assigned byfn_auto_label_provenance(AFTER INSERT trigger) — based on_dot_originfield default. No PROV-AI / PROV-HUMAN labels found among the sample. - Đ3 distinction: PROV-DOT description = basic/auto. To attach PROV-AI or PROV-HUMAN description provenance, the writing path must explicitly mark provenance —
dot-collection-registerdoes NOT pass any provenance flag, so any description supplied via--descriptionstill ends up tagged PROV-DOT (because the trigger uses_dot_origin, not description origin).
Unknowns
- UNKNOWN — needs design decision: when Pack 2A calls
dot-collection-register --description "<AI-authored>", the description provenance will be mislabeled as PROV-DOT. To honor Đ3 PROV-AI distinction, either (a) extenddot-collection-registerwith a--description-provenanceflag and a follow-up label write, or (b) accept PROV-DOT for all DOT-channel writes and document this convention. GPT review of file 12 likely raises this point. - Cannot read 21+ rows in this query — sample is the first 20 by registry insertion order. No counter-example in sample.
Summary of design decisions still required (NOT decided here)
- Q5: Rollback strategy — add
dot-collection-unregistercompanion or declare forward-only? - Q6: Create new species (e.g.,
SPE-IUN information_unit, composition_level=?) before registering IU collections? - Q7: Storage role for
information_unit/unit_version(probablyprimary, but pending IU schema spec). - Q9: Description provenance labeling — accept PROV-DOT for all DOT-channel writes, or extend tool to support PROV-AI/PROV-HUMAN tagging?
- Q4 cleanup: Duplicate AFTER INSERT triggers
birth_trigger_collection_registryvstrg_birth_collection_registry— pre-existing tech debt; not blocking but should be logged. - Q3: governance_role
law_artifactexists in DB but not in tool whitelist. UNKNOWN if IU needs it. - Q7 tech-debt: tool whitelist missing
derived,pg_only.