C2B1-R0 — Owner Decision Packet (approve migration path + next phase)
C2B1-R0 — Owner Decision Packet
Read this first. R0 is read-only; nothing was changed. This packet asks you to make one path decision and approve the next phase. Everything below is measured live on 2026-07-21 (see other files).
Gói quyết định (tiếng Việt — tóm tắt)
Chỉ 2 container thực sự còn cột vào token admin: Nuxt và agent-data. Bốn job dùng
password sửa được ngay bằng cách chỉnh file (không restart). Hai scanner tưởng dùng token nhưng
thực ra không (chạy PG thẳng). dot-apr-execute hỏng sẵn. claude-mcp dùng tac-agent (không phải admin).
Cổng chặn duy nhất: ảnh Nuxt là :latest mutable và registry không với tới được từ VPS ⇒
recreate mà pull sẽ gãy, không có bản offsite. ⇒ phải làm NUXT-IMG-H1 (ghim digest local 72715a
docker save+ chứng minh recreate không-pull) TRƯỚC khi repoint Nuxt và TRƯỚC khi xoay admin.
Khuyến nghị: chọn Option B (Direct Decomposition), làm các consumer file trước, chạy NUXT-IMG-H1 song song, rồi repoint Nuxt, rồi xoay. Lý do: cả hai option đều vướng cùng cổng Nuxt nên Fast Containment không tới đích nhanh hơn, mà lại để lại 1 token rộng phải dọn sau.
Phát hiện cần lưu 🔴: SYNC_SECRET = đúng bằng token admin (byte-identical). Phải tách trước/khi xoay.
Decision required
Approve the migration path:
- OPTION B — Direct Decomposition (RECOMMENDED) — 4 least-privilege identities, sequenced file-consumers-first; ~8 operator-hours; least-privilege end-state; no lockout risk; no cleanup pass.
- OPTION A — Fast Containment — 1 broad transitional identity; ~6 operator-hours; but leaves a broad token to decompose later and reaches rotation no sooner than B (same Nuxt gate).
Recommendation basis: both paths are gated by the same Nuxt-image blocker, so A's speed premise does not pay off; B costs ~2h more and ends at the correct least-privilege posture. See
06-time-risk-comparison.md.
What is (and is not) blocking
| Item | Status |
|---|---|
| Consumer map complete & measured | ✅ done (01, 02) |
| Recreate readiness assessed | ✅ done (03) |
| agent-data recreate | ✅ ready (image pinned+local; docker save first) |
| File/password consumers repoint | ✅ ready now (no restart, no gate) |
| Nuxt recreate | 🔴 NOT ready — NUXT_IMAGE_RECREATE_READY=NO → needs NUXT-IMG-H1 |
| Admin rotation (C2B1-X) | ⛔ blocked until all consumers repointed (Nuxt gated) |
Phase plan (what you approve to run next)
- C2B1-S1-DESIGN — write exact permission rows for the 4 identities (+ enumerate agent-data sync collections; confirm dot-dot-coverage API-vs-PG). Read-only design; no provisioning.
- C2B1-S1-APPLY — provision the 4 identities + tokens (parallel to admin; no repoint yet).
- C2B1-S2 — positive + negative capability verification (each identity denied outside its envelope).
- NUXT-IMG-H1 — pin Nuxt to local digest
72715a...,docker savebackup, prove a no-pull recreate on a throwaway clone. This is the critical-path item; start it early / in parallel. - C2B1-S3 — repoint consumers (file consumers first; agent-data; then Nuxt after H1).
- C2B1-R1 — prove machine-dependency-on-admin = 0.
- C2B1-X — rotate admin password + static token (decouple
SYNC_SECRETin the same change). - C2B1-V — post-rotation encrypted backup + restore proof.
Decisions embedded for your confirmation
- Convert password consumers to tokens? (recommended — kills the 25-fail lockout vector). Y/N.
SYNC_SECRETdecoupling: it is currently byte-identical to the admin token. Confirm we generate a fresh independentSYNC_SECRETas part of X. Y/N.- Vestigial-arm hygiene: remove the dead
DIRECTUS_ADMIN_TOKENexport from orphan/misclass scanners and the dead password export from dot-dot-health. Y/N. - dot-apr-execute: out of C2B1 scope (already broken). Fix/retire as a separate ticket. Acknowledge.
Known residual (either path)
Historical admin-credential exposure (git history, old PG dumps, Drive) stays live until C2B1-X. Future backups are encrypted and restore-proven. Shorten the window by prioritizing NUXT-IMG-H1.