KB-4893
S176-INVESTIGATE K1 — L1 Official Channels (DOT tools ghi PG)
20 min read Revision 1
s176investigateddldmlphaseCk1official-channels
title: "S176-INVESTIGATE K1 — L1 Chính thức: DOT tools ghi PG" sprint: S176 phase: INVESTIGATE block: K1 date: 2026-04-13 status: done tags: ['s176','investigate','ddl','dml','phaseC','k1','official-channels']
S176-INVESTIGATE · K1 — L1 Chính thức (DOT tools ghi PG)
Mục tiêu: trả lời "AI ghi PG qua con đường chính thức?" — liệt kê toàn bộ DOT đã đăng ký trong
dot_tools, phân loại DDL/DML, kiểm tra pattern an toàn và tỉ lệ DOT cặp NT12. Chế độ: CHỈ ĐỌC. Không GRANT/REVOKE/ALTER.
1. Tổng quan dot_tools (272 records)
Phương pháp
GET /items/dot_tools?limit=-1qua Directus REST (token admin login).- Field trả về:
code, tier, domain, operation, paired_dot, trigger_type, script_path, file_path, last_executed, coverage_status, status. - Đối chiếu từng record với file thật tại
dot/bin/(cloud branch) bằng cross-ref basename.
Phân phối
| Thuộc tính | Giá trị | Ghi chú |
|---|---|---|
| Tổng | 272 | Bao gồm cả trùng (xem #4) |
| Tier A (kiểm tra) | 49 | Theo lý thuyết = writer verifier |
| Tier B (hành động) | 223 | Writer |
status=active |
256 | |
status=published |
16 | |
file_path set |
212/272 (78%) | 60 record KHÔNG có file_path |
script_path set |
119/272 (44%) | Redundant với file_path |
paired_dot set |
107/272 (39%) | NT12 gap — xem #5 |
last_executed set |
157/272 (58%) | 157/157 = cùng một timestamp 2026-03-31T08:08:57.064Z → bulk backfill, KHÔNG phải run log thật |
coverage_status = complete |
13/272 (5%) | partial=158, ∅=101 |
Domain top 10
collection=49 infrastructure.schema=38 infrastructure.sync=20 sync=16
monitoring.integrity=15 infrastructure.deploy=15 lifecycle=11 normative=11
workflow=10 data_quality=8 pivot=8 kg.*=34
Trigger type
∅=203 on-demand=31 cron=28 dual=4 manual=3 event=2 on-deploy=1
→ 203/272 (75%) record KHÔNG khai trigger_type — coverage metadata yếu.
2. Phân loại theo con đường ghi PG
2.1 Con đường A — Directus REST API (/items/<collection>)
- ~56 file trong
dot/bin/dùngcurl/items//directus.*_item→ Directus là gateway; Directus tự viết PG. - Đây mới là "L1 chính thức" theo NT13 "PG FIRST" + 5 tầng đồng bộ PG→Directus→Nuxt (Directus là cổng).
- Mẫu:
dot-collection-register,dot-task-*,dot-species-*,dot-registry-*,dot-nav-*,dot-content-*,dot-audit-create,dot-layer-integrity-audit,dot-id-collision-check,dot-knowledge-sync*.
2.2 Con đường B — Trực tiếp PG (run_pg() → psql → docker exec postgres)
- 12 script trực tiếp gọi psql. Pattern chuẩn:
run_pg() { ssh root@VPS 'cd /opt/incomex/docker && docker compose exec -T postgres psql -U directus -d directus'; } - Với DDL bootstrap: chấp nhận được (L2 Tắt hợp lệ tạm) nếu có vòng đời retire.
- Với DML runtime: đi vòng qua Directus → rủi ro bypass (L3 về bản chất, dù DOT có đăng ký).
| # | Script | DOT code | Tier | Domain | Op | paired_dot | Nội dung chính | DDL cnt | Loại |
|---|---|---|---|---|---|---|---|---|---|
| 1 | dot-schema-taxonomy-pg-apply |
DOT-143 + DOT_SCHEMA_TAXONOMY_PG_APPLY (trùng) |
B | infrastructure.schema (num) / collection (sem) | — | None / DOT-HEALTH-DOT |
CREATE TYPE, ALTER TABLE, CREATE INDEX, CREATE OR REPLACE FUNCTION (system_issues, registry_*) | 28 | DDL |
| 2 | dot-pg-views-ensure |
DOT-129 | B | infrastructure.schema | — | None | CREATE OR REPLACE VIEW (v_registry_counts v.v.) | 12 | DDL |
| 3 | dot-pg-triggers-ensure |
DOT-128 | B | infrastructure.schema | — | None | CREATE TRIGGER | 6 | DDL |
| 4 | dot-pg-audit-ensure |
DOT-127 | B | infrastructure.schema | — | None | CREATE TABLE audit + fn_audit + trigger | 4 | DDL |
| 5 | dot-label-trigger-setup |
DOT-123 | B | classification.label | — | None | CREATE TRIGGER label | 2 | DDL |
| 6 | dot-entity-retire |
DOT-112 | B | lifecycle | — | None | SELECT fn_transition_lifecycle(...) — DML qua function |
0 | DML (gateway) |
| 7 | dot-entity-deprecate |
DOT-111 | B | lifecycle | — | None | SELECT fn_transition_lifecycle(...) |
0 | DML (gateway) |
| 8 | dot-production-truth-gate |
DOT-109 | B | monitoring.integrity | — | None | psql SELECT (read-only?) | 2 | SELECT chủ yếu |
| 9 | dot-coverage-inspector |
DOT-110 | A | monitoring.integrity | — | None | run_pg SELECT |
2 | Checker (ĐÚNG tier) |
| 10 | dot-cron-pivot-setup |
DOT-308 | B | pivot | — | None | Cài cron gọi fn_refresh_orphan_* 10 phút/lần |
3 | Cron installer |
| 11 | dot-cron-matrix-setup |
KHÔNG REGISTER | — | — | — | — | Cài cron | 1 | L3 candidate |
| 12 | dot-script-lint |
KHÔNG REGISTER | — | — | — | — | Lint script có gọi psql | 4 | L3 candidate |
2.3 Con đường C — PG function gateway (fn_*)
- 79 function
fn_*đã tồn tại trong schemapublic(pg_proc WHERE proname LIKE 'fn\_%'). - 3 nhóm:
- Guard/validate/enforce (
fn_guard_*,fn_enforce_*,fn_validate_*,fn_nrm_*_gate,fn_law_*_immutable) — trigger-based, bảo vệ invariants. - Reconcile/refresh (
fn_refresh_*,fn_reconcile_*,fn_sync_*) — vật chất hoá cache/count. - Action (
fn_transition_lifecycle,fn_bulk_transition,fn_gov_retire_cascade,fn_law_retire_cascade) — thực sự đổi state.
- Guard/validate/enforce (
- Đã có "phôi" gateway:
fn_transition_lifecycle(collection, entity_id, new_state, reason, source)được dùng bởi DOT-111 + DOT-112. Đây là hạt giống cho Phương án C (Single Writer Gateway) — có thể đóng vai trò cổng duy nhất cho lifecycle transitions, nhưng hiện chỉ bao phủ retire/deprecate, không bao phủ create/update nội dung.
3. Pattern an toàn (anti-duplicate) — NT #14 / §0-AV
Kết quả grep
| Chỉ số | Số lần | Nguồn |
|---|---|---|
ON CONFLICT trong dot/bin/ |
47 occurrences / 29 file | grep |
| File dùng pattern "SELECT-rồi-IF-NOT-FOUND-INSERT" | 12 file (multiline heuristic) | grep |
Tóm lược
- Tất cả script DDL bootstrap (DOT-063..144,
dot-pg-*-ensure) đều dùngCREATE TABLE IF NOT EXISTS+CREATE INDEX IF NOT EXISTS+CREATE OR REPLACE VIEW/FUNCTION→ idempotent DDL, an toàn. dot-pg-audit-ensure,dot-schema-taxonomy-pg-apply,dot-schema-dot-origin-ensure,dot-schema-trigger-registry-ensure,dot-schema-birth-registry-ensuredùng ON CONFLICT DO NOTHING/UPDATE cho seed row → tốt.- 12 file vẫn còn mẫu SELECT-then-INSERT (dot-orphan-scanner, dot-gov-seed, dot-nrm-enact, dot-collection-health, dot-matrix-declare, dot-collection-create, dot-pivot-declare, dot-schema-dot-origin-ensure, dot-birth-trigger-setup, v.v.). Race condition tiềm ẩn dưới tải, vi phạm NT "Nhầm được không?".
- AP-12 risk (DOT verify phải so COUNT(*) thật): chưa check khối này ở K1 — để K4.
Phát hiện bất thường
dot-nrm-amend(không có file_path trong dot_tools nhưng tồn tại trên disk) dùng ON CONFLICT 2 lần — tốt — nhưng ghi trực tiếp PG bên ngoài Directus, vi phạm NT13 tinh thần "PG FIRST nhưng qua Directus".
4. Trùng đăng ký — 2 quy ước đặt tên
Phát hiện
- 42 script bị đăng ký 2 lần trong
dot_tools:- Lần 1 dưới code số:
DOT-063,DOT-064, …DOT-144— đợt sớm, namingDOT-NNN. - Lần 2 dưới code semantic:
DOT_SCHEMA_APPLY,DOT_SCHEMA_BLOG_ENSURE, …DOT_SCHEMA_TAXONOMY_PG_APPLY— đợt sau, namingDOT_UPPER_SNAKE.
- Lần 1 dưới code số:
- Tổng 42 pair × 2 = 84 record thừa. Unique thực tế ≈ 272 − 42 ≈ 230 DOT.
- Không có luật nào quy định cái nào là canonical.
DOT-NNNcólast_executednhồi bulk,DOT_SEMANTICthường cólast_executed=None. - Ví dụ xung đột:
dot-schema-taxonomy-pg-apply= DOT-143 (domaininfrastructure.schema, paired=None) vàDOT_SCHEMA_TAXONOMY_PG_APPLY(domaincollection, paired=DOT-HEALTH-DOT) → 2 bản ghi khác domain, khác paired, khác ý nghĩa.
Hệ quả
- Khi query "DOT nào write bảng X" sẽ đếm trùng.
registry_changelogvà NT11 "Khai tối thiểu" bị vi phạm: khai thông tin lặp.- Phải làm sạch trước khi thiết kế gateway (K3/DESIGN).
5. NT12 — DOT cặp (Cấp A kiểm tra Cấp B)
Số liệu
| Chỉ số | Giá trị | Đánh giá |
|---|---|---|
| Writer (tier B) | 223 | |
Writer có paired_dot |
75/223 = 33.6% | 148 writer không có verifier |
| Writer có pair TRỎ ĐÚNG về tier-A | 75/75 (100%) của nhóm có pair | Khi khai thì khai đúng |
| Checker (tier A) | 49 | |
Checker có paired_dot |
32/49 = 65% | 17 checker không khai đối tượng kiểm tra |
| 66% writer KHÔNG có DOT cặp | — | Vi phạm NT12 ở quy mô lớn |
Phân loại khuyết cặp
- 38/38 DOT domain
infrastructure.schema(DOT-063..DOT-144, tất cảdot-schema-*-ensure,dot-pg-*): toàn bộpaired_dot=None. Không có verifier cho bất kỳ DDL nào trong lớp bootstrap schema. - 20/20 DOT
infrastructure.sync: phần lớn paired=None. - 15/15 DOT
infrastructure.deploy: paired=None. - Cụm KG (kg.*) và cụm Normative (nrm.*) có cặp đầy đủ nhất — do đây là các cụm ra đời muộn (S155-S159) khi luật cặp đã được ban hành.
Phát hiện bất thường
- Toàn bộ 10 writer gọi PG trực tiếp (mục 2.2) đều có
paired_dot=None. Các writer rủi ro cao nhất lại không có verifier → NT12 thất thủ ngay tại tuyến đầu. DOT-COL-HEALTHtier A check nhưngpaired_dot=None— không khai nó kiểm tra DOT nào → rỗng xích.- DOT trong cụm
DOT_KG_*,DOT_NRM_*tier A cófile_path=None— tồn tại dưới dạng metadata nhưng KHÔNG có script → tier A rỗng, verify không chạy được.
6. Scripts trong dot/bin/ KHÔNG nằm trong dot_tools — §0-AY
15 script mồ côi
Sau khi normalize (strip .ts/.js/.py) và cross-ref với file_path/script_path, còn 15 script trên disk không được dot_tools trỏ tới:
| # | Script | Direct PG | API calls | Loại |
|---|---|---|---|---|
| 1 | dot-cron-matrix-setup |
✓ (1) | — | Cron installer (giống DOT-308 nhưng chưa đăng ký) |
| 2 | dot-script-lint |
✓ (4) | — | Linter có query PG |
| 3 | dot-doc-generate |
✓ (4) | — | Normative doc generate |
| 4 | dot-doc-partition |
✓ (4) | — | Doc partition |
| 5 | dot-doc-render |
✓ (2) | — | Doc render |
| 6 | dot-nrm-amend |
✓ (5) | — | Normative amend |
| 7 | dot-nrm-binding |
✓ (2) | — | Normative bind |
| 8 | dot-nrm-config |
✓ (3) | — | Normative config |
| 9 | dot-nrm-discover |
✓ (5) | — | Normative discover |
| 10 | dot-nrm-enact |
✓ (4) | — | Normative enact |
| 11 | dot-nrm-impact |
✓ (5) | — | Normative impact |
| 12 | dot-nrm-lifecycle |
✓ (5) | — | Normative lifecycle |
| 13 | dot-nrm-retire |
✓ (3) | — | Normative retire |
| 14 | dot-nrm-sync |
✓ (4) | — | Normative sync |
| 15 | dot-nrm-verify |
✓ (8) | — | Normative verify |
Cả 15 đều ghi PG trực tiếp, KHÔNG gọi Directus API.
Làm rõ cụm dot-nrm-* và dot-doc-*
- Trong
dot_toolsCÓ record metadata choDOT_NRM_DISCOVER,DOT_NRM_VERIFY,DOT_NRM_IMPACT,DOT_NRM_LIFECYCLE,DOT_NRM_SYNC,DOT_DOC_PARTITION, v.v. nhưngfile_path=None→ metadata có, không link script.- Đây là L1 yếu: đăng ký tên nhưng không có trace file.
- Từ góc độ §0-AY "Writer KHÔNG nằm trong
dot_toolsmà vẫn chạy" thì chúng ĐƯỢC đăng ký. - Từ góc độ audit pipeline (K4 sẽ check) thì KHÔNG TÌM ĐƯỢC script bằng join
dot_tools.file_path.
dot-cron-matrix-setupvàdot-script-lint: Không có metadata hằng số nào trongdot_tools→ L3 BYPASS thật.
Số liệu kết luận
- 2 script L3 bypass thuần (
dot-cron-matrix-setup,dot-script-lint). - 13 script L1 yếu (NRM + DOC): có metadata nhưng không có file_path → phải verify bằng code-grep, không đảm bảo audit.
7. Coverage gap — DOT cover hết nhu cầu chưa?
Chỉ số coverage_status do dot_tools tự khai
| Trạng thái | Số lượng | Tỉ lệ |
|---|---|---|
complete |
13 | 4.8% |
partial |
158 | 58.1% |
∅ (không khai) |
101 | 37.1% |
→ Chính hệ thống tự nhận chỉ 4.8% DOT đạt mức "complete".
last_executed không đáng tin
- 157/272 record có
last_executed = 2026-03-31T08:08:57.064Z(đúng đến mili-giây) → đây là kết quả bulk-set bởi một migration chạy ngày đó, KHÔNG phải log thực thi thực tế. - 115 record
last_executed=None. - Không thể trả lời câu hỏi "DOT X có thực sự chạy không" từ
dot_tools.last_executed→ khớp với phát hiện K0 "không códot_run_log".
Vùng "cần nhưng không có"
Dựa vào dữ liệu PG/Directus + các script bypass, 4 nhóm CẦN nhưng không có DOT verifier chính thức:
- Normative writes (
nrm_*,law_*tables): 9 tier-B writer trực tiếp PG (dot-nrm-*). Có tier-A metadata nhưng file_path trống → verifier "rỗng". - Schema bootstrap (
infrastructure.schema, 38 DOT): toàn bộ paired=None. Không có "schema drift checker" tự động chạy sau mỗi DDL. - Cron installer (
dot-cron-*-setup): chỉdot-cron-pivot-setupcó trong registry,dot-cron-matrix-setupbypass. Không có DOT theo dõi vòng đời cron đã cài. - Doc partition / render (
dot-doc-*): ghi PG bảng normative_* nhưng không đăng ký file_path.
Vùng cover tốt nhất
- KG (knowledge graph) — ra đời muộn (S159), có đủ cặp tier-A ↔ tier-B ở mức metadata.
- Task sync — các DOT
dot-task-*đều đi qua Directus API → L1 đầy đủ.
Kết luận
- KHÔNG cover hết. Có 3 nguyên nhân đồng thời:
- DOT cũ (đợt DOT-001..DOT-150, trước S148) không tuân luật cặp → di tích.
- Lớp schema bootstrap về bản chất khó có verifier tự nhiên (DDL idempotent không cần "check sau khi tạo").
- Cụm normative/doc đi thẳng PG bỏ qua Directus → L1 yếu.
- Người viết bị buộc tự tạo writer riêng khi:
- Directus không có collection cho domain đó (đúng với
normative_*vì phần lớn tables PG-only). - Cần gọi function/trigger PG mà Directus REST không expose.
- Directus không có collection cho domain đó (đúng với
- → Đây là bằng chứng "Directus không cover hết nhu cầu writer" — đẩy đến L2/L3.
8. Tổng hợp ma trận L1 (phần điền được ở K1)
| Writer (DOT code) | Bảng/Object | Thao tác | Credential | L1/L2/L3 | H1/H2/H3 | Paired |
|---|---|---|---|---|---|---|
DOT-143 dot-schema-taxonomy-pg-apply |
system_issues, registry_* (types/constraints) |
DDL (ALTER/CREATE/FN) × 28 | docker exec postgres (user directus) |
L2 (bootstrap idempotent) | H3 (last_touch 2026-03-31) | None |
DOT-129 dot-pg-views-ensure |
v_* views |
DDL CREATE OR REPLACE VIEW × 12 | docker exec postgres | L2 | H3 | None |
DOT-128 dot-pg-triggers-ensure |
triggers | DDL × 6 | docker exec postgres | L2 | H3 | None |
DOT-127 dot-pg-audit-ensure |
audit tables + fn | DDL × 4 | docker exec postgres | L2 | H3 | None |
DOT-123 dot-label-trigger-setup |
label triggers | DDL × 2 | docker exec postgres | L2 | H3 | None |
DOT-112 dot-entity-retire |
directus_* items lifecycle |
DML qua fn_transition_lifecycle |
docker exec postgres | L1 (gateway partial) | H3 | None |
DOT-111 dot-entity-deprecate |
idem | idem | idem | L1 partial | H3 | None |
DOT-109 dot-production-truth-gate |
SELECT only | read | docker exec postgres | L1 (read) | H3 | None |
DOT-110 dot-coverage-inspector (A) |
SELECT only | read | docker exec postgres | L1 (read checker) | H3 | None |
DOT-308 dot-cron-pivot-setup |
installs cron → fn_refresh_orphan_* |
DML via scheduled fn | docker exec postgres | L1 (installer) + L2 residual cron | H3 | None |
— dot-cron-matrix-setup |
cron matrix | DDL/DML | docker exec postgres | L3 BYPASS | H3 | — |
— dot-script-lint |
? | psql | docker exec postgres | L3 BYPASS | H3 | — |
— dot-nrm-* (9) |
normative PG tables | DML ON CONFLICT | docker exec postgres | L1 yếu (meta có, file_path trống) | H3 | có (metadata) |
— dot-doc-* (3) |
normative rendered docs | DML | docker exec postgres | L1 yếu hoặc L3 | H3 | có (metadata) |
| ~56 script Directus API | mọi items/<coll> |
qua Directus | ADMIN_TOKEN hoặc DIRECTUS_TOKEN | L1 chuẩn | H3 | 75/223 có pair |
9. Câu hỏi mở (chuyển K2-K4)
- Trùng đăng ký: có luật nào chọn
DOT-NNNvsDOT_SEMANTIClà canonical không? Phải dedupe trước khi thiết kế gateway. - Lớp
dot-nrm-*vàdot-doc-*: tại sao không có file_path? Có phải cố tình (vì đi thẳng PG không kiểm soát được) hay là metadata chưa catch-up? - Function
fn_transition_lifecycle: có bao nhiêu entity state transitions hiện đi qua nó? Có bao nhiêu đi đường khác (UPDATE thẳngstatuscolumn)? (K2) dot-script-lintgọi psql: nó đang linting cái gì? Có phải "audit tool" nhưng bản thân nó là bypass? (K2)- Những DOT trong
dot_toolscófile_pathKHÔNG tồn tại trên disk (chiều ngược lại với §0-AY)? Cần check ở K4. coverage_status=partial158 record: do ai đánh? Có tiêu chí chưa? (K4)
10. Forward / backward link
- Backward: K0 — Timeline + Retention
- Áp dụng: dùng mốc 2026-03-30 (DOT 100%) để gán H3 cho mọi last_touch > ngày này.
- Áp dụng: vì không có
dot_run_log,last_executedkhông đáng tin → chuyển tất cả "có last_executed" thành "nghi vấn H3" trong ma trận.
- Forward:
- K2 sẽ quét code toàn repo (không chỉ
dot/bin/) để bắt bypass writers (scripts/, server/, agent-data/, layers portal, Directus flows). - K3 sẽ
\duPG để check quyền userdirectusvà so sánh với 79fn_*— xem các function nàoSECURITY DEFINER(phôi gateway). - K4 sẽ check: Directus Flows có raw SQL không; migration scripts on-deploy; code dead còn ghi MySQL/Firestore; writer không tên.
- K2 sẽ quét code toàn repo (không chỉ
11. Evidence trích dẫn
# Directus REST
GET /items/dot_tools?limit=-1 → 272 records
GET /fields/dot_tools → 28 fields (tier, paired_dot, coverage_status, ...)
# Distribution
tier={'A':49,'B':223}
status={'active':256,'published':16}
coverage_status={'partial':158,'∅':101,'complete':13}
last_executed={'2026-03-31T08:08:57.064Z':157, None:115}
# Direct PG writers (grep psycopg|asyncpg|docker exec postgres|psql)
dot/bin/dot-script-lint ← NOT in dot_tools
dot/bin/dot-cron-matrix-setup ← NOT in dot_tools
dot/bin/dot-cron-pivot-setup DOT-308
dot/bin/dot-entity-retire DOT-112 (→ fn_transition_lifecycle)
dot/bin/dot-entity-deprecate DOT-111 (→ fn_transition_lifecycle)
dot/bin/dot-production-truth-gate DOT-109
dot/bin/dot-coverage-inspector DOT-110 (tier A)
dot/bin/dot-label-trigger-setup DOT-123
dot/bin/dot-schema-taxonomy-pg-apply DOT-143 + DOT_SCHEMA_TAXONOMY_PG_APPLY (dup)
# DDL counters
dot-schema-taxonomy-pg-apply: 28
dot-pg-views-ensure: 12
dot-pg-triggers-ensure: 6
dot-pg-audit-ensure: 4
dot-label-trigger-setup: 2
# ON CONFLICT presence (anti-duplicate pattern)
47 occurrences / 29 files (positive — idempotent)
12 files still have SELECT-then-INSERT multiline pattern (race risk)
# Pairing
Writers(B)=223, with paired_dot=75 (33.6%) → 148 writers without verifier
Checkers(A)=49, with paired_dot=32 (65%)
100% of paired_dot strings on tier-B resolve to existing tier-A record
# Unregistered scripts (disk − dot_tools)
15 scripts (all direct PG, zero via Directus API)
Of these: 2 hard-bypass (cron-matrix, script-lint), 13 L1-weak (nrm-*, doc-*)
# PG gateway prototype
SELECT COUNT(*) FROM pg_proc WHERE proname LIKE 'fn_%'
→ 79 functions (guards + reconcile + transitions)
fn_transition_lifecycle(collection, entity_id, new_state, reason, source)
fn_bulk_transition(5 args)
fn_refresh_orphan_{species,dot,col}, fn_refresh_species_per_level → scheduled by DOT-308 cron
12. Trạng thái
- K1 DONE. Chờ duyệt để chuyển sang K2 (L3 BYPASS — quét toàn repo ngoài
dot/bin/). - Không chỉnh sửa code/schema/quyền. Toàn bộ query là SELECT / GET.
- Đề xuất cho K2 khi duyệt: sẽ grep
scripts/,server/,agent-data-test/,web-test/web/,infra/,directus/cho psycopg/asyncpg/psql/Directus flow exec; verify 9 writer S175; đối chiếu với danh sách 15 unregistered tại K1.