KB-1CC9 rev 2

LỆNH 1.5 — Forensic drift chỉ đọc (2026-07-15)

17 min read Revision 2
codexreportsforensicdriftvps-ssotreadonly2026-07-15da89657491-1171

LỆNH 1.5 — Forensic drift chỉ đọc (2026-07-15)

0. Kết luận điều hành

DỪNG deploy da89657; DỪNG mọi recreate/restore. Điều tra xác nhận cú triển khai ngày 11/07 đã chép nội dung GitHub 07caed3b lên các tệp làm việc VPS ở ba vùng:

  • docker/docker-compose.yml — trùng byte với GitHub 07caed3b;
  • docker/nginx/conf.d/default.conf — trùng byte với GitHub 07caed3b;
  • 40 tệp dot/bin/* đang drift — từng tệp đều trùng byte với GitHub 07caed3b.

Phép đo DOT 491+/1171- có chiều chính xác là:

trái = Git DOT SSOT commit 5a2e1bf (nội dung trước sự cố cho 40 tệp bin); phải = working tree VPS hiện tại sau rsync ngày 11/07.

Vì vậy 1171- là 1.171 dòng có trong mốc VPS đã commit nhưng không còn trong tệp làm việc hiện tại. Chúng không biến mất hoàn toàn: nội dung vẫn còn trong Git object của repo DOT. Ngoại lệ duy nhất trong tập 41 là sql/approved-sql-manifest.tsv: 6 dòng thêm có mtime 07/07, tức có trước sự cố và phải giữ.

Ba hồi quy DOT nghiêm trọng đã được chứng minh bằng version:

  • dot-apr-execute: 2.2.0 → 1.0.0;
  • dot-apr-propose: 2.0.2 → 1.0.0;
  • dot-dot-health: 2.0.0 → 1.0.0.

Compose hiện tại còn nguy hiểm hơn diff thuần túy: nó không mô tả đúng runtime đang chạy. Container Agent Data đang chạy agent-data-local:latest, có các biến DIRECTUS_DB_*PG_*; compose hiện tại lại trỏ image Artifact Registry và xóa toàn bộ các biến này. Recreate theo compose hiện tại có thể làm lùi Agent Data.

Riêng nginx hiện tại có nguồn từ GitHub nhưng phân tích ngữ nghĩa không thấy mất tuyến chức năng: các include MCP/KB vẫn còn, /api/reports/ còn, whitelist /.well-known/* mới hơn đang hoạt động. Không nên phục hồi nginx về commit cũ.

da89657 chưa đủ điều kiện deploy: 88/88 route artifact có đủ; ba route registries-pivot trùng byte production và MCP không thuộc artifact Nuxt. Nhưng candidate thiếu giao diện ma trận đang có trên production (pivot-matrices, TemplatesMatrixView, matrix_spec). Do đó chưa thể chứng minh da89657 ⊇ runtime; đã chứng minh được một khoảng thiếu cụ thể.

Không có service nào bị restart/reload/recreate; không có file VPS hay DB nào bị ghi trong mission này.

1. Phạm vi, luật và phương pháp

Đã đọc trực tiếp:

  • .claude/skills/incomex-rules.md — 36 mục, quy trình 8 bước;
  • KB operating rules SSOT;
  • KB hiến pháp v4.0 constitution;
  • báo cáo sự cố/Reports liên quan.

Mission này là forensic, không thiết kế feature mới; Bước 2 về thiết kế sản phẩm là N/A. Mọi kiểm tra production là read-only: Git object/hash/diff, metadata file, docker inspect, nginx -t, và HTTP GET.

3 câu Tuyên ngôn

  1. Vĩnh viễn: quyết định khôi phục phải dựa trên mốc và chiều diff có hash, không dựa vào tên “backup” hay giả định GitHub là chuẩn.
  2. Nhầm được không: chưa cho deploy/recreate khi compose không khớp runtime và candidate Nuxt chưa là tập cha; gate bằng bằng chứng artifact và content.
  3. 100% tự động: chưa đạt trong mission chỉ đọc. Bước sửa sau phải tạo drift verifier tự so working tree với SSOT và chặn deploy nếu xóa tính năng/runtime contract.

2. Mốc và chiều diff

Nhóm Mốc trái Mốc phải Kết quả Ý nghĩa dấu +/-
Compose /opt/incomex HEAD b5e0f962 — file docker/docker-compose.yml working file cùng path, trùng GitHub 07caed3b:infra/docker/docker-compose.yml 80+/61- + chỉ có ở file hiện tại; - chỉ có ở root HEAD
Nginx /opt/incomex HEAD b5e0f962 — file docker/nginx/conf.d/default.conf working file cùng path, trùng GitHub 07caed3b:infra/nginx/conf.d/default.conf 26+/25- như trên
41 DOT /opt/incomex/dot HEAD 5a2e1bf working tree /opt/incomex/dot 491+/1171- + là dòng current-only; - là dòng HEAD-only bị thiếu khỏi working tree

Hash bằng chứng:

compose current/GitHub07ca/infra-prev = 7f24333632597db02713cd4fcb9f803c2c2e38e7d9e66d0b49d70ec03f9b0f26
compose root HEAD                   = 798b4b2c8c9574449498895939c72d2b91c4f4796862e565622464ae443bb501

nginx current/GitHub07ca/infra-prev = 9404dce882aab39c3d56c2f9a314f21d86e49e852939e8ed74a1a72bebd5ea77
nginx root HEAD                     = 63789b6934b093439520a6e55360c3f2ae294130092b57d1b0d4e72e0eb4c0c4

Thời gian ghi file hiện tại:

40 DOT bin: 2026-07-11 04:47:37 +0200
compose:    2026-07-11 04:50:30 +0200
nginx:      2026-07-11 04:50:30 +0200

3. Compose — mã đúng còn/mất và rủi ro

Hạng mục Hiện trạng Mã đúng còn/mất Rủi ro để nguyên Rủi ro phục hồi nguyên file
Agent Data image Live: agent-data-local:latest; compose: Artifact Registry Contract runtime bị mất khỏi compose Rất cao nếu recreate: đổi image ngoài ý muốn Cao: root HEAD/backup cũ có thể thiếu thay đổi sau tháng 4/6
Agent Data memory Live được tạo theo ${AGENT_DATA_MEM_LIMIT:-2560m}; compose: 1536m cấu hình đang chạy không còn trong current Cao khi recreate Vừa; phải hợp nhất có chọn lọc
Agent Data DB env Live có DIRECTUS_DB_*PG_*; current xóa cả hai nhóm mất khỏi file, còn thấy trong docker inspect và backup tháng 6 Rất cao khi recreate Vừa nếu chỉ phục hồi đúng block; cao nếu phủ cả file
Nuxt RP PG env Current có RP_PG_*, live cũng có còn nguyên, là bổ sung Reports hợp lệ Thấp nếu giữ Cao nếu phục hồi compose cũ và làm mất gateway Reports/pivot
Nuxt image Live/current đều Artifact Registry; root/backup cũ là local image current khớp live thấp vừa-cao nếu đổi ngược image

Container start time chứng minh compose drift chưa được áp đồng loạt:

postgres             2026-04-17
incomex-directus     2026-05-08
incomex-agent-data   2026-05-19  image=agent-data-local:latest
incomex-nginx        2026-06-30
incomex-nuxt         2026-07-11  image=.../nuxt-ssr:latest

Kết luận compose: không giữ nguyên dài hạn, không restore nguyên file, tuyệt đối không recreate. Cần một lệnh sau có Owner gate để dựng compose hợp nhất từ runtime contract + RP env, rồi verify render config trước khi chạm service.

4. Nginx — mã đúng còn/mất và rủi ro

Diff 26+/25- chủ yếu là:

  • xóa/đổi comment;
  • thay broad /.well-known/* → 404 bằng ba endpoint whitelist rồi mới fallback 404;
  • giữ nguyên các include bí mật MCP/KB;
  • giữ /api/reports/ đứng trước /api/ catch-all;
  • giữ UI preview routes.

Evidence production:

nginx -t → syntax is ok / test is successful
GET /api/reports/live?table_id=tbl_report_pg → 200
GET /.well-known/oauth-authorization-server → 200
GET /.well-known/openid-configuration → 200
GET /api/mcp → 200

Kết luận nginx: giữ current. Root HEAD b5e0f962 không phải mốc phục hồi đầy đủ vì thiếu whitelist OAuth mới hơn. Không có bằng chứng tuyến MCP/KB bị mất trong diff này.

5. Bảng 41 tệp DOT

Mã phân loại:

  • C1: hồi quy lõi/version, mã đúng mất khỏi working file nhưng còn trong Git DOT HEAD;
  • C2: mất cơ chế xác thực Agent Data;
  • C3: bổ sung hợp lệ trước sự cố, phải giữ;
  • C4: GitHub hardcode PG thay cho biến có default; mất khả năng cấu hình/SSOT.

Tất cả 40 file bin/* dưới đây trùng byte với GitHub 07caed3b; 39/40 có candidate khôi phục giống nhau trong root HEAD và DOT HEAD. Riêng dot-dot-health nên lấy DOT HEAD, vì DOT HEAD có thêm safe source guard và chấp nhận --local|--cloud so với root HEAD.

File Drift Loại Mã đúng còn/mất Rủi ro giữ current Rủi ro phục hồi có kiểm soát
bin/dot-apr-execute 114+/441- C1 mất khỏi working; còn DOT HEAD rất cao: 2.2.0→1.0.0, mất dispatch/patch guard/verify vừa: syntax + contract verifier trước kích hoạt
bin/dot-apr-health 3+/3- C4 mất default-env vừa: hardcode PG thấp-vừa
bin/dot-apr-propose 19+/114- C1 mất khỏi working; còn DOT HEAD rất cao: 2.0.2→1.0.0, mất metadata action + reject/log vừa
bin/dot-birth-backfill 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-birth-trigger-setup 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-collection-create 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-collection-field-sync 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-collection-health 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-coverage-inspector 2+/2- C4 mất default-env trong lệnh PG vừa thấp-vừa
bin/dot-cron-matrix-setup 1+/1- C4 mất default-env trong cron vừa thấp-vừa
bin/dot-cron-pivot-setup 3+/3- C4 mất default-env trong cron vừa thấp-vừa
bin/dot-dot-coverage 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-dot-health 250+/508- C1 mất khỏi working; còn DOT HEAD rất cao: 2.0.0→1.0.0, mất generic executor/guards/SSOT vừa; chọn DOT HEAD, không chọn root HEAD
bin/dot-dot-register 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-entity-deprecate 2+/2- C4 mất default-env trong lệnh PG vừa thấp-vừa
bin/dot-entity-retire 2+/2- C4 mất default-env trong lệnh PG vừa thấp-vừa
bin/dot-inspect-pen 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-knowledge-search 0+/6- C2 mất load API key + header cao: KB search có thể 401/không hoạt động thấp-vừa
bin/dot-label-trigger-setup 2+/2- C4 mất default-env trong lệnh PG vừa thấp-vừa
bin/dot-matrix-declare 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-matrix-health 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-matrix-retire 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-matrix-update 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-migration-s127d-legacy-origin 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-migration-s128b-dead-links 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-migration-s155-p1b 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-nrm-draft 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pg-audit-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pg-triggers-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pg-views-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pivot-declare 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pivot-health 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-pivot-virtual-create 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-production-truth-gate 2+/2- C4 mất default-env trong lệnh PG cao: gate bị hardcode thấp-vừa
bin/dot-schema-birth-registry-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-schema-dot-origin-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-schema-meta-catalog-add-composition 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-schema-species-tree-ensure 3+/3- C4 mất default-env vừa thấp-vừa
bin/dot-schema-taxonomy-pg-apply 4+/4- C4 mất default-env trong lệnh PG vừa thấp-vừa
bin/dot-schema-trigger-registry-ensure 3+/3- C4 mất default-env vừa thấp-vừa
sql/approved-sql-manifest.tsv 6+/0- C3 còn nguyên; mtime 07/07 trước sự cố thấp khi giữ cao nếu restore phủ: mất 6 SQL Sửa RE đã phê duyệt

Sáu dòng manifest là các entry sua-re/*; đây thuộc Sửa RE, mission này không thực thi và không đụng dữ liệu balo.

6. Phân tích deploy da89657 (không deploy)

Phần đã chứng minh không lùi

Surface Evidence Kết luận
Route inventory live = 88 file; candidate = 88 file không mất route server
Registries-pivot API hash node/rows/summary và source map trùng byte giữa live/candidate không lùi ba API này
Reports API reports/live.get.mjs hash trùng byte live/candidate route live giữ nguyên; thay đổi chính ở UI refresh
MCP /api/mcp do nginx/Agent Data, không nằm trong volume .output Nuxt; production trả 200 deploy riêng .output không sửa nginx/compose/MCP

Hash pivot tiêu biểu:

node.get.mjs    5402d21f4b95a1473a8860be6d078488613e81bf950cf2b4ecc3f01c26155800
rows.get.mjs    4dc7e46eb5259da2a55d18dbafb3d305f01ef1414f53983b44e105cdcff23942
summary.get.mjs fb81d88c927a142409728fbc0080564f6e8bde655f66bf88ac52b8a24d6b8cbc

Khoảng thiếu đã chứng minh

GitHub/runtime hiện có:

  • components/templates/MatrixView.vue;
  • pages/knowledge/pivot/index.vue tải pivot_definitions.matrix_spec;
  • build live chứa marker pivot-matrices, TemplatesMatrixView, matrix_spec.

Candidate da89657:

  • không có components/templates/MatrixView.vue;
  • trang Knowledge Pivot không còn block “Ma trận đa chiều”;
  • build candidate không có ba marker trên.

Evidence marker:

pivot-matrices:       live=1 candidate=0
TemplatesMatrixView:  live=1 candidate=0
matrix_spec:          live=1 candidate=0

Do đó da89657 không phải tập cha của runtime hiện tại. Deploy ngay có thể sửa nút Reports nhưng làm mất giao diện ma trận Knowledge Pivot. Gate deploy phải giữ.

Production vẫn hoạt động lúc forensic

2026-07-15T04:12:17Z
GET /api/reports/live?table_id=tbl_report_pg
HTTP 200; Cache-Control: no-store, max-age=0
table=385; function=654; trigger=410; view=699; rows=12
refreshed_at=2026-07-15T04:12:17.010Z

GET /api/registries-pivot/summary
HTTP 200; nodes=39; roots=26; leaf_rows=160; generated_at=2026-07-15T04:12:18.010Z

GET /api/mcp → HTTP 200

7. Backup và độ tin cậy

Candidate Độ tin cậy Dùng thế nào
Git objects /opt/incomex/dot HEAD 5a2e1bf Cao cho 40 DOT bin nguồn phục hồi theo file sau Owner gate; riêng dot-dot-health ưu tiên mốc này
Root Git HEAD b5e0f962 Cao để đối chiếu; không phải full current cho compose provenance, không restore nguyên compose
deploys/infra-prev/* Không tin cậy trùng byte file GitHub đã ghi đè; không phải pre-incident
backup code/VPS 14–15/07 Không dùng để phục hồi sự cố tạo sau 11/07, đã chứa drift
DOT bundle 25/06 Vừa mốc chéo trước sự cố nhưng cũ hơn DOT HEAD 28/06+
docker-compose.yml.pre-executor-20260604... Vừa cho block Agent Data có local image + PG env, nhưng thiếu RP env mới; chỉ dùng đối chiếu/merge
default.conf.bak.pre-reports-live... Vừa có MCP/KB trước Reports nhưng thiếu Reports + OAuth whitelist; không restore nguyên file
approved-sql-manifest.tsv.bak-g1-* Thấp cho current cũ hơn 6 entry 07/07; restore sẽ làm mất metadata hợp lệ

8. Khuyến nghị theo thứ tự và Owner gate

  1. Giữ runtime nguyên trạng. Không deploy da89657, không recreate, không reload, không restore.
  2. Owner mở lệnh riêng để dựng candidate Nuxt hợp nhất: lấy VPS source da89657 làm nền, đưa lại MatrixView.vue + block Knowledge Pivot và mọi live-only feature được inventory; build rồi so content/artifact, không chỉ route count.
  3. Owner mở lệnh riêng để khôi phục 40 DOT theo file từ DOT HEAD, giữ nguyên manifest 6 dòng; syntax/test từng nhóm trước khi kích hoạt scheduler. Không copy cả thư mục.
  4. Owner mở lệnh riêng để hợp nhất compose, tối thiểu giữ Agent Data image/env/memory đang chạy và RP env; chạy config-render diff với docker inspect. Chưa recreate service trong bước này.
  5. Giữ nginx current, chỉ đưa nó vào SSOT commit sau khi Owner duyệt; không phục hồi từ root HEAD hay backup cũ.
  6. Khi candidate Nuxt đã là tập cha, mới xin gate deploy Reports; verify production bằng số + timestamp + click thật + Knowledge Matrix + registries-pivot + MCP.
  7. Cuối cùng mới sao ngược SSOT đã sạch về GitHub.

9. Trạng thái Bước 0→6

  • Bước 0: đọc skill/OR/Hiến pháp và luật liên quan.
  • Bước 1: chốt mission forensic chỉ đọc.
  • Bước 2: N/A — không thiết kế feature; lập mốc/chiều diff trước kiểm tra.
  • Bước 3: không code/không sửa runtime; chỉ thu evidence.
  • Bước 4: không deploy/recreate/reload.
  • Bước 5: verify production bằng content GET và artifact/hash.
  • Bước 6: báo cáo này; OR/TD không cập nhật vì chưa có quyết định hay thay đổi hệ thống.

Trạng thái cuối: FORENSIC COMPLETE / DEPLOY BLOCKED BY PROVEN FEATURE GAP / CHỜ OWNER.