KB-5C50

§3 Phương án A+ + §4 5 Ngoại lệ E1-E5

6 min read Revision 1
s176pg-reconfigphuong-an-a-plusexceptionse1-e5

§3 PHƯƠNG ÁN A+ + §4 5 NGOẠI LỆ E1-E5

Part of: PG Reform Tools — S176 mission Prev: 06-ks3-metadata-shells.md ← | → Next: 08-dot-moi-va-catalog.md Trạng thái: Sơ bộ — sẽ chốt lại trong DESIGN D8 sau khi điều tra xong KS.4-KS.6 + K3-K5


§3. PHƯƠNG ÁN GIẢI QUYẾT — PHƯƠNG ÁN A+ (SƠ BỘ)

Lưu ý: Phương án A đã lộ ra 2 lỗ hổng mới sau KS.1+KS.3. Giữ phương án A làm khung xương chính, nhưng CHƯA chốt cuối — phải đợi điều tra xong KS.4-KS.6 + K3-K5 rồi mới DESIGN tổng. Tránh vá lẻ tẻ.

§3.1 Bản chất phương án A

Dùng PostgreSQL ROLE + PASSWORD AUTHENTICATION (cơ chế chuẩn ngành):

  1. 1 password DUY NHẤT cho cluster PG, lưu GSM (Google Secret Manager) làm SSOT
  2. 1 biến .env CHUNG trên VPS (/opt/incomex/.env, chmod 600, owner root) chứa password
  3. Cả PG container và mọi DOT đọc cùng biến này — đổi GSM 1 lần → kéo về VPS 1 lần → cả hệ thống nhận
  4. PG REVOKE mọi connection trustless. Mọi connection PHẢI có password đúng.
  5. DOT đã review code, không sợ nhầm. Mã DOT cứng, không tự đổi ý. Lo ngại chính = chặn ai đó (người, AI, script ngoài) cố ghi PG mà không có thẩm quyền.

§3.2 Tại sao phương án A, KHÔNG phải C (thuần)

Phương án C (Single Function Gateway): Mọi ghi đi qua 1 PG function. Nhưng K1 cho thấy 3 vùng buộc đi thẳng PG (DDL bootstrap không có function tương đương, function call vốn là PG-only, normative tables PG-only). Phương án C thuần chỉ ổn cho DML data, không ổn cho DDL schema.

Phương án A đơn giản hơn, đúng kiến trúc Directus + DOT đang có.

Hạn chế phương án A (sau KS.1+KS.3):

  • Hạn chế cũ (K1-K2): Logic dedupe vẫn nằm trong code DOT từng cái → user có password đúng vẫn có thể viết SELECT-then-INSERT sai. Phải kết hợp UNIQUE constraint ở schema.
  • (MỚI KS.1) Không có audit DDL ở tầng PG → cần PG event trigger ddl_command_end + ddl_audit_log + dot-ddl-audit-monitor (bắt buộc bổ sung)
  • (MỚI KS.3) Registry có "metadata shells" vô hiệu hoá §0-AY → cần PG constraint file_path NOT NULL + dot-file-path-orphan-check + CI gate (bắt buộc bổ sung)
  • (ARGUMENT KS.2 WHY-5) Tuyến L1 qua Directus API là tuyến forensic khả thi DUY NHẤT → nếu giữ phương án A cho cả DDL, cần event trigger tầng PG để không mất forensic trail

Kết luận tạm thời: Phương án A + 2 lớp bổ sung (DDL audit trigger + file_path constraint) = "Phương án A+". Sẽ chốt lại trong DESIGN sau KS.6.

§3.3 Cấu trúc biến môi trường

# /opt/incomex/.env (chmod 600, owner root)
PG_PASSWORD=<lấy từ GSM, không hardcode>
PG_HOST=postgres
PG_PORT=5432
PG_USER_DIRECTUS=workflow_admin    # user cho directus DB (Lớp KHO)
PG_USER_AGENT=incomex              # user cho incomex_metadata DB (Lớp NÃO)
PG_USER_ADMIN=workflow_admin       # superuser cho admin emergency

