KB-CF3E

S174-INV-02 — Rà tàn dư MySQL / Firestore / GCS / Artifact Registry

26 min read Revision 1
reports174investigationvpsmysqlfirestorefirebasegcsartifact-registryread-onlyremnants

S174-INV-02 — Rà tàn dư MySQL / Firestore / GCS / Artifact Registry

Date: 2026-04-08 Agent: Codex Mode: READ-ONLY Scope: toàn VPS Incomex + code/config deploy path trên VPS + note-only knowledge/docs trong workspace Checkpoint KB:

  • search_knowledge("operating rules SSOT") → OR SSOT v7.55
  • search_knowledge("hiến pháp v4.0 constitution") → Constitution KB v4.4.0
  • search_knowledge("s174 pg backup rca container retired pattern")
  • search_knowledge("operating rules v7.55 ap evidence blind out of scope")
  • search_knowledge("constitution gcp services retired postgres only architecture")

Bước 0 — Nền tảng

Files / SSOT / luật đã đọc

  • .claude/skills/incomex-rules.md
  • KB OR SSOT knowledge/dev/ssot/operating-rules.md (v7.55)
  • KB Constitution knowledge/dev/laws/constitution.md (v4.4.0)
  • KB VPS Architecture knowledge/dev/ssot/vps/vps-architecture.md (Version 2.0, update 2026-03-26)
  • KB session knowledge/current-state/sessions/s174-todo-list.md

