KB-6D52

§2.6b KS.1 — INVISIBLE AUDIT GAP

5 min read Revision 1
s176pg-reconfigks1ddl-auditinvisible-gap

§2.6b KS.1 — 🔴 INVISIBLE AUDIT GAP

Part of: PG Reform Tools — S176 mission Prev: 03-k2-bypass-writers.md ← | → Next: 05-ks2-mar10-debunked.md Khối điều tra: KS.1 (K2 supplement — DDL MySQL era audit) Trạng thái: 🔴 Phát hiện quan trọng nhất của S176 điều tra


Tóm tắt phát hiện

directus_activity chỉ log DDL qua Directus REST API. Mọi DDL chạy trực tiếp psql (CI auto-apply 36 SQL file, dot-pg-*-ensure, dot-schema-taxonomy-pg-apply, dot-schema-*-apply) KHÔNG xuất hiện trong audit log nào. Cộng với PG WAL archive OFF (K0) → cửa sổ 128 ngày directus_activity chỉ cover MỘT PHẦN DDL, phần còn lại MÙ HOÀN TOÀN, không có bất kỳ log nào.

Đây là gốc lý do K0-K2 mất cả buổi mới hiểu được kiến trúc thực tế — không có ai ghi lại lịch sử DDL trực tiếp PG.


Số liệu KS.1 (cửa sổ 96 ngày H2: 2025-12-07 → 2026-03-13)

  • 2084 DDL events trên directus_collections + directus_fields (qua Directus API)
  • 100% events ghi user admin@example.com — vi phạm AP-03 ở quy mô 2084 lần (admin monopoly trước S148)
  • 99.6% là bot/script (Python-urllib 41.8%, node 31.3%, curl 19.4%) — chỉ 0.4% (9 events) qua browser UI thật
  • 2 spike đáng chú ý:
    • 2026-02-14 05:32-05:48 (16 phút): 490 create + 33 update fields từ 127.0.0.1 — bulk script, ~2 fields/giây
    • 2026-03-06 07:03-09:22: tạo collection meta_catalog + bulk update 23 collections trong 21 giây — sprint S140 prep migration
  • Hint vàng cho KS.2: 2026-03-10 có 41 events từ IP 14.162.130.216 (cùng ngày system_issues + registry_changelog ra đời)
  • directus_relations 0 events — không phải bug, là artifact thiết kế Directus (relation qua directus_fields special_field)

5 WHY — Cơ hội học gốc rễ

WHY-1 — Admin monopoly legacy

Trước S148, mọi DOT chia sẻ admin token. 2084 events H2 không thể phân biệt "DOT nào sửa schema nào" → khi NT12 yêu cầu writer/verifier khác credential thì dữ liệu lịch sử mất ý nghĩa.

WHY-2 — DOT 100% là codification, không phải start from zero

99.6% DDL là script chứng tỏ triết lý "schema bằng script" đã áp dụng từ H2, mặc dù mốc DOT 100% chính thức là 2026-03-30.

WHY-3 — directus_relations 0 events

Là artifact thiết kế Directus, không phải bug. Audit relation phải qua directus_fields (special_field=m2o).

WHY-4 — INVISIBLE AUDIT GAP (gốc lớn nhất)

Để có SSOT về DDL, phải có DDL event log ở tầng PG (event trigger pg_event_trigger_ddl_commands()) — không thể tin tầng Directus. Hoặc REVOKE quyền DDL khỏi user directus để buộc DDL đi qua 1 cửa.

WHY-5 — Bulk-prep pattern

Mỗi sprint preparation đều là 1-shot bulk (2026-03-06 tạo meta_catalog + 23 collections trong 21s). Nếu fail giữa chừng → không rollback → dữ liệu lệch.


Hệ quả thiết kế cho phương án A

Phương án A (1 password GSM + REVOKE direct + 5 ngoại lệ) chưa đủ chặn lỗ hổng audit. Cần bổ sung:

  • PG event trigger ddl_command_end ghi vào bảng ddl_audit_log mới — log MỌI DDL bất kể đi qua đường nào
  • Trigger này SECURITY DEFINER, không thể bypass
  • DOT cảnh sát dot-ddl-audit-monitor quét daily — alert nếu có DDL không có DOT owner
  • → Sửa Điều 33 §0 hoặc §15 thêm yêu cầu này trong DESIGN tổng sau khi điều tra xong, không vá lẻ tẻ

Chi tiết schema ddl_audit_log + fn_ddl_audit_capture() xem 08-dot-moi-va-catalog.md §5.5.


3 TD phát sinh từ KS.1

TD Priority Mô tả
TD-S176-DDL-MYSQL-ERA-AUDIT 🔴 High INVISIBLE AUDIT GAP. Cần PG event trigger ddl_command_endddl_audit_log SECURITY DEFINER + DOT dot-ddl-audit-monitor daily. Bổ sung Đ33 §16 sau DESIGN.
TD-S176-ADMIN-MONOPOLY-LEGACY 🟡 Medium 2084 events user=admin không phân biệt. K3 verify còn DOT dùng admin token không + backfill nhãn "events <2026-03-30 không phân biệt user".
TD-S176-LOG-WITH-SECRET 🟡 Medium Rà log file tìm secret leak: /var/log/, /opt/incomex/logs/, Directus logs, agent-data logs, telegram logs. Pattern: password=, token=, Bearer, Incomex2026PG, _secret, api_key.

File 04 — §2.6b KS.1 | Index | S176 | Living doc