Điều 35: Luật Quản trị DOT v5.2 FINAL BAN HÀNH
ĐIỀU 35: LUẬT QUẢN TRỊ DOT — v5.2 FINAL (BAN HÀNH 2026-04-18 S178 Fix 15)
v5.2 FINAL | 2026-04-18 S178 Fix 15 — BAN HÀNH sau enact gói DOT Repair Governance v4 FINAL. Base: v5.1 FINAL (2026-04-14 S177 Fix 8) — xem history/changelog và backup v5.0 tại
dieu35-dot-governance-law-v5-0-backup.md. Tham chiếu HP: v4.6.3 (13 NT). Amend trọng tâm so với v5.1: flowfix_repair_dotend-to-end, verify 3 tầng, ADMIN fallback có audit schema, paired test retrofit, và liên kết APR risk/quorum với Đ32 v1.1. Tình trạng: Đã tiếp thu đầy đủ sign-off Council cho gói S178 Fix 15.** TUÂN THỦ: HP v4.6.3, Đ0-G, Đ0-H, Đ22 v1.1, Đ26, Đ31, Đ32 v1.1, Đ36, Đ41 v1.1.
★ 7 fix Council R2 đã apply inline:
dot_config.valuecho phép NULL + sentinellaw_v5_1_enacted_at+ UTC ISO format (§4.4)- H14 mới — bắt
law_v5_1_enacted_atchưa set > 24h (§8.1) fn_log_issueBỎ severity khỏi signature → severity leo thang trên cùng row (§4.1B)- PRECHECK dedupe
system_issuesopen trước CREATE UNIQUE INDEX (§4.1B) - §5.1 viết cứng: infer fail = CẤM POST partial row (§5.1)
- H13 chỉ báo động, KHÔNG self-repair
dot-metadata-repair(§5.2) - BLOCK 4 thêm bước 4.0 snapshot + 4.3 lưu old_file_path + 4.10 atomic transaction + 4.13 cleanup (§9.2)
§1. MỤC TIÊU
"DOT là cổng duy nhất thao tác dữ liệu (Điều 0-H). Nhưng nếu không quản trị CHÍNH DOT — ai biết DOT nào đang làm gì, thiếu gì, hỏng gì?"
3 mục tiêu (giữ từ v5.0):
| # | Mục tiêu | Đo bằng | Tính chất |
|---|---|---|---|
| MT1 | Nhìn toàn cảnh: Biết mọi DOT đang làm gì, thuộc domain nào, phục vụ luật nào, thiếu/thừa/hỏng ở đâu | dot_tools có đầy đủ metadata cho 100% DOT |
Vĩnh viễn |
| MT2 | Đo được bằng số: Coverage, pairing rate, automation rate — đếm bằng 1 query PG | dot_coverage_required + pivot = % coverage |
Tự thích nghi |
| MT3 | Tự vận hành khép kín: Phát hiện → tạo APR → sửa → verify | 3+ DOT tự quản trị + dual-trigger | Tự động 100% |
Thứ tự ưu tiên: Nhìn thấy → Đo được → Tự vận hành.
★ MT4 MỚI (v5.1): Luật áp cả entity CŨ, không chỉ entity MỚI
Luật ban hành không để lại legacy mãi vênh. Mọi luật có impact trên bảng sẵn data CŨ → bắt buộc kèm retrofit mechanism (§11). Áp cho cả luật mới VÀ luật đã ban hành (xem §11.4).
§2. PHẠM VI
TRONG phạm vi Điều 35:
- Quản trị sổ đăng ký DOT (
dot_tools— SSOT duy nhất) - Phân loại DOT theo domain, tier, operation, trigger_type — TẤT CẢ qua PG SSOT tables, KHÔNG text tự do
- Quản lý domain DOT (
dot_domains— FK enforce, 4 lớp bảo vệ) - Đo coverage: domain × operation × tier — mẫu số TỰ ĐỘNG cập nhật
- Quản lý vòng đời DOT: tạo → active → deprecated → retired
- Kiểm tra sức khoẻ DOT: pairing, domain, target, file_path, cron, metadata completeness (v5.1)
- DOT 2 cấp: Cấp A (kiểm tra) + Cấp B (thực thi) — paired bắt buộc
- ★ Retrofit luật mới cho entity cũ (v5.1 — §11)
★ v5.1 LƯU Ý VẬN HÀNH:
fn_birth_gatemặc định mode='warn' ngay sau ban hành. Chuyển 'block' quaUPDATE dot_config SET value='block' WHERE key='birth_gate_mode'khi đạt tiêu chí cứng §10.UNIQUE(file_path) WHERE file_path IS NOT NULL: partial index chỉ cho phép nhiều row có file_path NULL cùng tồn tại; KHÔNG cho phép duplicate non-null. 45 cặp duplicate hiện hữu PHẢI dedupe TRƯỚC khi tạo index — xem BLOCK 4 §9.2.
NGOÀI phạm vi:
| Vấn đề | Luật phụ trách | Đ35 chỉ làm |
|---|---|---|
| Nội dung cụ thể DOT xử lý | Luật tương ứng | Biết DOT phục vụ luật nào |
| Collection mà DOT tác động | Đ36 | Khai báo target_collections |
| Khai sinh entity DOT | Đ0-G | Trigger khai sinh khi tạo DOT |
| Phê duyệt thay đổi DOT | Đ32 | Tạo APR |
| Toàn vẹn hệ thống | Đ31 | Báo cáo sức khoẻ DOT |
| Escalation → con người | Đ22 Self-healing | Đẩy vào system_issues |
§3. DOT 2 CẤP
| Thuộc tính | Cấp A — Kiểm tra | Cấp B — Thực thi |
|---|---|---|
| Vai trò | Giám sát, quét, báo cáo | Ghi, sửa, tạo dữ liệu |
| Quyền | Read-only | Read + Write (có secret GSM) |
| Ví dụ | dot-dot-health, dot-collection-health | dot-schema-ensure, dot-apr-execute |
| Auto-approve | ✅ Có | ❌ Pending duyệt |
| Bắt buộc paired | Không | PHẢI có DOT Cấp A (paired_dot FK) |
Quy tắc paired_dot (luật nội tại Đ35):
- Mỗi DOT Cấp B ghi dữ liệu → PHẢI có DOT Cấp A kiểm tra cùng scope.
paired_dotFK →dot_tools.code. FK enforce.- Cấp A IDLE = Cấp B làm đúng. Cấp A phát hiện lỗi → APR → Cấp B sửa → A re-verify.
★ PG TRIGGER enforce paired_dot:
CREATE OR REPLACE FUNCTION fn_dot_enforce_paired() RETURNS TRIGGER AS $$
BEGIN
IF NEW.tier = 'B' AND NEW.paired_dot IS NULL THEN
RAISE EXCEPTION 'DOT Cấp B (%) PHẢI có paired_dot.', NEW.code;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_dot_enforce_paired
BEFORE INSERT OR UPDATE ON dot_tools
FOR EACH ROW EXECUTE FUNCTION fn_dot_enforce_paired();
§4. SCHEMA
4.1 dot_tools — 11 fields (v5.1: thêm _dot_origin chính thức)
| Field | Type | Constraint v5.0 | Constraint v5.1 | Mục đích |
|---|---|---|---|---|
| tier | TEXT | FK → dot_tiers.code | Giữ | Cấp DOT (A/B) |
| domain | TEXT | FK → dot_domains.code, NOT NULL, DEFAULT 'unclassified' | Giữ | Domain |
| operation | TEXT | FK → dot_operations.code, nullable | + NOT NULL sau grace + Block 4 | Loại thao tác |
| paired_dot | TEXT | FK → dot_tools.code, nullable | Giữ (trigger enforce B) | DOT Cấp A |
| trigger_type | TEXT | FK → dot_trigger_types.code | + NOT NULL sau grace | Cơ chế kích hoạt |
| cron_schedule | TEXT | nullable | + NOT NULL sau grace ('' cho manual) |
Lịch cron |
| file_path | TEXT | nullable | + NOT NULL sau grace + UNIQUE partial WHERE NOT NULL | Đường dẫn file |
| last_executed | TIMESTAMPTZ | nullable | Giữ | Lần chạy cuối |
| coverage_status | TEXT | FK → dot_coverage_statuses.code | + NOT NULL sau grace | Trạng thái bao phủ |
_dot_origin |
TEXT | (không có v5.0) | ★ v5.1 MỚI: NOT NULL DEFAULT 'unknown' | Truy vết công cụ tạo DOT (RC-3) |
| extra_metadata | JSONB | DEFAULT '{}' | Giữ | Metadata mở rộng |
★ v5.1 KHOẢN 1 — UNIQUE PARTIAL + NOT NULL + REFERENCE TABLES
WORDING ĐÚNG về UNIQUE partial:
UNIQUE INDEX ... WHERE file_path IS NOT NULLchặn 2 row cùng có cùngfile_pathnon-null. Cho phép nhiều rowfile_path IS NULLcùng tồn tại.- 45 cặp duplicate non-null hiện hữu sẽ làm
CREATE UNIQUE INDEXFAIL ngay. - → BLOCK 4 §9.2 PHẢI dedupe TRƯỚC khi CREATE INDEX.
-- v5.1 BLOCK 4 — CHỈ chạy SAU dedupe verify 0 row duplicate non-null:
CREATE UNIQUE INDEX uq_dot_tools_file_path
ON dot_tools(file_path) WHERE file_path IS NOT NULL;
-- v5.1 BLOCK 4 — CHỈ chạy SAU DOT_METADATA_AUDIT báo 0 drift:
ALTER TABLE dot_tools
ALTER COLUMN operation SET NOT NULL,
ALTER COLUMN coverage_status SET NOT NULL,
ALTER COLUMN trigger_type SET NOT NULL,
ALTER COLUMN file_path SET NOT NULL,
ALTER COLUMN cron_schedule SET NOT NULL,
ALTER COLUMN _dot_origin SET NOT NULL;
Reference tables (v5.1 mở rộng dot_operations từ 9 → 18 op):
CREATE TABLE dot_tiers (code TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT);
INSERT INTO dot_tiers VALUES ('A', 'Kiểm tra', 'Read-only'), ('B', 'Thực thi', 'Read+Write');
CREATE TABLE dot_operations (code TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT);
INSERT INTO dot_operations VALUES
-- 9 op từ v5.0:
('health','Kiểm tra sức khoẻ',''), ('create','Tạo mới',''), ('sync','Đồng bộ',''),
('ensure','Đảm bảo tồn tại',''), ('register','Đăng ký',''), ('report','Báo cáo',''),
('execute','Thực thi',''), ('refresh','Làm mới',''), ('classify','Phân loại',''),
-- 9 op MỚI v5.1 (CLI S177 C6 phát hiện 8/12 op runtime ngoài luật seed v5.0):
('verify','Kiểm tra hợp lệ',''), ('delete','Xoá',''), ('update','Cập nhật',''),
('restore','Khôi phục',''), ('import','Nhập liệu',''), ('snapshot','Chụp ảnh',''),
('seed','Gieo dữ liệu',''), ('audit','Kiểm toán',''), ('backfill','Điền ngược','');
CREATE TABLE dot_trigger_types (code TEXT PRIMARY KEY, name TEXT NOT NULL);
INSERT INTO dot_trigger_types VALUES
('cron','Lịch định kỳ'), ('event','Sự kiện Directus'), ('on-deploy','Khi deploy'),
('on-demand','Khi yêu cầu'), ('manual','Thủ công'), ('one-off','1 lần duy nhất');
CREATE TABLE dot_coverage_statuses (code TEXT PRIMARY KEY, name TEXT NOT NULL);
INSERT INTO dot_coverage_statuses VALUES
('complete','Đầy đủ'), ('partial','Một phần'), ('orphan','Mồ côi'),
('phantom','Ma'), ('deprecated','Lỗi thời');
★ v5.1 KHOẢN 1B — ĐỊNH NGHĨA 2 HÀM PHỤ TRỢ
-- B1: fn_is_in_grace_period()
CREATE OR REPLACE FUNCTION fn_is_in_grace_period()
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public, pg_catalog
AS $$
DECLARE
v_days INT;
v_enacted TIMESTAMPTZ;
BEGIN
SELECT value::INT INTO v_days FROM dot_config WHERE key = 'grace_period_days';
SELECT value::TIMESTAMPTZ INTO v_enacted FROM dot_config WHERE key = 'law_v5_1_enacted_at';
IF v_days IS NULL OR v_enacted IS NULL THEN
RETURN TRUE; -- fail-open
END IF;
RETURN NOW() < v_enacted + (v_days || ' days')::INTERVAL;
END;
$$;
ALTER FUNCTION fn_is_in_grace_period() OWNER TO workflow_admin;
-- B2: fn_log_issue() — v5.1 FINAL: signature BỎ severity → escalate trên cùng row
CREATE OR REPLACE FUNCTION fn_log_issue(
p_source TEXT,
p_severity TEXT,
p_category TEXT,
p_summary TEXT,
p_entity_code TEXT DEFAULT NULL
) RETURNS BIGINT
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public, pg_catalog
AS $$
DECLARE
v_id BIGINT;
v_signature TEXT;
BEGIN
-- signature KHÔNG có severity → 1 issue/(source,category,entity), severity leo thang cùng row
v_signature := md5(coalesce(p_source,'') || '|' || coalesce(p_category,'') || '|' || coalesce(p_entity_code,''));
INSERT INTO system_issues (source, severity, category, summary, entity_code, issue_signature, status, created_at, updated_at)
VALUES (p_source, p_severity, p_category, p_summary, p_entity_code, v_signature, 'open', NOW(), NOW())
ON CONFLICT (issue_signature) WHERE status = 'open'
DO UPDATE SET
-- Chỉ leo severity lên, không tụt
severity = CASE
WHEN (CASE EXCLUDED.severity WHEN 'critical' THEN 3 WHEN 'warning' THEN 2 ELSE 1 END)
> (CASE system_issues.severity WHEN 'critical' THEN 3 WHEN 'warning' THEN 2 ELSE 1 END)
THEN EXCLUDED.severity
ELSE system_issues.severity
END,
summary = EXCLUDED.summary,
updated_at = NOW()
RETURNING id INTO v_id;
RETURN v_id;
END;
$$;
ALTER FUNCTION fn_log_issue(TEXT,TEXT,TEXT,TEXT,TEXT) OWNER TO workflow_admin;
GRANT EXECUTE ON FUNCTION fn_log_issue(TEXT,TEXT,TEXT,TEXT,TEXT) TO incomex;
-- BLOCK 1 preflight (v5.1 FINAL): dedupe system_issues TRƯỚC khi tạo unique partial index.
-- WITH dups AS (
-- SELECT md5(coalesce(source,'')||'|'||coalesce(category,'')||'|'||coalesce(entity_code,'')) AS sig,
-- MIN(id) AS keep_id, COUNT(*) AS cnt
-- FROM system_issues WHERE status='open'
-- GROUP BY 1 HAVING COUNT(*) > 1
-- )
-- UPDATE system_issues SET status='resolved', updated_at=NOW(),
-- summary = summary || ' [auto-merged duplicate sig pre-v5.1]'
-- WHERE id IN (
-- SELECT s.id FROM system_issues s
-- JOIN dups d ON md5(coalesce(s.source,'')||'|'||coalesce(s.category,'')||'|'||coalesce(s.entity_code,''))=d.sig
-- WHERE s.status='open' AND s.id <> d.keep_id
-- );
-- Sau đó:
-- ALTER TABLE system_issues ADD COLUMN IF NOT EXISTS issue_signature TEXT;
-- CREATE UNIQUE INDEX IF NOT EXISTS uq_system_issues_open_sig ON system_issues(issue_signature) WHERE status='open';
SECURITY DEFINER an toàn: Mọi function SECDEF v5.1 đặt SET search_path = public, pg_catalog. Owner = workflow_admin.
4.2 dot_domains (giữ v5.0)
CREATE TABLE dot_domains (
code TEXT PRIMARY KEY,
name TEXT NOT NULL,
parent_domain TEXT REFERENCES dot_domains(code)
);
4 lớp bảo vệ: DEFAULT 'unclassified' + NOT NULL + FK + ON DELETE RESTRICT. Seed 24 domains: Phụ lục A.
4.3 dot_coverage_required (giữ v5.0)
CREATE TABLE dot_coverage_required (
id SERIAL PRIMARY KEY,
domain TEXT NOT NULL REFERENCES dot_domains(code),
operation TEXT NOT NULL REFERENCES dot_operations(code),
tier TEXT NOT NULL REFERENCES dot_tiers(code),
description TEXT,
UNIQUE(domain, operation, tier)
);
4.4 dot_config (v5.1 FINAL fix — nullable + UTC ISO)
-- v5.1 FINAL fix Council R2 GPT #1: value nullable (cho phép seed law_v5_1_enacted_at=NULL)
CREATE TABLE dot_config (
key TEXT PRIMARY KEY,
value TEXT, -- v5.1: nullable
description TEXT,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
INSERT INTO dot_config VALUES
('dot_base_path', 'bin/dot/', 'Thư mục gốc DOT'),
('stale_threshold_days', '7', 'Ngày stale'),
('grace_period_days', '7', 'Grace mặc định — có thể UPDATE để gia hạn'),
('health_cron', '0 3 * * *', ''),
('coverage_cron', '0 2 * * 0', ''),
('birth_gate_mode', 'warn', 'v5.1: warn mặc định. UPDATE=block khi đạt §10 checklist'),
('law_v5_1_enacted_at', NULL, 'v5.1: SET tại thời điểm ban hành (UTC ISO). H14 báo nếu NULL > 24h');
-- BƯỚC BẮT BUỘC khi ban hành (BLOCK 2 cuối):
-- UPDATE dot_config SET value=to_char(NOW() AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"')
-- WHERE key='law_v5_1_enacted_at';
★ GUARD H14 (v5.1 FINAL): dot-dot-health H14 bắt law_v5_1_enacted_at IS NULL + BLOCK 1 đã chạy > 24h → fn_log_issue('dot-dot-health','critical','grace_never_set','...').
§5. QUY TRÌNH TẠO DOT MỚI — 8 BƯỚC (v5.1 strengthened bước 4)
| Bước | Hành động | Cơ chế | Luật |
|---|---|---|---|
| 1 | Tạo APR request_type='new_dot' | Đ32 | Đ32 |
| 2 | Cấp A auto-approve. Cấp B pending | APR | Đ32 |
| 3 | Tạo file .ts tại dot_config.dot_base_path |
Agent | — |
| 4 | Register vào dot_tools 11/11 fields + dual-trigger | dot-dot-register + cron repair | Đ22 |
| 5 | Khai báo target_collections | dot-dot-register | Đ8 |
| 6 | Khai sinh birth_registry | Trigger tự động | Đ0-G |
| 7 | dot-dot-health kiểm tra | Cron/manual | Đ31 |
| 8 | Health PASS → active | Tự động | Đ22 |
★ v5.1 KHOẢN 5 (BƯỚC 4 STRENGTHENED)
5.1 Payload TỐI THIỂU ở API boundary (11 fields)
{
"code": "DOT-...", // REQUIRED, unique
"name": "...", // REQUIRED
"tier": "A|B", // REQUIRED, FK
"domain": "xxx.yyy", // REQUIRED dotted, FK
"operation": "...", // REQUIRED, FK
"trigger_type": "...", // REQUIRED, FK
"cron_schedule": "...", // REQUIRED ('' cho manual)
"coverage_status": "partial", // REQUIRED, default 'partial'
"file_path": "/opt/incomex/...", // REQUIRED absolute
"_dot_origin": "dot-dot-register" // REQUIRED
}
WORDING NT11: Payload 11 fields = API boundary contract. Nguồn ưu tiên = suy luận tự động. dot-dot-register PHẢI infer trước khi POST.
★ v5.1 FINAL fix #4 — INFER FAIL = CẤM POST PARTIAL ROW:
Khi
dot-dot-registerinfer thất bại field bắt buộc, TUYỆT ĐỐI CẤM POST partial/placeholder:
fn_log_issue('dot-dot-register','warning','infer_fail',...)- Tạo APR
request_type='backfill_metadata'- SKIP file trong run hiện tại
- Chờ APR duyệt → re-register
Pattern CẤM: "POST trước, cron sửa sau" — chính là RC-4 đẻ ra 49 DOT POST-S151 vẫn 94% NULL. Không lặp lại.
5.2 DUAL-TRIGGER — sống cả khi mode=block
| Path | Vai trò | Trigger | Sống khi block? |
|---|---|---|---|
Pre-POST inference trong dot-dot-register |
Engine chính — infer 11 fields TRƯỚC khi POST | on-deploy + on-demand | ✅ Có |
Cron dot-metadata-repair (v5.1 MỚI, Tier B) |
Lưới đỡ — scan row partial → infer + PATCH; fail → APR | Cron 0 * * * * |
✅ Có |
Health check H13: DOT dot-metadata-repair không tồn tại HOẶC last_executed > 2h → critical.
★ v5.1 FINAL fix #5 — H13 chỉ là BÁO ĐỘNG:
H13 escalate qua
fn_log_issue+ APRrequest_type='fix_repair_dot'. KHÔNG có self-repair tự động (tránh self-paradox DOT canh gác chính nó). Khi repair DOT chết,fn_birth_gatelà hàng phòng thủ tạm thời cho DOT mới.
Flow Directus [AUTO-ID] DOT Tools: giữ ACTIVE làm lưới đỡ phụ giai đoạn warn.
5.3 Reject row không đầy đủ sau grace + mode=block
Kết hợp §8.3: sau grace AND birth_gate_mode='block', INSERT thiếu field bị PG reject ngay.
§6. VÒNG ĐỜI DOT (v5.2 mở rộng)
6.1 Trạng thái
created → active → deprecated → retired
Retire 6 bước + Luật Bảo toàn (CẤM rename/xoá file).
6.2 Flow Sửa Bug DOT Canonical Đã Enacted (fix_repair_dot) — v5.2 MỚI
Điều kiện kích hoạt: Phát hiện bug trong DOT đã status='enacted' (không phải draft/review). Ví dụ: cột SQL sai, silent-fail, logic bug.
6 bước bắt buộc:
| Bước | Hành động | Chi tiết | Luật |
|---|---|---|---|
| 1. DETECT | Ghi system_issues |
kind='dot_bug', dot_code, evidence (file:line + error observed) | Đ22 |
| 2. PROPOSE | dot-apr-propose |
request_type='fix_repair_dot', proposed_action_code='patch_ops_code', payload gồm diff cũ→mới, root cause, test plan |
Đ32 v1.1 |
| 3. APPROVE | Theo cơ chế Đ32 | risk_level từ apr_action_types → Council (high) / Chủ tịch (medium) / auto (low) |
Đ32 v1.1 §3.3 |
| 4. APPLY | Flow Đ41 §5.8 | backup .bak-{session} → patch → dry-run → commit+log. Bắt buộc test case regress bug gốc TRƯỚC khi commit |
Đ41 v1.1 |
| 5. VERIFY | Post-deploy scan 3 tầng | DOT chạy lại: bug tái hiện = FAIL → rollback từ backup | §6.4 |
| 6. CLOSE | Đóng sổ | system_issue → 'resolved', APR → 'applied', vps_deploy_log entry đầy đủ |
Đ31 |
6.3 Điều kiện từng bước
- Bước 1→2: DETECT phải có evidence cụ thể (file, dòng, lỗi quan sát được). KHÔNG "cảm thấy có bug" → DỪNG (NT9).
- Bước 2→3: Payload APR phải chứa diff (old→new), root cause analysis, test plan verify. Thiếu bất kỳ = APR bị reject.
- Bước 3→4: Chỉ khi APR
status='approved'. Trigger DBfn_apr_quorum_checkenforce quorum theo risk_level (P14). - Bước 4→5: Backup
.bak-{session}TỒN TẠI và verify checksum TRƯỚC khi patch. Không backup = DỪNG. - Bước 5→6: 3 tầng verify PASS. Bất kỳ tầng nào FAIL → rollback từ backup, mở system_issues mới.
6.4 Verify 3 tầng (post-deploy)
| Tầng | Kiểm tra | PASS | FAIL |
|---|---|---|---|
| 1. Syntax | File mới parse được (TypeScript: tsc --noEmit, Bash: bash -n) |
Tiếp tầng 2 | Rollback ngay |
| 2. Dry-run | DOT chạy với --dry-run (nếu hỗ trợ) hoặc trên data test, output hợp lý |
Tiếp tầng 3 | Rollback ngay |
| 3. Integration | DOT chạy thật trên production, verify bug gốc không tái hiện + không regression | CLOSE | Rollback + system_issues mới |
6.5 ADMIN Fallback — Khi chính DOT APR hỏng
Tình huống: dot-apr-propose hoặc dot-apr-execute chính nó bị bug → không thể tạo/thực thi APR bình thường → vòng lặp vô tận.
Quy trình ngoại lệ (chỉ Chủ tịch):
- INSERT
admin_fallback_log(dot_code, reason, backup_path, patch_diff, verify_evidence, session_code, status='applied') TRƯỚC khi patch. - Patch trực tiếp (bypass APR).
- Verify 3 tầng (§6.4).
- Tạo retroactive APR trong 24 giờ (
retroactive_deadline). Quá hạn →fn_admin_fallback_overdue_scan()tự flip status='audit_overdue' →system_issueskind='fallback_audit_overdue'. - Ghi
retroactive_apr_idvàoadmin_fallback_logkhi APR tạo xong.
Giới hạn: Chỉ dùng cho DOT thuộc hệ thống APR chính nó. Không dùng cho DOT nghiệp vụ khác.
6.6 Paired test bắt buộc (NT12)
Mọi DOT bash canonical (thuộc ops-code/) PHẢI đi kèm paired test script kiểm tra hành vi tối thiểu (smoke test). Pattern: dot-XXX-test chạy dry-run, verify output mẫu. Retrofit 90 ngày cho DOT lõi (nrm-*, apr-*, dot-dot-*).
6.7 Retrofit
DOT legacy đã enacted trước §6 này vẫn áp dụng flow fix_repair_dot khi phát hiện bug. KHÔNG có cửa bypass.
§7. ĐO LƯỜNG (giữ v5.0 + bổ sung 7.6)
7.1-7.5 giữ v5.0
★ 7.6 Metadata Completeness Rate (v5.1 MỚI)
(DOT có 11/11 fields NOT NULL) / (Tổng DOT) × 100- Mục tiêu: 100% sau grace + Block 4 retrofit
§8. DOT TỰ QUẢN TRỊ — 4 CẶP (v5.1 mở rộng)
| DOT | Cấp | Chức năng | Paired | Trigger |
|---|---|---|---|---|
| dot-dot-health | A | 14 health checks v5.1 | — | cron |
| dot-dot-coverage | A | Coverage + auto-suggest | — | cron weekly |
| dot-dot-register | B | Đăng ký (11/11 fields infer) | dot-dot-health | on-deploy + on-demand |
| dot-metadata-repair (v5.1 MỚI) | B | Cron repair partial → infer + PATCH; fail → APR | dot-dot-health (H13) | cron 0 * * * * |
8.1 dot-dot-health — 14 health checks (v5.1 FINAL)
| Check | Phát hiện | Hành động (dùng fn_log_issue()) |
|---|---|---|
| H1 | domain='unclassified' | APR classify |
| H2 | DOT B thiếu paired_dot | APR pairing |
| H3 | thiếu target_collections | APR |
| H4 | file_path không tồn tại | APR fix |
| H5 | retired nhưng cron còn chạy | APR disable |
| H6 | last_executed > threshold | warning stale |
| H7 | File disk không trong registry | APR register |
| H8 | coverage_status không nhất quán | APR update |
| H9 | retired mà register cố re-register | Block |
| H10 | v5.1: operation IS NULL sau grace | critical + APR backfill_operation |
| H11 | v5.1: coverage_status IS NULL sau grace | Như H10 |
| H12 | v5.1: file_path drift — 2 row cùng trỏ 1 file | critical + APR dedupe |
| H13 | v5.1: dot-metadata-repair chết / stale > 2h | critical (chỉ báo động, không self-repair) |
| H14 | v5.1 FINAL: law_v5_1_enacted_at IS NULL + BLOCK 1 > 24h |
critical grace_never_set + APR set_law_enacted_at |
Severity (đối chiếu Đ31):
warning= trong grace HOẶC drift < 24hcritical= sau grace HOẶC drift > 24h HOẶC duplicate file_path
★ v5.1 KHOẢN 2 — ESCALATION BẮT BUỘC qua fn_log_issue()
Mọi H1-H14 phát hiện → BẮT BUỘC gọi fn_log_issue(). CẤM dùng curl ... || true (silent-fail). Cầu nối Đ22 self-healing.
8.2 dot-dot-coverage (Cấp A) — giữ v5.0
8.3 dot-dot-register (Cấp B) — v5.1 strengthened
- Đọc
dot_base_pathtừdot_config - Quét → so sánh với
dot_tools - File mới → infer 11/11 fields rồi POST (§5.1). Infer fail → CẤM POST + APR
- Dual-trigger: kết hợp
dot-metadata-repaircron - File retired → SKIP
★ v5.1 KHOẢN 3 — fn_birth_gate configurable mode + scope rõ
SCOPE: fn_birth_gate trong Đ35 là gate cho dot_tools metadata, KHÔNG phải birth gate generic của Đ0-G. Code comment: fn_birth_gate (Đ35-scope: dot_tools).
CREATE OR REPLACE FUNCTION fn_birth_gate()
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER
SET search_path = public, pg_catalog
AS $$
DECLARE
v_missing text[] := ARRAY[]::text[];
v_mode text;
v_grace boolean;
BEGIN
SELECT value INTO v_mode FROM dot_config WHERE key='birth_gate_mode';
v_grace := fn_is_in_grace_period();
IF NEW.operation IS NULL THEN v_missing := array_append(v_missing, 'operation'); END IF;
IF NEW.coverage_status IS NULL THEN v_missing := array_append(v_missing, 'coverage_status'); END IF;
IF NEW.trigger_type IS NULL THEN v_missing := array_append(v_missing, 'trigger_type'); END IF;
IF NEW.file_path IS NULL THEN v_missing := array_append(v_missing, 'file_path'); END IF;
IF NEW._dot_origin IS NULL THEN NEW._dot_origin := 'unknown'; END IF;
IF array_length(v_missing, 1) > 0 THEN
PERFORM fn_log_issue(
'fn_birth_gate',
CASE WHEN v_grace THEN 'warning' ELSE 'critical' END,
'dot_metadata_missing',
format('DOT %s thiếu: %s', NEW.code, array_to_string(v_missing, ',')),
NEW.code
);
IF NOT v_grace AND v_mode = 'block' THEN
RAISE EXCEPTION 'DOT % missing required fields: % (grace expired, mode=block)',
NEW.code, array_to_string(v_missing, ',');
ELSE
RAISE WARNING 'DOT % missing fields: %', NEW.code, array_to_string(v_missing, ',');
END IF;
END IF;
RETURN NEW;
END;
$$;
ALTER FUNCTION fn_birth_gate() OWNER TO workflow_admin;
§9. BOOTSTRAP — 4 BLOCKS (v5.1)
§9.1 Vấn đề gà-trứng (giữ v5.0)
§9.2 Migration PR — 4 BLOCKS
BLOCK 1 — SCHEMA:
- Tạo
dot_domains,dot_coverage_required, 4 reference tables,dot_config - Thêm 11 fields nullable vào
dot_tools(FK trỏ reference tables) - v5.1: Thêm
system_issues.issue_signature+ preflight dedupe + UNIQUE partial WHERE status='open'
BLOCK 2 — DATA:
- Seed 24 domains, reference tables (18 op), dot_config (+
birth_gate_mode='warn') - UPDATE
law_v5_1_enacted_at=NOW() AT TIME ZONE 'UTC'ISO format - Backfill
dot_toolsmetadata +_dot_origin='legacy_pre_v5_1' - Register 6 bootstrap DOT
BLOCK 3 — CONSTRAINTS + ENABLE:
- FK constraints
trg_dot_enforce_paired- v5.1: Tạo
fn_is_in_grace_period()+fn_log_issue()+fn_birth_gatev5.1 - KHÔNG bật NOT NULL (chờ BLOCK 4)
- KHÔNG bật cron (chờ BLOCK 4)
BLOCK 4 (v5.1 MỚI) — RETROFIT + DEDUPE + NOT NULL — CHECKLIST CỨNG
[ ] 4.0 ★ SNAPSHOT BASELINE (rollback safety):
- CREATE TABLE dot_tools_pre_v5_1 AS SELECT * FROM dot_tools;
- CREATE TABLE system_issues_pre_v5_1 AS SELECT * FROM system_issues WHERE status='open';
- Snapshot 45 cặp duplicate → reports/s177-block4-baseline-<date>.md
- Mapping canonical ↔ retire → reports/
[ ] 4.1 Snapshot 45 cặp duplicate file_path (chi tiết format)
[ ] 4.2 Chọn canonical row (coverage_status='complete' > created_at sớm hơn)
[ ] 4.3 Row dư: APR retire — LƯU old_file_path TRƯỚC khi NULL:
BEGIN;
UPDATE dot_tools
SET extra_metadata = extra_metadata || jsonb_build_object(
'retired_at', NOW(),
'retired_reason', 'block4_dedup_v5_1',
'old_file_path', file_path,
'canonical_dot', <canonical_code>
),
status = 'retired',
file_path = NULL
WHERE code IN (<row_du_codes>);
COMMIT;
[ ] 4.4 VERIFY: 0 row duplicate non-null file_path
[ ] 4.5 Kích DOT_BIRTH_BACKFILL (TRƯỚC 4.6: khai sinh trước, hoàn thiện hồ sơ sau)
[ ] 4.6 Kích DOT_METADATA_FILL (trong transaction; fail → rollback từ 4.0)
[ ] 4.7 Kích DOT_METADATA_AUDIT → báo cáo drift
[ ] 4.8 VERIFY: DOT_METADATA_AUDIT báo 0 drift
[ ] 4.9 CREATE UNIQUE INDEX uq_dot_tools_file_path WHERE NOT NULL
(272 row: thường đủ; >100K: khuyến nghị CONCURRENTLY)
[ ] 4.10 ★ ALTER NOT NULL ATOMIC TRANSACTION:
BEGIN;
ALTER TABLE dot_tools
ALTER COLUMN operation SET NOT NULL,
ALTER COLUMN coverage_status SET NOT NULL,
ALTER COLUMN trigger_type SET NOT NULL,
ALTER COLUMN file_path SET NOT NULL,
ALTER COLUMN cron_schedule SET NOT NULL,
ALTER COLUMN _dot_origin SET NOT NULL;
COMMIT;
(Fail cột nào → rollback toàn bộ 6 cột)
[ ] 4.11 Enable cron dot-dot-health + dot-dot-coverage + dot-metadata-repair
[ ] 4.12 Quan sát 24h. 0 critical → PASS. Critical → restore từ 4.0:
BEGIN;
TRUNCATE dot_tools;
INSERT INTO dot_tools SELECT * FROM dot_tools_pre_v5_1;
COMMIT;
[ ] 4.13 Sau 7 ngày PASS ổn định → DROP snapshot tables (safety net 7 ngày)
§9.3 Grace period (v5.1 enforce)
- Mặc định 7 ngày (
dot_config.grace_period_days). - Có thể gia hạn qua config. Khi
DOT_METADATA_AUDITcòn drift → KHÔNG được chuyểnmode='block'— gia hạn grace.
§9.4 Maintenance window (giữ v5.0)
§10. SUCCESS METRICS + TIÊU CHÍ CỨNG warn → block
Success Metrics
- 100%
dot_toolscó 11/11 fields NOT NULL - 100% DOT B có paired_dot
- 0 hardcode
- 0 duplicate file_path
- 14/14 health checks LIVE
- Flow
[AUTO-ID] DOT ToolsACTIVE +dot-metadata-repaircron LIVE -
system_issuesnhận events từ H10-H14 +fn_birth_gate - last_executed cập nhật tự động
★ TIÊU CHÍ CỨNG warn → block
Chỉ được
UPDATE dot_config SET value='block' WHERE key='birth_gate_mode'khi 4 điều kiện AND:
- ✅
DOT_METADATA_AUDITbáo 0 drift trong 3 ngày liên tiếp - ✅
0 row duplicate non-nulltrênfile_path - ✅
dot-metadata-repaircron LIVE + last_executed < 2h (H13 PASS) - ✅ H10-H14 PASS liên tục 3 ngày (0 critical mới)
Chưa đủ → giữ warn + gia hạn grace.
§11. RETROFIT CLAUSE (v5.1 MỚI)
§11.1 Nguyên tắc
Mọi luật mới áp dụng cho bảng có DATA CŨ BẮT BUỘC kèm DOT retrofit. Luật không có §retrofit = legacy mãi vênh = vi phạm HP NT1.
§11.2 Yêu cầu với mọi luật áp dot_tools (và bảng quản trị khác)
- Phải có
DOT_<LAW_ID>_BACKFILL(tier B) — scan + infer + backfill, hoặc APR. - Paired với
DOT_<LAW_ID>_VERIFY(tier A) — báo entity chưa đáp ứng →system_issues. - Chạy 1 lần sau ban hành TRƯỚC khi bật NOT NULL §4.1.
- Cron daily
DOT_<LAW_ID>_VERIFYđể catch drift.
§11.2.1 RULE auto-backfill vs APR
| Trường hợp | Hành động |
|---|---|
| Infer chắc chắn + idempotent + có verify pair | Auto-PATCH + log kb_audit_log |
| Infer mơ hồ HOẶC không idempotent | Tạo APR backfill_<field> |
§11.3 Áp cho Đ35 v5.1 — 6 DOT birth-related
| DOT | Vai trò | Kích sau ban hành |
|---|---|---|
DOT_BIRTH_BACKFILL |
Scan 272 DOT cũ, tạo birth_registry | ✅ BLOCK 4 bước 4.5 |
DOT_METADATA_AUDIT |
Report drift | ✅ Bước 4.7 |
DOT_METADATA_FILL |
Backfill metadata | ✅ Bước 4.6 |
DOT_KG_COMPLETENESS |
Verify paired FILL | ✅ Cron daily |
DOT_SCHEMA_BIRTH_REGISTRY_ENSURE |
Schema ensure | ✅ Trước BLOCK 3 |
DOT_BIRTH_TRIGGER_SETUP |
Verify fn_birth_gate trên 133 collections | ✅ Sau BLOCK 3 |
Race condition: tuần tự có barrier. KHÔNG kích đồng thời.
§11.4 Áp cho luật ĐÃ BAN HÀNH (wording cứng)
Mọi luật đang có hiệu lực mà tác động bảng có data cũ NHƯNG chưa có retrofit clause đều phải mở amend bổ sung retrofit trong kỳ sửa gần nhất. TRƯỚC KHI amend xong, KHÔNG được bật constraint/block mới làm legacy kẹt cứng.
Đ36, Đ37, Đ38, Đ39, Đ41 → audit chéo + amend retrofit. Tracker: knowledge/current-state/retrofit-audit-tracker.md (tạo trong cùng PR).
§11.5 Áp cho luật tương lai
OR soạn luật v1.0 → v1.1 bổ sung checklist: "Luật có impact lên bảng có data cũ → kèm §retrofit + DOT_<LAW>BACKFILL + DOT<LAW>_VERIFY".
§12. (Đã bỏ — PROMPT-LAW DRIFT xử ở OR + Skill Handoff)
- OR soạn luật v1.0 → v1.1: checklist "Prompt bootstrap đối chiếu §4+§9, ghi TÊN không chỉ số"
- Skill Handoff v7 + AP-22 "Đếm số không đo tên"
PHỤ LỤC A — 24 Domain Seed (giữ v5.0)
| code | name | parent_domain |
|---|---|---|
| infrastructure | Hạ tầng kỹ thuật | NULL |
| infrastructure.schema | Schema & Fields | infrastructure |
| infrastructure.sync | Đồng bộ | infrastructure |
| infrastructure.backup | Sao lưu | infrastructure |
| infrastructure.deploy | Triển khai | infrastructure |
| governance | Quản trị | NULL |
| governance.approval | Phê duyệt | governance |
| governance.audit | Kiểm toán | governance |
| birth | Khai sinh | NULL |
| birth.register | Đăng ký | birth |
| birth.orphan | Mồ côi | birth |
| classification | Phân loại | NULL |
| classification.label | Nhãn | classification |
| classification.species | Loài | classification |
| monitoring | Giám sát | NULL |
| monitoring.health | Sức khoẻ | monitoring |
| monitoring.integrity | Toàn vẹn | monitoring |
| monitoring.dot | Quản trị DOT | monitoring |
| pivot | Đếm & Báo cáo | NULL |
| sync | Đồng bộ 5 tầng | NULL |
| lifecycle | Vòng đời | NULL |
| data_quality | Chất lượng dữ liệu | NULL |
| workflow | Quy trình | NULL |
| collection | Collection Protocol | NULL |
CHANGELOG
| Ver | Ngày | Nội dung |
|---|---|---|
| v5.2 FINAL | 2026-04-18 S178 Fix 15 BAN HÀNH | Amend trực tiếp từ v5.1. Bổ sung flow fix_repair_dot, verify 3 tầng, ADMIN fallback audit, paired test retrofit, bridge/quorum liên kết với Đ32 v1.1 và hành lang ops-code/ theo Đ41 v1.1. |
| v5.1 FINAL | 2026-04-14 S177 Fix 8 BAN HÀNH | Council 2 vòng DONE. R1: Gemini 9/10 + GPT 8.3/10 APPROVE WITH CHANGES → fix 5 blocker. R2: Gemini 9.8/10 APPROVE FINAL + GPT 9.1/10 APPROVE WITH MINOR → apply 7 fix inline: (1) dot_config.value nullable + UTC ISO sentinel; (2) H14 grace_never_set > 24h; (3) fn_log_issue bỏ severity khỏi signature + escalate trên cùng row; (4) precheck dedupe system_issues trước CREATE UNIQUE INDEX; (5) §5.1 infer fail CẤM POST partial; (6) H13 chỉ báo động không self-repair; (7) BLOCK 4 +4.0 snapshot +4.3 lưu old_file_path +4.10 atomic transaction +4.13 cleanup. 0 blocker còn lại. |
| v5.0 FINAL | 2026-03-31 S151 | Ban hành gốc. Xem backup: dieu35-dot-governance-law-v5-0-backup.md. S177 phát hiện prompt bootstrap S155 thiếu 5 bảng → 49 DOT POST-S151 vẫn 94% NULL operation. |
GHI CHÚ BAN HÀNH (post-merge TODO)
Sau khi PR ban hành v5.1 merge, phải thực hiện theo thứ tự:
- ✅ Tạo
knowledge/current-state/retrofit-audit-tracker.md— theo dõi amend Đ36/37/38/39/41 theo §11.4 - ✅ Vá
dot-dot-registerpayload 11 fields + BẬT[AUTO-ID] DOT ToolsDirectus flow ACTIVE - ✅ Chạy BLOCK 4 checklist §9.2 (13 bước từ 4.0 snapshot → 4.13 cleanup)
- ✅ UPDATE
law_v5_1_enacted_at=NOW() AT TIME ZONE 'UTC' ISO'ngay khi BLOCK 2 xong - ✅ Amend song song trong cùng PR:
knowledge/dev/ssot/operating-rules-law-drafting.mdv1.0 → v1.1: checklist Gap-1knowledge/dev/ssot/anti-patterns.md: thêm AP-22 "Đếm số không đo tên"- Skill Handoff v7: bắt buộc ghi TÊN khi ghi N artifact
Điều 35 v5.1 FINAL | BAN HÀNH 2026-04-14 S177 Fix 8 | Council 2 vòng DONE | 0 blocker | Sẵn sàng deploy theo BLOCK 4 §9.2