3 câu Tuyên ngôn

  1. Vĩnh viễn? Muốn dọn sạch vĩnh viễn thì phải gỡ runtime references trong cron, compose, env, docker auth, build path, không chỉ xóa image/file lẻ.

  2. Nhầm được không? Không được. Cần một checklist retire bắt buộc kiểu grep-dependency trước khi chốt “retired”, nếu không remnant sẽ tiếp tục bị gọi âm thầm như case backup.

  3. 100% tự động? Cần một scanner định kỳ hoặc CI guard grep các token retired (mysql, firestore, gs://, pkg.dev, gcr.io) trong runtime paths và fail sớm.


Bước 1 — Thiết kế điều tra

8 lớp đã quét

  1. Cron + systemd timers + unit files
  2. Shell script + Python/Node scripts
  3. Env files + runtime env + credential refs
  4. Docker compose + images + volumes + networks + running containers
  5. App code trong nuxt-repo, agent-data-repo, dot, scripts
  6. PostgreSQL schema + sample data search
  7. OS layer: packages, binaries, ports, mounts, users/groups, gcloud/docker auth
  8. KB/docs trong workspace: note-only, không đưa vào danh sách xóa

4 nguồn bằng chứng chính

  • Cron / file hệ thống / shell outputs
  • Docker runtime / image / network / inspect
  • PostgreSQL schema + data grep
  • KB/docs/report/history note-only

Snapshot lúc kiểm tra

Command:

ssh root@38.242.240.89 'date -Is && uptime'

Output:

2026-04-08T11:30:36+02:00
11:30:36 up 55 days, 13 min, 5 users, load average: 0.49, 0.46, 0.39

Bước 2 — Kết luận nhanh

Verdict

  • Không có MySQL daemon/binary/user/port đang chạy trên host.
  • Nhưng VPS chưa sạch; vẫn còn 2 remnant clusters đang chạm runtime/deploy path:
    • Artifact Registry / pkg.dev còn nằm trong runtime compose + running nuxt container
    • Workflow/GCS backup path còn nằm trong root cron + workflow backup chain
  • Ngoài ra còn 5 cụm dormant trong env, repo deploy, migration backups, build/dev path.
  • GOOGLE_APPLICATION_CREDENTIALS hiện tại nhiều khả năng là LEGITIMATE cho GSM-only path, không nên gắn nhầm vào nhóm remnant.

Bảng tổng hợp cuối

Area 🔴 Dangerous 🟡 Dormant 🟢 Safe-delete ⚪ Legitimate
MySQL 0 1 1 0
Firestore / Firebase 0 2 0 0
GCS 1 1 0 0
Artifact / GCR 1 1 0 0
Extra workflow infra 0 0 1 0
GSM + KB note-only 0 0 0 2
Total 2 5 2 2

Bước 3 — Phân loại findings

🔴 DANGEROUS

AR-01 — Runtime nuxt vẫn phụ thuộc pkg.dev

  • Service: Artifact Registry / GCR
  • Component: /opt/incomex/docker/docker-compose.yml + running container incomex-nuxt
  • Symptom: runtime compose và container thực tế vẫn dùng image từ asia-southeast1-docker.pkg.dev/...
  • Tần suất: mỗi lần docker compose up, recreate, pull, cold restore
  • Ảnh hưởng: redeploy/cold-start tương lai vẫn phụ thuộc registry đã tuyên bố retired
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/docker-compose.yml | sed -n "124,126p"'

Output:

124  nuxt:
125    image: ${NUXT_SSR_IMAGE:-asia-southeast1-docker.pkg.dev/github-chatgpt-ggcloud/web-test/nuxt-ssr:latest}
126    container_name: incomex-nuxt

Command:

ssh root@38.242.240.89 'docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"'

Output excerpt:

incomex-nuxt  asia-southeast1-docker.pkg.dev/github-chatgpt-ggcloud/web-test/nuxt-ssr:latest  Up 5 days (healthy)

Command:

ssh root@38.242.240.89 'grep -n -E "pkg\.dev" /root/.docker/config.json'

Output:

3:    "asia-southeast1-docker.pkg.dev": {

Reasoning:

  • Đây không còn là “chỉ có trong docs”; nó nằm trong compose runtime và container đang chạy.
  • Nếu host/image cache bị xóa hoặc cần redeploy sạch, dependency pkg.dev sẽ sống lại ngay.

GCS-01 — Root cron vẫn giữ workflow/GCS backup chain sau retire

  • Service: GCS + workflow legacy path
  • Component: root crontab, /opt/workflow/.env, /opt/workflow/postgres/backup.sh, /opt/workflow/docker-compose.postgres.yml
  • Symptom: cron vẫn chạy workflow backup path cũ; script vẫn giữ GCS_BUCKET_BACKUP + gcloud storage cp; workflow compose cũ vẫn hardcode workflow-postgres
  • Tần suất: hàng ngày 02:00
  • Ảnh hưởng: drift sau retire tiếp tục tồn tại; backup chain cũ vẫn “sống” trong cron và vẫn còn GCS dependency
  • Mức chắc chắn: Cao cho remnant; Trung bình cho trạng thái sau hotfix hôm nay

Command:

ssh root@38.242.240.89 'crontab -l'

Output excerpt:

0 2 * * * /opt/workflow/postgres/backup.sh >> /opt/workflow/postgres/backup.log 2>&1
0 2 * * * /opt/incomex/scripts/pg-backup.sh >> /opt/incomex/backups/pg/backup.log 2>&1

Command:

ssh root@38.242.240.89 'nl -ba /opt/workflow/.env; nl -ba /opt/workflow/postgres/backup.sh | sed -n "63,71p"'

Output:

4  GCS_BUCKET_BACKUP=huyen1974-system-backups-shared

63  # GCS upload — best-effort (IAM may not be configured)
64  GCS_BUCKET_BACKUP="${GCS_BUCKET_BACKUP:-}"
65  if [[ -n "$GCS_BUCKET_BACKUP" ]]; then
66    GCS_PATH="gs://${GCS_BUCKET_BACKUP}/postgres/${PREFIX}_${TIMESTAMP}.sql.gz"
67    if gcloud storage cp "$BACKUP_FILE" "$GCS_PATH" >&2; then
68      echo "... GCS_OK ..."
69    else
70      echo "... WARN: GCS upload failed ..."
71    fi

Command:

ssh root@38.242.240.89 'tail -n 20 /opt/workflow/postgres/backup.log'

Output:

[2026-04-01T00:00:01Z] START backup -> /opt/workflow/postgres/backups/workflow_20260401T000001Z.sql.gz
Error response from daemon: No such container: workflow-postgres
...
[2026-04-08T00:00:02Z] START backup -> /opt/workflow/postgres/backups/workflow_20260408T000002Z.sql.gz
Error response from daemon: No such container: workflow-postgres

Command:

ssh root@38.242.240.89 'nl -ba /opt/workflow/docker-compose.postgres.yml | sed -n "1,24p"'

Output:

1   services:
2     postgres:
3       container_name: workflow-postgres
...
21  networks:
22    workflow_internal:
23      name: workflow_internal
24      internal: true

Command:

ssh root@38.242.240.89 'docker network inspect workflow_internal --format "name={{.Name}} containers={{len .Containers}}"'

Output:

name=workflow_internal containers=0

Reasoning:

  • Đây là đúng pattern user nghi ngờ: retire service nhưng dependency trong cron/env/script/compose không bị quét sạch.
  • Có dấu hiệu hotfix trong ngày 2026-04-08 (backup.sh mtime 11:28 và file backup 453B/456B mới xuất hiện), nhưng lịch cron sau fix chưa chạy qua đêm, nên chưa thể coi là sạch.

🟡 DORMANT

MYSQL-01 — MySQL backup chain vẫn còn trong env/script/archive của stack hiện tại

  • Service: MySQL
  • Component: /opt/incomex/docker/.env, /opt/incomex/scripts/mysql-backup.sh.retired, /opt/incomex/backups/mysql
  • Symptom: active env file vẫn mang MYSQL_ROOT_PASSWORD; retired backup script vẫn đọc biến đó và gọi incomex-mysql; thư mục backup MySQL vẫn giữ cả dump thành công lẫn chuỗi file 20-byte fail
  • Tần suất: không còn cron active; có thể “sống lại” nếu ai đó dùng script/path cũ
  • Ảnh hưởng: drift secret + operator confusion + future accidental reuse
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/.env | sed -n "5,9p"; nl -ba /opt/incomex/scripts/mysql-backup.sh.retired | sed -n "7,34p"'

Output:

5  # --- MySQL (RETIRED 2026-03-13 — S115) ---
6  MYSQL_ROOT_PASSWORD=...
7  DB_DATABASE=directus
8  DB_USER=directus
9  DB_PASSWORD=...

7   ENV_FILE="/opt/incomex/docker/.env"
8   BACKUP_DIR="/opt/incomex/backups/mysql"
17  MYSQL_PWD="$(grep '^MYSQL_ROOT_PASSWORD=' "$ENV_FILE" | cut -d= -f2)"
28  docker exec incomex-mysql mysqldump \

Command:

ssh root@38.242.240.89 'ls -lah /opt/incomex/backups/mysql'

Output excerpt:

directus_2026-03-11_0200.sql.gz  19M
directus_2026-03-12_0200.sql.gz  20
...
directus_2026-04-03_0200.sql.gz  20

Reasoning:

  • Không còn active crontab call tới mysql-backup.sh.
  • Nhưng biến môi trường và archive chain cũ vẫn nằm ngay trong cây deploy hiện tại.

FS-01 — Firestore migration scripts + backup JSON vẫn nằm trên VPS

  • Service: Firestore
  • Component: /opt/incomex/docker/agent-data-repo/scripts/*, /opt/incomex/backups/gcp-pre-migration/firestore/*
  • Symptom: vẫn còn script import/migrate/orphan-check cho Firestore và bộ backup JSON pre-migration
  • Tần suất: không có cron active; manual / future operator path
  • Ảnh hưởng: dễ tái sử dụng nhầm hoặc kéo nhầm mental model Firestore trở lại
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'ls -lh /opt/incomex/backups/gcp-pre-migration/firestore/*'

Output:

chat_sessions.json   2
kb_documents.json    5.9M
metadata_test.json   1.7K

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/agent-data-repo/scripts/import_firestore_to_pg.py | sed -n "1,35p"'

Output:

2  """Import Firestore backup JSON into PostgreSQL.
7  Reads from /opt/incomex/backups/gcp-pre-migration/firestore/*.json
8  Writes to PostgreSQL incomex_metadata database.
25 BACKUP_DIR = "/opt/incomex/backups/gcp-pre-migration/firestore"

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/agent-data-repo/scripts/migrate_v3.py | sed -n "1,18p"'

Output:

1  """Migrate old GitHub docs into V3 Firestore KB structure.
3  Reads from /api/docs/file (GitHub), writes to POST /documents (Firestore KB).

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/agent-data-repo/scripts/orphan_vector_check.py | sed -n "1,20p"'

Output:

3  Compares vector IDs in Qdrant against document IDs in Firestore...
17 from google.cloud import firestore

FB-01 — Firebase auth path còn trong nuxt-repo, nhưng runtime env hiện tại không bật

  • Service: Firebase / Firestore-era frontend auth
  • Component: /opt/incomex/docker/nuxt-repo/web
  • Symptom: runtimeConfig, plugin, middleware, dependency firebase vẫn còn; nhưng container incomex-nuxt không có NUXT_PUBLIC_FIREBASE_*
  • Tần suất: dormant hiện tại; có thể thức dậy khi build/deploy từ repo cũ hoặc nếu env được bơm lại
  • Ảnh hưởng: future build drift; auth path dễ gây hiểu lầm rằng Firebase vẫn là auth SSOT
  • Mức chắc chắn: Trung bình-cao

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/nuxt-repo/web/nuxt.config.ts | sed -n "117,125p"; nl -ba /opt/incomex/docker/nuxt-repo/web/plugins/firebase.client.ts | sed -n "1,45p"; nl -ba /opt/incomex/docker/nuxt-repo/web/middleware/auth.ts | sed -n "1,33p"'

Output excerpt:

117  firebase:
118    apiKey: process.env.NUXT_PUBLIC_FIREBASE_API_KEY || ''
...
1  import { initializeApp, getApps } from 'firebase/app';
2  import { getAuth } from 'firebase/auth';
...
1  import { onAuthStateChanged } from 'firebase/auth';

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/nuxt-repo/web/package.json | sed -n "45,63p"'

Output:

45  "dependencies": {
...
61    "firebase": "^12.6.0",
62    "google-auth-library": "^10.5.0",

Command:

ssh root@38.242.240.89 'docker inspect incomex-nuxt --format "{{range .Config.Env}}{{println .}}{{end}}" | grep -E "^NUXT_PUBLIC_FIREBASE_|^FIREBASE_" || true'

Output:

(no output)

GCS-02 — GCS dev/test paths vẫn còn trong repo deploy trên VPS

  • Service: GCS
  • Component: agent-data-repo scripts/terraform + historical gcp-pre-migration/gcs
  • Symptom: repo deploy vẫn còn e2e_gcs_setup.py, gcs_buckets.tf, functions_artifacts.tf, historical GCS copies
  • Tần suất: dormant; build/test/manual only
  • Ảnh hưởng: future operator có thể tiếp tục dùng GCS test buckets / old ingest assumptions
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/agent-data-repo/scripts/e2e_gcs_setup.py | sed -n "1,55p"'

Output:

3   E2E GCS Setup Script
6     python scripts/e2e_gcs_setup.py upload
10  Uses Application Default Credentials...
31  BUCKET_NAME = "huyen1974-agent-data-knowledge-test"
52  print(f"Uploading ... to gs://{BUCKET_NAME}/{BLOB_NAME} ...")

Command:

ssh root@38.242.240.89 'find /opt/incomex/docker/agent-data-repo/terraform -maxdepth 2 -type f | grep -E "gcs_buckets|functions_artifacts|artifact_registry"'

Output:

/opt/incomex/docker/agent-data-repo/terraform/artifact_registry.tf
/opt/incomex/docker/agent-data-repo/terraform/functions_artifacts.tf
/opt/incomex/docker/agent-data-repo/terraform/gcs_buckets.tf

Command:

ssh root@38.242.240.89 'find /opt/incomex/backups/gcp-pre-migration/gcs -maxdepth 3 -type f | sed -n "1,20p"'

Output excerpt:

/opt/incomex/backups/gcp-pre-migration/gcs/postgres/workflow_20260301T010001Z.sql.gz
...
/opt/incomex/backups/gcp-pre-migration/gcs/postgres/workflow_20260311T010001Z.sql.gz

AR-02 — Build/dev path trên VPS vẫn còn gcr.io / pkg.dev

  • Service: Artifact Registry / GCR
  • Component: nuxt-repo/docker-compose.local.yml, dot-local-up, web/Dockerfile, agent-data-repo/terraform/*
  • Symptom: local-dev/build path vẫn kéo gcr.io/cloud-sql-connectors/cloud-sql-proxypkg.dev images; agent-data repo vẫn giữ terraform Artifact Registry
  • Tần suất: dormant; build/local-dev/manual only
  • Ảnh hưởng: drift trong lần build/debug sau; người vận hành dễ quay lại registry cũ
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'nl -ba /opt/incomex/docker/nuxt-repo/docker-compose.local.yml | sed -n "14,24p"; nl -ba /opt/incomex/docker/nuxt-repo/docker-compose.local.yml | sed -n "34,48p"; nl -ba /opt/incomex/dot/bin/dot-local-up | sed -n "40,42p"; nl -ba /opt/incomex/docker/nuxt-repo/web/Dockerfile | sed -n "1,6p"'

Output:

14  # Cloud SQL Proxy - Secure tunnel to production database
17    image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.2
22    - github-chatgpt-ggcloud:asia-southeast1:mysql-directus-web-test

35    image: asia-southeast1-docker.pkg.dev/github-chatgpt-ggcloud/web-test/directus:latest
47      STORAGE_GCS_KEY_FILENAME: /app/config/google-credentials.json

40  echo "[2/5] Pulling latest images..."
41  docker pull gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.14.2
42  docker pull asia-southeast1-docker.pkg.dev/github-chatgpt-ggcloud/web-test/directus:latest

5   # Also pushed to Artifact Registry as backup for Cloud Run.

🟢 SAFE-DELETE

MYSQL-02 — Cached image mysql:8.0 còn trên host nhưng không có runtime nào dùng

  • Service: MySQL
  • Component: Docker image cache
  • Symptom: image còn lưu trên host; không có container, user, binary, port liên quan
  • Tần suất: không được gọi
  • Ảnh hưởng: chiếm disk + tạo false signal khi audit
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'docker image inspect mysql:8.0 --format "{{.RepoTags}}|{{.Created}}|{{.Size}}"'

Output:

[mysql:8.0]|2026-02-05T22:09:44.226691198Z|232308084

Command:

ssh root@38.242.240.89 'docker ps --format "table {{.Names}}\t{{.Image}}"'
ssh root@38.242.240.89 'ss -tlnp | grep -E ":3306" || true'
ssh root@38.242.240.89 'command -v mysql mysqldump mariadb 2>/dev/null || true'
ssh root@38.242.240.89 'id mysql 2>/dev/null || true; getent group mysql 2>/dev/null || true'

Output:

(no mysql container)
(no 3306 listener)
(no mysql/mysqldump/mariadb binary)
(no mysql user/group)

X-01 — workflow_internal là network mồ côi

  • Service: extra finding (workflow legacy infra)
  • Component: Docker network
  • Symptom: network vẫn tồn tại nhưng containers=0
  • Tần suất: không được gọi
  • Ảnh hưởng: low, nhưng là dấu vết hạ tầng cũ còn sót
  • Mức chắc chắn: Cao

Command:

ssh root@38.242.240.89 'docker network inspect workflow_internal --format "name={{.Name}} containers={{len .Containers}}"'

Output:

name=workflow_internal containers=0

⚪ LEGITIMATE

LEG-01 — GOOGLE_APPLICATION_CREDENTIALS trong agent-data hiện tại nên giữ

  • Service: GSM-only GCP path
  • Component: incomex-agent-data runtime
  • Symptom: agent-data container có GOOGLE_APPLICATION_CREDENTIALS; directus runtime không có GCS env; storage file records đều local
  • Tần suất: runtime hiện tại
  • Ảnh hưởng: cần giữ nếu service account này còn dùng cho GSM/secret retrieval
  • Mức chắc chắn: Trung bình (inference từ SSOT + runtime evidence)

Evidence:

  • KB VPS Architecture nói rõ: chỉ còn Secret Manager là GCP service hợp lệ; MySQL/Firestore/GCS/Artifact Registry đều retired.

Command:

ssh root@38.242.240.89 'docker inspect incomex-agent-data --format "{{range .Config.Env}}{{println .}}{{end}}" | grep -E "^GOOGLE_APPLICATION_CREDENTIALS" || true'

Output:

GOOGLE_APPLICATION_CREDENTIALS=/app/credentials/google-credentials.json

Command:

ssh root@38.242.240.89 'docker inspect incomex-directus --format "{{range .Config.Env}}{{println .}}{{end}}" | grep -E "^STORAGE_GCS|^GCS_|^GOOGLE_APPLICATION_CREDENTIALS" || true'

Output:

(no output)

Command:

ssh root@38.242.240.89 'docker exec postgres sh -lc "PGPASSWORD=\"$POSTGRES_PASSWORD\" psql -U directus -d directus -Atc \"SELECT storage, count(*) FROM public.directus_files GROUP BY 1 ORDER BY 1;\""'

Output:

local|7

Supporting host evidence:

ssh root@38.242.240.89 'gcloud config list --format="text(core.account,core.project)"'
account: cursor-ci-builder@github-chatgpt-ggcloud.iam.gserviceaccount.com
project: github-chatgpt-ggcloud

LEG-02 — Knowledge/docs historical references: note-only, không đề xuất xóa trong mission này

  • Service: KB / docs history
  • Component: knowledge/current-state/reports, docs/*
  • Symptom: nhiều tài liệu lịch sử vẫn nhắc MySQL / Firestore / GCS / Artifact
  • Tần suất: note-only
  • Ảnh hưởng: giữ để làm bài học lịch sử; không tính là operational remnant cần xóa trong mission này
  • Mức chắc chắn: Cao

Command:

rg -n -i 'mysql|firestore|firebase|gs://|gcr\.io|pkg\.dev|artifact registry|cloud-sql-proxy' knowledge/current-state/reports docs | sed -n '1,20p'

Output excerpt:

knowledge/current-state/reports/s173-gh-push-rca.md:87:displayName: GitHub Actions Build / Push Artifact Registry
docs/ssot/Law_of_data_and_connection.md:1:... references đến "MySQL-first"... là lịch sử.
docs/dev/blueprints/Opus_buckets_reform_plan.md:57:| Sys-1 | ... gs://github-chatgpt-ggcloud_cloudbuild ...

Bước 4 — Pattern observation

Có cùng gốc với PG backup RCA không?

Có, gần như cùng một gốc:

  • Service đã retired nhưng dependency không bị grep sạch trong cron, compose, env, docker auth, build path, repo deploy.
  • Kết quả là phần “đã retired” vẫn sống âm thầm trong các đường chạy phụ:
    • workflow-postgres sống trong backup chain cũ
    • pkg.dev sống trong runtime nuxt + docker auth
    • MYSQL_ROOT_PASSWORD sống trong env đang dùng
    • Firestore/GCS vẫn sống trong migration scripts và test/build path

Mẫu drift quan sát được

  1. Retire runtime xong nhưng không quét dependency strings toàn cây.
  2. Script/file được rename thành .retired hoặc .bak, nhưng env/compose/archive/log vẫn giữ reference.
  3. Repo clone trên VPS giữ local-dev/build path cũ, về sau có thể bị dùng lại nhầm như “source of truth”.
  4. Docker auth / cached image / orphan network làm audit bề mặt trông như service còn sống.

Bước 5 — Đề xuất cleanup theo thứ tự ưu tiên

Fix ngay hôm nay

  1. Gỡ runtime pkg.dev khỏi nuxt production compose/deploy path. Action: đổi image source của nuxt sang local build/tag hoặc source khác đã được chấp thuận trong kiến trúc hiện tại. Rủi ro nếu chưa làm: redeploy/cold restore tiếp tục phụ thuộc Artifact Registry retired. Rollback: revert compose/image reference về commit trước nếu build mới lỗi.

  2. Khóa sạch workflow backup chain cũ ra khỏi cron/runtime path. Action: dọn root crontab còn /opt/workflow/postgres/backup.sh, tách hẳn legacy workflow backup path khỏi backup production hiện tại, và bỏ GCS upload code/env nếu không còn hợp lệ. Rủi ro nếu chưa làm: drift backup tiếp tục lặp lại; đêm sau có thể lại tạo cảm giác “OK giả”. Rollback: giữ bản copy file/script cũ trong repo archive ngoài runtime path, không giữ trong cron active.

Fix trong 1–3 ngày

  1. Dọn MySQL residue trong env/script/archive của stack hiện tại. Action: loại MYSQL_ROOT_PASSWORD khỏi env đang dùng, di chuyển/xóa mysql-backup.sh.retired, backup chain và compose backup files ra khỏi cây deploy active. Rủi ro nếu chưa làm: secret drift + người vận hành có thể đọc nhầm state hiện tại. Rollback: giữ 1 artifact archive được đặt tên rõ “migration-evidence”, không giữ lẫn trong runtime tree.

  2. Dọn Firebase/Firestore path khỏi nuxt-repoagent-data-repo nếu xác nhận không còn sản phẩm nào dùng. Action: bỏ Firebase auth plugin/middleware/dependency; gom Firestore import/migration scripts và backup JSON sang khu archive lịch sử hoặc repo evidence riêng. Rủi ro nếu chưa làm: build path và mental model tiếp tục lệch kiến trúc Postgres-only + GSM-only. Rollback: tag/archive repo state trước cleanup; không giữ trong nhánh deploy mặc định.

  3. Dọn local-dev/build paths còn gcr.io / pkg.dev / Cloud SQL MySQL / GCS. Action: sửa docker-compose.local.yml, dot-local-up, web/Dockerfile, agent-data-repo/terraform theo thực tế kiến trúc mới hoặc chuyển hẳn sang archive. Rủi ro nếu chưa làm: lần debug/dev tiếp theo sẽ tái sinh hạ tầng đã retired. Rollback: giữ README migration cho local-dev cũ, không giữ config cũ ở path mặc định.

Theo dõi thêm

  1. workflow backup path đã bị sửa lúc 2026-04-08 11:28, nhưng cron sau fix chưa chạy qua đêm. Theo dõi: xác nhận run scheduled kế tiếp trước khi đóng hẳn finding này.

  2. GOOGLE_APPLICATION_CREDENTIALS trên agent-data. Theo dõi: xác nhận bằng code/runtime audit rằng credential này chỉ còn phục vụ GSM. Hiện bằng chứng nghiêng mạnh về “legitimate”, nhưng nên có xác nhận cuối trong fix mission.


KHÔNG CHẮC

  1. Tôi không kết luận rằng workflow backup chain đã sạch chỉ vì backup.sh hiện tại đã đổi workflow-postgres -> postgres. Reason: bằng chứng fail gần nhất trong cron log vẫn là 2026-04-08 00:00, còn file/script mới được sửa lúc 11:28.

  2. Tôi không gắn GOOGLE_APPLICATION_CREDENTIALS vào nhóm remnant. Reason: SSOT kiến trúc nói GSM là service Google duy nhất còn hợp lệ, directus runtime không có GCS env, và directus_files.storagelocal|7. Kết luận “GSM-only” ở đây là inference hợp lý nhưng chưa có trace code runtime 100%.


Bước 6 — Appendix

Lệnh chính đã chạy

sed -n '1,260p' .claude/skills/incomex-rules.md
search_knowledge("operating rules SSOT")
search_knowledge("hiến pháp v4.0 constitution")
search_knowledge("s174 pg backup rca container retired pattern")
search_knowledge("operating rules v7.55 ap evidence blind out of scope")
search_knowledge("constitution gcp services retired postgres only architecture")

ssh root@38.242.240.89 hostnamectl
ssh root@38.242.240.89 'date -Is && uptime'
ssh root@38.242.240.89 'crontab -l'
ssh root@38.242.240.89 'docker ps --format ...'
ssh root@38.242.240.89 'docker images --format ...'
ssh root@38.242.240.89 'docker volume ls'
ssh root@38.242.240.89 'docker network ls'
ssh root@38.242.240.89 'docker network inspect workflow_internal ...'
ssh root@38.242.240.89 'docker inspect incomex-nuxt|incomex-directus|incomex-agent-data ...'
ssh root@38.242.240.89 'dpkg -l | grep ...'
ssh root@38.242.240.89 'command -v mysql mysqldump mariadb gcloud gsutil gcsfuse'
ssh root@38.242.240.89 'ss -tlnp | grep ...'
ssh root@38.242.240.89 'gcloud config list ...'
ssh root@38.242.240.89 'grep -RniE ... /opt/incomex /opt/workflow ...'
ssh root@38.242.240.89 'nl -ba ...'
ssh root@38.242.240.89 'tail -n ... backup.log'
ssh root@38.242.240.89 'ls -lah /opt/incomex/backups ...'
ssh root@38.242.240.89 'docker exec postgres ... psql ...'
rg -n -i ... knowledge/current-state/reports docs

Logs đã đọc

  • /opt/workflow/postgres/backup.log
  • /opt/incomex/logs/backup-gdrive.log
  • /opt/incomex/logs/cdn-warm.log (chỉ để loại comment/docs hit khỏi runtime dependency)
  • /opt/incomex/backups/mysql/backup.log*

Containers / services đã kiểm

  • incomex-nuxt
  • incomex-directus
  • incomex-agent-data
  • postgres
  • incomex-nginx
  • incomex-qdrant
  • uptime-kuma

OS / infra objects đã kiểm

  • Docker images
  • Docker volumes
  • Docker networks
  • /root/.docker/config.json
  • /root/.config/gcloud/*
  • /opt/incomex/docker/credentials/google-credentials.json
  • /opt/workflow/docker-compose.postgres.yml
  • /opt/incomex/docker/docker-compose.yml

Kết luận cuối

VPS hiện chưa đạt trạng thái “Postgres-only + GSM-only sạch hoàn toàn”. Hai remnant cần ưu tiên cao nhất là:

  • runtime nuxt còn bám pkg.dev
  • workflow backup chain cũ còn bám cron + GCS + workflow compose/network

Các remnant còn lại chủ yếu là dormant trong env/repo/backups/build path. Không có dấu hiệu MySQL runtime còn chạy thật trên host.