§3.4 Quy trình rotate password

gcloud secrets versions add pg-password --data-file=- < new_password.txt
gcloud secrets versions access latest --secret=pg-password > /opt/incomex/.env.new
chmod 600 /opt/incomex/.env.new
mv /opt/incomex/.env.new /opt/incomex/.env
docker compose restart postgres

§3.5 DOT đọc password — pattern chuẩn

Bash/Python/Node.js: source/load /opt/incomex/.envPGPASSWORD env var → connect. Xem Đ33 §14.4.

§3.6 CẤM TUYỆT ĐỐI

  • CẤM hardcode password trong code/SQL/YAML/comment
  • CẤM commit .env vào git
  • CẤM gửi password qua chat
  • CẤM dùng password trong URL parameter
  • CẤM admin connect bằng tài khoản chung không audit

§3.7 DOT cảnh sát kiểm tra (bổ sung KS.1+KS.3)

  • dot-pg-credential-audit (A, weekly): quét hardcoded password, git history leak
  • dot-pg-connection-monitor (A, daily): query pg_stat_activity xem connection lạ
  • dot-ddl-audit-monitor (A, daily — MỚI KS.1): đọc ddl_audit_log bảng mới, alert nếu DDL không có DOT owner
  • dot-file-path-orphan-check (A, daily — MỚI KS.3): cross-ref ls dot/bin/ vs dot_tools.file_path, alert nếu mismatch

§4. 5 NGOẠI LỆ DOT 100% — HỢP PHÁP HOÁ

Bài học S176: NT3 "DOT 100%" trong HP cũ áp cứng → 3 vùng kỹ thuật + 2 vùng kiến trúc về bản chất KHÔNG THỂ qua Directus REST. Luật cứng quá → người ta bypass → bệnh quay lại. Sửa luật, không sửa hành vi: thừa nhận 5 ngoại lệ HỢP PHÁP, có điều kiện ràng buộc rõ ràng.

§4.1 NGOẠI LỆ KỸ THUẬT (3 ngoại lệ)

E1 — Schema Bootstrap DDL

  • Ai: dot-pg-*-ensure, dot-schema-*-apply
  • Cách: docker exec postgres psql
  • Điều kiện: đăng ký dot_tools, idempotent, có DOT cặp, password GSM, log vào dot_run_log

E2 — PG Function Call

  • Ai: Cron + DOT gọi SELECT fn_*() trực tiếp
  • Điều kiện: function SECURITY DEFINER, cron link tới DOT installer, idempotent, log dot_run_log

E3 — Normative Law Tables (PG-only)

  • Ai: Cụm dot-nrm-*
  • Điều kiện: domain='normative', pattern an toàn, DOT cặp, password GSM

§4.2 NGOẠI LỆ KIẾN TRÚC (2 ngoại lệ)

E4 — Agent Data → incomex_metadata

  • Ai: pg_store.py connect trực tiếp PG
  • Điều kiện: Agent Data = gateway duy nhất, pattern ON CONFLICT DO UPDATE, đăng ký dot_tools, password GSM

E5 — Workflow Engine → workflow DB (chưa active)

  • Ai: TBD
  • Điều kiện: Sẽ định khi engine active

§4.3 KHÔNG HỢP PHÁP — Phải dẹp

Mọi pattern KHÔNG nằm trong E1-E5 = vi phạm NT3, phải dẹp:

  • Script ad-hoc psql tay
  • CI bypass session variable
  • Hardcoded password
  • SQL file vĩnh viễn auto-apply không qua DOT
  • Writer ghi PG bằng connection không qua GSM
  • (KS.3 mới) Writer có metadata trong dot_tools nhưng file_path=NULL — "metadata shells"

File 07 — §3 Phương án A+ + §4 Ngoại lệ | Index | S176 | Living doc