KB-1458

Claude — C1: Loại Directus admin password hardcode khỏi current source (2026-07-17)

16 min read Revision 1
current-statec1secret-containmentdirectus-admin-passwordreconcilehardcode-removedprotected-env-filefail-closeddocker-exec-envvps-ssotgit-safetyrollback-readyzero-mutationhistorical-exposure-activerotation-priority-high2026-07-17PASS_CURRENT_DIRECTUS_ADMIN_HARDCODE_REMOVED

C1 — Loại plaintext DIRECTUS_ADMIN_PASSWORD khỏi source/worktree hiện hành (2026-07-17)

Tác giả: Claude (Opus 4.8). Host: vmi3080463 / 38.242.240.89 (Contabo). Nguồn điều hành: survey rev8 + Wave A1 rev1 + C0 rev1 — đọc toàn văn cả ba + đo live. Mọi giá trị secret = REDACTED. Không password/token/key nào trong báo cáo này. Owner đã chốt Phương án 1 (thực thi + nguồn đang đẩy off-site) + ràng buộc A–G.


1. EXECUTIVE VERDICT

PASS_CURRENT_DIRECTUS_ADMIN_HARDCODE_REMOVED
  → overall: PASS_WITH_HISTORICAL_EXPOSURE_REQUIRING_PRIORITY_ROTATION

ACTIVE_EXECUTION_HARDCODE        = REMOVED     (/opt/incomex/scripts/*.py + wrappers)
ACTIVE_OUTBOUND_SOURCE_HARDCODE  = REMOVED     (agent-data-repo/scripts/*.py)
LOCAL_DORMANT_RESIDUAL           = REMAINS     (3 worktree + .env.bak + .env.local)
HISTORICAL_EXPOSURE              = REMAINS     (Git/GitHub/Drive history)

🔴 NÓI THẲNG (không được hiểu nhầm): Mật khẩu admin Directus VẪN đang hiệu lựcVẪN phơi trên GitHub (branch vps-daily-* + main, đẩy 2×/ngày) và trong 56 artifact Drive/repo + history. C1 chỉ ngừng đẻ bản plaintext mới từ source hiện hành, KHÔNG thu hồi chìa đã phát tán. Rotate admin Directus là việc GẤP kế tiếp, không phải việc thư thả sau A2. Đây KHÔNG phải "mọi current plaintext copy đã bị xóa" và KHÔNG phải đóng exposure.

LOCAL_DORMANT_PLAINTEXT_RESIDUAL = ACTIVE
OFFSITE_PROPAGATION (residual)   = NO
ROTATION_WILL_INVALIDATE         = YES
SANITIZATION_WAVE_REQUIRED       = YES

2. SOURCES READ

  • claude-c0-stop-git-history-drive-propagation-2026-07-17.md (rev1, toàn văn)
  • claude-post-migration-service-secret-controlplane-reconciliation-survey-2026-07-17.md (rev8, toàn văn qua subagent)
  • claude-wave-a1-agent-data-image-compose-env-hardening-2026-07-17.md (rev1, toàn văn qua subagent)
  • Live evidence: crontab, wrappers, scripts (redacted), docker/.env (value trích tmpfs, không in), container env SET/UNSET, git status/HEAD/bundle.

3. GIT SAFETY GATE (PASS)

repo /opt/incomex                branch feat/s177-sprint1-round-a  HEAD(PRE) 74459bd  remote KHÔNG CÓ ⇒ push bất khả thi
repo /opt/incomex/docker/agent-data-repo  branch main  HEAD(PRE) 0ffd6778  remote github.com/Huyen1974/agent-data-test
6 target files: TRACKED + CLEAN pre-patch (0 unrelated modification chồng lấn)
Phân loại: MISSION_CHANGE=6 · VERIFIED_LIVE_BASELINE (docker/.env value) · UNRELATED_WORK=103→104 (giữ nguyên) · SECRET_IN_HEAD (pre) =6 · UNKNOWN=0
Checkpoint: /root/c1-checkpoint-20260717T203954Z  (root:root 0700, NGOÀI mọi outbound scope — D4)

Bundles (root-only, VPS-only, ngoài Drive/GitHub/KB — D4):

opt-incomex-PRE.bundle        afca429a6e7a7fbb756d6ebadab2b32e4b7f544eaf464167f939f4471b09245f
agent-data-repo-PRE.bundle    88b2c5f702ff4b9e66c3199423d650cf8aa742b306ee8b13df1e05e8626ad9d4
opt-incomex-POST.bundle       15c82c78c3a9d031c589e79249cc626a1b36d70632eb5abec1f3a0baf2f83b56
agent-data-repo-POST.bundle   242e8f08fd55aed5dd5561ceeb49f72f0a3d9b83683fd77918717a630a4049cc
git bundle verify: cả 4 = "is okay" + "records a complete history"  ⇒ PASS
VPS_SSOT_GIT_SAFETY = PASS

4. EXACT AFFECTED SOURCE FILES (6 target)

/opt/incomex/scripts/reconcile-knowledge.py   (EXECUTED — docker cp → exec trong incomex-agent-data)
/opt/incomex/scripts/reconcile-tasks.py       (EXECUTED)
/opt/incomex/scripts/reconcile-knowledge.sh   (wrapper THỰC THI)
/opt/incomex/scripts/reconcile-tasks.sh       (wrapper THỰC THI)
/opt/incomex/docker/agent-data-repo/scripts/reconcile-knowledge.py   (TRACKED → Drive 4×/ngày + GitHub 2×/ngày)
/opt/incomex/docker/agent-data-repo/scripts/reconcile-tasks.py       (TRACKED)

Đính chính premise mission: bản mission NÊU TÊN (agent-data-repo/scripts/*.py) KHÔNG được thực thi; bản THỰC THI là /opt/incomex/scripts/*.py (khác byte, repo /opt/incomex không remote). Hai bộ Python khác byte ⇒ áp cùng semantic patch tối thiểu cho từng file, KHÔNG copy đè (ràng buộc A).

5. DIRECTUS ADMIN VALUE VERIFICATION (payload REDACTED)

DIRECTUS_ADMIN_VALUE = VERIFIED_CURRENT
value length = 23 bytes (REDACTED). Nguồn canonical: docker/.env (0600, §5 CẤM sửa — giữ nguyên).
Phương pháp: trích value vào tmpfs 0600 (không qua argv, không in) → grep -Ff.
grep -Ff (value) match=1 ở CẢ: docker/.env + 4 reconcile .py (/opt + adr) + 6 worktree copy ⇒ 1 giá trị duy nhất, KHÔNG VALUES_DIFFER.
Auth smoke: docker exec -e DIRECTUS_PASSWORD (name-only) → POST {DIRECTUS_URL}/auth/login {email=admin@example.com}
  → AUTH_OK http=200 has_token=True ; env_seen_len=23. Không in request body/token; không giữ session.
Endpoint: DIRECTUS_URL container-internal http://incomex-directus:8055 ; account admin@example.com.

6. SCRIPT INVOCATION MAP (đo live)

root crontab (Europe/Berlin):
  0 */6 * * *  /opt/incomex/scripts/reconcile-tasks.sh      >> /var/log/reconcile-tasks.log 2>&1
  0 */6 * * *  /opt/incomex/scripts/reconcile-knowledge.sh  >> /var/log/reconcile-knowledge.log 2>&1
  → user = root ; TZ = CEST → chạy 00/06/12/18 CEST (last 18:00, next 00:00)
wrapper: docker cp /opt/incomex/scripts/reconcile-X.py incomex-agent-data:/tmp/... ; docker exec … python3 /tmp/…
Container incomex-agent-data KHÔNG set DIRECTUS_PASSWORD/EMAIL ⇒ (pre-C1) script chạy bằng HARDCODED DEFAULT.

7. GITHUB OUTBOUND MECHANISM (§9 — read-only, KHÔNG sửa/không chạy)

job         /opt/incomex/scripts/git-push-gh-daily-v2.sh
schedule    0 6,18 * * *  CRON_TZ=Europe/Berlin  ⇒ 06:00/18:00 CEST (2×/ngày)  [đính chính C0: CEST không phải UTC]
source      /opt/incomex/docker/nuxt-repo + /opt/incomex/docker/agent-data-repo
mechanism   git add -A + commit + force-push  ⇒ GITHUB_OUTBOUND_MODE = FULL_GIT_HISTORY
dest        github.com/Huyen1974/{web-test,agent-data-test}  branch vps-daily-YYYYMMDD (+ main)  CLEANUP_DAYS=7
credential  /opt/incomex/.git-token (PAT ~41B, 0600, trên VPS) ; bản sao SM gh_pat_sync_secrets (scope repo+workflow)
            ⇒ credential KHÔNG chỉ-trên-VPS (có bản SM); đủ quyền bật lại 5 workflow deploy đang disabled

8. PROTECTED CREDENTIAL FILE CONTRACT

path    /etc/incomex/reconcile/directus-admin.env   (dir /etc/incomex/reconcile root:root 0700)
owner   root:root      mode 0600      format  DIRECTUS_PASSWORD='<value>'  (value byte-exact từ docker/.env)
value_len = 23 ; sourcing (set -a; . file) → env_seen_len=23
NGOÀI: mọi git root · Drive backup source · GitHub outbound source · web-served · KB/evidence · Docker build context.
Chỉ chứa credential reconcile-Directus (không gom credential khác).

9. SOURCE CHANGES (semantic patch tối thiểu, per-file)

.py (mỗi file đúng 1 match, sys/os đã import):

-DIRECTUS_PASSWORD = os.getenv("DIRECTUS_PASSWORD", "<REDACTED live value>")
+DIRECTUS_PASSWORD = os.environ.get("DIRECTUS_PASSWORD", "")
+if not DIRECTUS_PASSWORD:
+    sys.stderr.write("FATAL: DIRECTUS_PASSWORD not set in environment; refusing to run (no hardcoded fallback)\n")
+    sys.exit(3)

Wrapper (.sh, ràng buộc B): set -euo pipefail + set +x; đọc protected file; fail-closed nếu file thiếu/không đọc được, perm≠600 hoặc owner≠root, biến rỗng; set -a; . envfile; set +a (export); docker exec -e DIRECTUS_PASSWORD (chỉ tên biến, value KHÔNG vào argv).

10. STATIC & FAILURE-MODE TESTS

py_compile ×4 = OK · bash -n ×2 = OK
fail-closed: chạy bản .py đã vá TRONG container KHÔNG có env → exit 3 (module-top guard, không WRITE)  ✓
wrapper fail-closed: thiếu export ⇒ container thấy rỗng ⇒ script exit 3 (defense-in-depth chứng minh)  ✓

11. DIRECTUS AUTHENTICATION SMOKE (§14.2)

D0a mechanism (cron-env, set -a → docker exec -e → authtest): env_seen_len=23 · AUTH_OK http=200 has_token=True
D0b real wrappers --dry-run (env -i HOME/LOGNAME/PATH=/usr/bin:/bin/SHELL, ĐÚNG ngữ cảnh cron):
   reconcile-tasks.sh --dry-run     rc=0  (Reconciliation start, no FATAL/Traceback/auth-failed)
   reconcile-knowledge.sh --dry-run rc=0
Không in request body/token; không WRITE (dry-run). Token không giữ.

12–14. VALUE-SCAN (theo GIÁ TRỊ) — methodology + worktree + HEAD

Method: value → tmpfs 0600 (stdin/file, KHÔNG argv) → grep -Ff ; chỉ đếm MATCH/NO_MATCH ; payload REDACTED.
Working-tree 6 target : match=0 mỗi file          (CURRENT_TRACKED_SOURCE_COPY=0, CURRENT_UNTRACKED_COPY trong scope=0)
Staged 6 target       : match=0 mỗi file
HEAD tree 6 target    : match=0 mỗi file          (CURRENT_HEAD_PLAINTEXT=0)
Protected file        : match=1                    (AUTHORIZED_PROTECTED_COPY=1)

15. LOCAL DRIVE-PACKAGE SIMULATION (§15.1 / E — KHÔNG upload, KHÔNG retention, KHÔNG xóa)

A) code-backup (agent-data-repo): rsync với 11 exclude PARSE TỪ SCRIPT LIVE (.git in danh sách) → stage → tar (list-only)
   reconcile-{knowledge,tasks}.py PRESENT trong package (source giữ để restore) nhưng
   CODEBACKUP_WORKTREE_PLAINTEXT = 0 ; .git-in-stage = 0
B) nightly backup-to-gdrive (/opt/incomex/scripts/* + compose): cp -r + find compose →
   NIGHTLY_PACKAGE_PLAINTEXT = 0  (quét toàn bộ scripts + compose)
⇒ FUTURE_BACKUP_INPUT_CLEAN. KHÔNG kết luận artifact Drive hiện có đã sạch; historical Drive vẫn contaminated.

16. CURRENT DRIVE / GITHUB / HISTORICAL EXPOSURE

DRIVE  : FUTURE_BACKUP_INPUT_CLEAN (sim=0). Artifact Drive hiện có (56/repo + nightly) VẪN contaminated. Không chạy production backup (retention=REMOTE_KEEP đúng ngưỡng ⇒ 1 run sẽ xoá artifact cũ). Historical Drive = contaminated.
GITHUB : GITHUB_OUTBOUND_SOURCE_INPUT = CLEAN (agent-data-repo HEAD 7f13207f, source sạch)
         GITHUB_REMOTE_REFRESH        = PENDING_SCHEDULED_RUN (đẩy tự nhiên 06:00 CEST; C1 KHÔNG push/không trigger)
         GITHUB_HISTORY_EXPOSURE      = ACTIVE (vps-daily-* + main mang value; force-push mới KHÔNG xoá history)
         ⇒ KHÔNG báo GITHUB_REMOTE_CURRENT_HEAD=REMOVED khi chưa có evidence remote sau scheduled run.
GIT_HISTORY_EXPOSURE  = ACTIVE_ROTATION_AND_SANITIZATION_REQUIRED (blob 4acebbc + packed history còn value)

17. GIT COMMITS & BUNDLES (ràng buộc C — tách 2 repo, stage đúng path, giữ unrelated)

/opt/incomex                 74459bd → 2b086472b15b50fa088340dd00d42dca89aa36a0  (4 file: 2 .py + 2 .sh)
/opt/incomex/docker/agent-data-repo  0ffd6778 → 7f13207f85949701a85321027d9b3b8c99e9d509  (2 .py)
git add = ĐÚNG path (không -A/không .) · diff --cached --check CLEAN · staged value-scan = 0 · redacted diff (value masked, pattern qua file/stdin)
Unrelated: opt dirty 108→104 (chỉ 4 file của tôi chuyển modified→committed) ; adr 2→0 ; 15 tracked-modified unrelated = UNCHANGED (giữ nguyên 103+ dirty)
POST bundles verify PASS (§3). Bundle chứa deleted-secret line ⇒ root-only /root, NGOÀI Drive/GitHub/KB (D4). KHÔNG push.

18. RUNTIME ZERO-MUTATION PROOF (§17)

CONTAINER_MUTATION = 0 : 11 container, ID + StartedAt + RestartCount PRE == POST (byte-identical diff).
Thao tác duy nhất chạm container = docker cp + docker exec (đúng hành vi wrapper thường ngày, đọc/login, KHÔNG restart/recreate).
Không DB WRITE · không Secret Manager mutation · không restart Directus/Agent Data/PG/Nuxt/Qdrant/KB/MCP.

19. VERDICTS (§18)

CURRENT_DIRECTUS_ADMIN_HARDCODE     = REMOVED (6 target)
RECONCILE_CREDENTIAL_INJECTION      = PASS_PROTECTED_LOCAL_FILE
DRIVE_CURRENT_WORKTREE_PROPAGATION  = STOPPED (future input clean; artifact cũ còn contaminated)
GITHUB_OUTBOUND_SOURCE_INPUT        = CLEAN
GITHUB_REMOTE_REFRESH               = PENDING_SCHEDULED_RUN
GITHUB_HISTORY_EXPOSURE             = ACTIVE
GIT_HISTORY_EXPOSURE                = ACTIVE_ROTATION_AND_SANITIZATION_REQUIRED
GITHUB_HISTORY_EXPOSURE (mech)      = ACTIVE_ROTATION_AND_SANITIZATION_REQUIRED
DRIVE_HISTORICAL_EXPOSURE           = ACTIVE_ROTATION_OR_RETENTION_DECISION_REQUIRED
GITHUB_OUTBOUND_CONTROL_PLANE       = IDENTIFIED
VPS_SSOT_GIT_SAFETY                 = PASS

20. RESIDUAL (Owner-labeled — KHÔNG đụng trong C1)

LOCAL_DORMANT_PLAINTEXT_RESIDUAL = ACTIVE:
  3 worktree /root/agent-runs/worktrees/{hermes-qwen,kilo-deepseek,codex-gemini}/scripts/reconcile-{knowledge,tasks}.py (6 file, branch agent/* của repo /opt/incomex) — OFFSITE_PROPAGATION=NO (không nằm trong backup nào)
  .env.local (consumer chưa rõ — survey open item) ; 7× docker/.env.bak*/.env.mysql-backup* (→ Wave C4)
  docker/.env (nguồn injection HỢP PHÁP, §5 cấm sửa, không backup post-A1)
ROTATION_WILL_INVALIDATE = YES · SANITIZATION_WAVE_REQUIRED = YES

21. ROLLBACK COMMANDS

ssh contabo '/root/c1-checkpoint-20260717T203954Z/rollback/ROLLBACK.sh'   # phục hồi 6 file byte-exact + xoá protected file (cặp nguyên tử — D1)
# nếu cần revert commit:
cd /opt/incomex && git revert 2b086472                     # (hoặc git checkout 74459bd -- scripts/reconcile-*.{py,sh})
cd /opt/incomex/docker/agent-data-repo && git revert 7f13207f

⚠️ Rollback trả CẢ script LẪN wrapper về cũ đồng bộ (cấm trạng thái lai — D1). Sau rollback, reconcile lại chạy bằng hardcode.

22. DIRECTUS ROTATION PRIORITY

ROTATION_PRIORITY = HIGH (GẤP kế tiếp). Chỉ rotate + sanitize history (Git+GitHub) + retention-decision Drive mới đóng exposure.
Wave C2 rotate DIRECTUS_ADMIN_PASSWORD ; Wave C3 rewrite history 2 repo + xử lý 8 nhánh vps-daily-* + main trên GitHub.
Sau rotate: 6 worktree dormant + .env.bak + artifact Drive/GitHub cũ tự vô hiệu (ROTATION_WILL_INVALIDATE=YES).

23. A2 HANDOFF (chỉ chuẩn bị — KHÔNG thực hiện)

DIRECTUS_ADMIN_PASSWORD:
  CURRENT_HARDCODE=REMOVED (active exec + outbound source)
  CURRENT_PROPAGATION=STOPPED (future backup/outbound input)
  HISTORICAL_EXPOSURE=ACTIVE
  SECRET_MANAGER_ESCROW=DEFER_CURRENT_VALUE
  ROTATION_PRIORITY=HIGH
  A2_AGENT_DATA_RECOVERY_SET=EXCLUDED   (không đưa admin password vào recovery escrow)

24. EVIDENCE PATHS

CHECKPOINT /root/c1-checkpoint-20260717T203954Z  (root:root 0700)
  backup/   6 *.PRE + 3 outbound-*.sh.PRE + root-crontab.PRE + backup.sha256
  bundle/   opt/adr PRE+POST (+ bundles.sha256, bundles-POST.sha256) — cả 4 verify PASS
  evidence/ containers.PRE == containers.POST (11)
  rollback/ ROLLBACK.sh (0700)
WORKDIR /root/c1-work  (redact.py · authtest.py · patch_py.py · c1-*.sh · opt-unrelated-tracked.PRE/POST)
COMMITS  opt 2b086472 · adr 7f13207f

25. SECRET HYGIENE / PAYLOAD=REDACTED PROOF

✅ Không echo/print/log giá trị secret · không đưa vào argv (value qua tmpfs 0600 + grep -Ff / env export + docker exec -e name-only)
✅ Redacted diff: exact-value mask + long-literal mask ; pattern nhận qua file/stdin (không argv) ; KHÔNG lưu raw diff
✅ tmpfs pattern shred sau mỗi lần đo (trap EXIT) ; sim dir xoá (trap)
✅ Không đọc Secret Manager payload · không đọc /proc/*/environ · docker inspect chỉ StartedAt (không Env)
✅ Report/KB/commit/bundle-off-site: 0 password/token/key ; bundle chứa deleted-secret line = root-only, không off-site (D4)

SCOPE PROOF (bắt buộc)

DIRECTUS_PASSWORD_VALUE_CHANGE = NO
DIRECTUS_PASSWORD_ROTATION     = NO
DIRECTUS_PASSWORD_REVOKE       = NO
SECRET_MANAGER_MUTATION        = NO
CONTAINER_MUTATION             = NO
SERVICE_RESTART                = NO
DB_WRITE                       = NO
PRODUCTION_DRIVE_BACKUP_RUN    = NO
GITHUB_PUSH                    = NO
HISTORICAL_BACKUP_DELETE       = NO
GIT_HISTORY_REWRITE            = NO
GIT_PUSH                       = NO
DOCKER_CLEANUP                 = NO

DỪNG sau báo cáo. Không tự soạn/chạy A2.

Back to Knowledge Hub knowledge/current-state/reports/claude-c1-remove-directus-admin-hardcode-current-source-2026-07-17.md