KB-7F3E

Hardcode Audit — Codex Agent (Nuxt + config + docker + agent-data + .claude)

40 min read Revision 1
reportscodexhistorical-sync

Hardcode Audit — Codex Agent (Nuxt + config + docker + agent-data + .claude)

Tóm tắt

  • Tổng files rà soát: 474
  • Tổng hardcode ghi nhận trong báo cáo: 315 file:line occurrences sau khi loại generated/docs/assets/package-lock và khử trùng lặp giữa các pass
  • 🔴 CRITICAL: 177
  • 🟡 WARNING: 130
  • 🟢 ACCEPTABLE: 8
  • agent-data/: 0 files trong workspace này

3 câu Tuyên ngôn

  • Vĩnh viễn: hiện có nhiều chỗ buộc thay đổi domain/collection/ID/asset thì phải sửa code hoặc workflow YAML, trái trực tiếp với §0-AU và nguyên tắc metadata > code.
  • Nhầm được không: có nhiều fallback trỏ thẳng sang test/prod URL, credential mẫu, UUID/policy/file/folder cố định; nếu sai môi trường thì hệ thống vẫn chạy nhưng chạy nhầm.
  • 100% tự động: các UUID, collection name, page size, rate limit, smoke asset ID và workflow URL pin cứng làm hệ thống không tự co giãn theo metadata/config.

Luật đã đọc và căn cứ

Nguồn Version / trạng thái Ghi chú
.claude/skills/incomex-rules.md 36 mục / 8 bước Luật thao tác mission bắt buộc
docs/ssot/constitution.md Hiến pháp v1.11e + amendment 2026-03-13 Có ghi rõ PG 16 là hiện trạng, MySQL là lịch sử
.claude/laws/Law_of_data_and_connection.md v1.1, 24/11/2025 Nhấn mạnh SSOT, Assemble > Build, config/infra tách khỏi data
.claude/laws/constitution.md local copy v1.11e Dùng đối chiếu khi KB timeout

Evidence bắt buộc

KB / luật

search_knowledge("operating rules SSOT")
-> tool call failed: timed out awaiting tools/call after 120s

search_knowledge("hiến pháp v4.0 constitution")
-> tool call failed: timed out awaiting tools/call after 120s

search_knowledge("hardcode law §0-AU metadata > code foundation principles")
-> tool call failed: timed out awaiting tools/call after 120s

Scope thực tế

find . -maxdepth 2 -type d (...) -> 
./.claude
./.github
./web
./web/.github

test -d agent-data && find agent-data -type f | wc -l || printf '0\n'
0

Count evidence

474 unique files in scope

wc -l critical_literals.txt
30

wc -l source_runtime_urls.txt
44

grep -Ev '^(web/Dockerfile:|web/package.json:)' source_runtime_urls.txt | wc -l
41

wc -l collections_runtime.txt
106

wc -l tunable_numbers.txt
106

wc -l warning_infra_urls.txt
23

Phương pháp lọc

  • Quét đúng scope: web/, .claude/, root .github/, web/.github/, docker-compose*.yml, Dockerfile*, root *.env*/*.json/*.yaml/*.yml/*.toml.
  • Bỏ qua: node_modules, .nuxt, .output, dist, playwright-report, test-results, web/#, package-lock.json, SVG/logo assets, generated manifests.
  • Với runtime collection names: chỉ giữ các chỗ nằm trong page/component/composable/server/module logic; không đếm web/scripts/**web/config/** vào appendix runtime collection vì đó là bootstrap/schema side.
  • Với runtime URLs: giữ lại các fallback/test/prod endpoints trong source và workflow; hạ một số build/test config xuống WARNING thay vì CRITICAL.
  • Với .env.local.env.example: xem là surface config hợp lệ nên chỉ ghi nhận ACCEPTABLE.

Chi tiết

🔴 CRITICAL

# File Dòng Code Hardcode gì Tại sao critical
1 .claude/settings.local.json 21, 29, 38-48, 55, 60, 95, 110, 112, 134, 140-148, 159-164 DIRECTUS_ADMIN_EMAIL=[REDACTED], DIRECTUS_ADMIN_PASSWORD=[REDACTED], DOT_TOKEN=[REDACTED JWT], TOKEN=[REDACTED JWT], FILE_ID="...", DIRECTUS_URL="https://directus-test-..." Credential, JWT token, file UUID, test URL ghi cứng trong tool allowlist Lộ secret trực tiếp và khóa agent vào môi trường/asset cố định; đổi môi trường hay rotate secret là phải sửa file
2 web/.directus/docker-compose.yaml 12-15, 31-32, 37-39, 45-46 POSTGRES_PASSWORD=[REDACTED], KEY=[REDACTED UUID], SECRET=[REDACTED UUID], ADMIN_PASSWORD=[REDACTED] DB creds, app secret, admin defaults ghi cứng Vừa là secret vừa là environment binding; sai môi trường hoặc leak credential là hỏng toàn bộ local stack
3 web/scripts/link_policy_to_public.ts 5, 20-21 API_URL = ...directus-test..., publicRoleId = '728b...', policyId = 'bb3b...' Test Directus URL + role/policy UUID Thay policy/role/môi trường là phải sửa code; đây là logic vận hành chạm permission
4 web/scripts/e1-06_seed_legal_globals.ts, web/scripts/e1-09_final_verification.ts, web/scripts/fix_globals_schema.ts 24-25, 25-26, 27-28 DIRECTUS_ADMIN_EMAIL=[REDACTED DEFAULT], DIRECTUS_ADMIN_PASSWORD=[REDACTED DEFAULT] Admin default fallback Fallback credential trong source làm script có thể chạy nhầm hoặc lộ secret qua code review/log
5 web/scripts/setup_permissions.ts, web/scripts/probe_directus.ts, web/scripts/setup_flows.ts 16, 16, 19 `API_URL = process.env.DIRECTUS_URL "https://directus-test-..."`
6 web/scripts/e1-10_seed_branding_navigation.ts 40-44 TARGET_WEBSITE, CLEARBIT_LOGO_URL, FALLBACK_LOGO_URL, SMOKE_ASSET_ID Domain, external asset URL, smoke asset UUID Đổi brand/asset là phải sửa code; smoke asset ID là literal business dependency
7 web/layers/portal/pages/portal/projects/[id]/files.vue 3 const folderId = '3545f8b9-...' Folder UUID trong page logic Route nào cũng trỏ vào cùng folder; đổi folder là phải sửa code
8 web/components/ai/CreateDiscussionModal.vue 155 `https://vps.incomexsaigoncorp.vn/api/agent-webhook/${executor.id}` Webhook base URL production trong component logic UI gắn thẳng vào một host cụ thể; đổi domain/gateway là phải sửa frontend
9 web/nuxt.config.ts, web/modules/directus/runtime/plugins/directus.ts, web/server/utils/directusService.ts, web/server/routes/__sitemap__/urls.ts, web/server/api/**, web/scripts/e1-sync-docs-from-github.ts nhiều https://directus.incomexsaigoncorp.vn, https://vps.incomexsaigoncorp.vn/api, https://github-chatgpt-ggcloud.web.app, https://directus-test-... Runtime/service URL fallback trong source Thiếu env là source tự trỏ sang prod/test cố định; thay host bắt buộc sửa code
10 web/pages/**, web/components/**, web/composables/**, web/modules/**, web/server/utils/directusService.ts 106 occurrences / 55 files readItems('knowledge_documents'), readItems('meta_catalog'), readItems('workflow_steps'), ... Collection/table names trong runtime logic Đổi schema/collection phải sửa code khắp UI/server; vi phạm metadata > code§0-AU
11 .github/workflows/ops-smoke.yml 11 SMOKE_ASSET_ID: "eb037157-..." Smoke asset UUID pin cứng trong CI Asset đổi là CI phải sửa YAML; không tự thích ứng theo metadata

🟡 WARNING

# File Dòng Code Hardcode gì Tại sao warning
1 .github/workflows/deploy-vps.yml, deploy.yml, dieu31-vps-setup.yml, e2e-test.yml, nuxt-ci.yml, sync-check.yml nhiều https://directus.incomexsaigoncorp.vn, https://vps.incomexsaigoncorp.vn, .../api/registry/refresh-counts Prod endpoint pin cứng trong CI/CD Nên đi qua repo vars/env để chuyển môi trường dễ hơn, nhưng vẫn là cấu hình pipeline hơn là runtime business logic
2 docker-compose.local.yml 21, 44-57, 73-78 3306, 8055, 3000, localhost, health retry values Port/host local dev và health thresholds Hợp lý cho dev nhưng vẫn là infra constant đổi tay khi topology đổi
3 web/Dockerfile 32-33 ARG NUXT_PUBLIC_SITE_URL=https://ai.incomexsaigoncorp.vn, ARG NUXT_PUBLIC_DIRECTUS_URL=... Build-time prod URL default Không phải runtime business logic nhưng build output vẫn phụ thuộc host mặc định
4 web/package.json 14 "test:e2e:prod": "BASE_URL=https://vps..." Prod test target pin cứng Smoke/E2E prod command nên lấy từ env/vars để không phải sửa package script
5 web/firebase.json 12, 17 redirect destination: "https://vps.incomexsaigoncorp.vn/..." Redirect domain pin cứng Deploy target/domain thay đổi là phải sửa config file
6 web/** 106 occurrences / 60 files RATE_LIMIT = 100, CACHE_TTL = 30*1000, PAGE_SIZE = 50, timeout: 30000, limit: 1000, intervalMs = 10000 Tunable numbers ghi cứng Không phải secret, nhưng là operational/business thresholds nên nên đưa ra config/metadata

🟢 ACCEPTABLE

# File Dòng Code Hardcode gì Tại sao acceptable
1 .env.local 11, 31, 44, 47, 48 DB_PORT=5432, AGENT_DATA_URL=http://host.docker.internal:8000, http://localhost:8055, http://localhost:3000 Local env config Đây chính là bề mặt config; user yêu cầu .env được xem là OK
2 docker-compose.override.yml 6-7 DIRECTUS_ADMIN_EMAIL: "", DIRECTUS_ADMIN_PASSWORD: "" Blank placeholders Không chứa secret; là local override placeholder
3 web/.env.example 6 NUXT_PUBLIC_SITE_URL="http://localhost:3000" Example config value File mẫu cấu hình, không phải runtime source logic

Tuân thủ Bước 0 → 6

Bước Trạng thái Evidence
0. Nền tảng PASS Đã đọc skill + hiến pháp + luật data flow; KB timeout đã được ghi rõ
1. Nhận việc PASS Scope khóa ở audit-only; không sửa, không commit
2. Thiết kế trước khi làm PASS Đặt rule phân loại CRITICAL/WARNING/ACCEPTABLE, tách runtime logic khỏi config/example
3. Thực thi PASS Chỉ dùng find, rg, sed, nl, wc, mkdir -p; không có edit source ngoài file report này
4. Mũ 1 / triển khai N/A Mission chỉ audit, không code, không PR, không deploy
5. Verify production N/A Mission không thay đổi hệ thống; verify production theo §29 không áp dụng
6. Report PASS File này tại knowledge/current-state/reports/hardcode-audit-codex-agent.md

Ghi chú phân loại

  • workflow secret refs kiểu ${{ secrets.X }} không bị tính là hardcoded value, nên bị loại khỏi finding.
  • HTTP status codes (404, 500, 503), base image versions (node:20, node:22), SVG/XML URLs, generated manifests, docs/openapi assets không được đưa vào bảng finding chính.
  • Runtime collection names bị giữ ở mức CRITICAL đúng theo yêu cầu mission: đổi business/schema mà phải sửa code là thiết kế tồi.

Appendix A — Critical Literals / UUIDs / Secrets (30, values redacted where sensitive)

web/.directus/docker-compose.yaml:45:      ADMIN_EMAIL: [REDACTED EMAIL]
web/.directus/docker-compose.yaml:46:      ADMIN_PASSWORD: [REDACTED PASSWORD]
.claude/settings.local.json:21:      ADMIN_PAYLOAD includes [REDACTED EMAIL] + [REDACTED PASSWORD]
.claude/settings.local.json:29:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:38:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:39:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:40:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:41:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:45:      DIRECTUS_URL="https://directus-test-812872501910.asia-southeast1.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:46:      DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:48:      DIRECTUS_URL="https://directus-test-pfne2mqwja-as.a.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:55:      DIRECTUS_URL="https://directus-test-pfne2mqwja-as.a.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:60:      DIRECTUS_URL="https://directus-test-pfne2mqwja-as.a.run.app" + DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:95:      node login snippet includes hostname directus-test-pfne2mqwja-as.a.run.app + [REDACTED EMAIL] + [REDACTED PASSWORD]
.claude/settings.local.json:140:      DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:142:      DIRECTUS_ADMIN_EMAIL=[REDACTED] + DIRECTUS_ADMIN_PASSWORD=[REDACTED]
.claude/settings.local.json:145:      auth_with_retry("https://directus-test-pfne2mqwja-as.a.run.app", [REDACTED EMAIL], [REDACTED PASSWORD])
.claude/settings.local.json:146:      printf payload includes [REDACTED EMAIL] + [REDACTED PASSWORD]
.claude/settings.local.json:147:      printf payload includes [REDACTED EMAIL] + [REDACTED PASSWORD]
.claude/settings.local.json:148:      bash payload includes [REDACTED EMAIL] + [REDACTED PASSWORD]
.claude/settings.local.json:161:      FILE_ID="b18f3792-bd31-43e5-8a7d-b25d76f41dd9"
.github/workflows/ops-smoke.yml:11:  SMOKE_ASSET_ID: "eb037157-91f7-462a-97fe-e17642b6d960"
web/scripts/e1-06_seed_legal_globals.ts:24: DIRECTUS_ADMIN_EMAIL default fallback = [REDACTED EMAIL]
web/scripts/fix_globals_schema.ts:27: DIRECTUS_ADMIN_EMAIL default fallback = [REDACTED EMAIL]
web/scripts/probe_directus.ts:8: usage docs still demonstrate DIRECTUS_ADMIN_EMAIL=[REDACTED EMAIL] + DIRECTUS_ADMIN_PASSWORD=[REDACTED VALUE]
web/scripts/e1-10_seed_branding_navigation.ts:43: const SMOKE_ASSET_ID = 'b18f3792-bd31-43e5-8a7d-b25d76f41dd9';
web/scripts/e1-09_final_verification.ts:25: DIRECTUS_ADMIN_EMAIL default fallback = [REDACTED EMAIL]
web/scripts/link_policy_to_public.ts:20:	const publicRoleId = '728b6b9b-a902-47d1-85fa-e7188ed2b78b';
web/scripts/link_policy_to_public.ts:21:	const policyId = 'bb3bb45f-e962-4ad9-b6c6-747f4e616f8c';
web/layers/portal/pages/portal/projects/[id]/files.vue:3:const folderId = '3545f8b9-d7a4-449c-86e1-5353bd69101a';

Appendix B — Raw Critical Runtime URLs (44 raw, 41 counted critical; web/Dockerfile:32-33 + web/package.json:14 were downgraded to WARNING)

web/server/routes/__sitemap__/urls.ts:15:		'https://directus.incomexsaigoncorp.vn';
web/server/api/directus/[...path].ts:77:    'https://directus.incomexsaigoncorp.vn'
web/Dockerfile:32:ARG NUXT_PUBLIC_SITE_URL=https://ai.incomexsaigoncorp.vn
web/Dockerfile:33:ARG NUXT_PUBLIC_DIRECTUS_URL=https://directus.incomexsaigoncorp.vn
web/scripts/setup_permissions.ts:16:const API_URL = process.env.DIRECTUS_URL || "https://directus-test-812872501910.asia-southeast1.run.app";
web/server/api/registry/species-summary.get.ts:11:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/pivot-query.get.ts:17:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/counts.get.ts:11:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/species-matrix.get.ts:29:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/raw-counts.get.ts:11:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/unmanaged.get.ts:26:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/docs/context.get.ts:22:		'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/system-issues.get.ts:23:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/matrix.get.ts:53:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/scripts/link_policy_to_public.ts:5:const API_URL = process.env.DIRECTUS_URL || "https://directus-test-812872501910.asia-southeast1.run.app";
web/server/api/registry/system-issues-detail.get.ts:23:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/modules/directus/index.ts:30:				nuxtBaseUrl: 'http://localhost:3000',
web/server/api/registry/system-issues-groups.get.ts:30:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/scripts/e1-sync-docs-from-github.ts:21:const DIRECTUS_URL = process.env.NUXT_PUBLIC_DIRECTUS_URL || 'https://directus.incomexsaigoncorp.vn';
web/scripts/e1-sync-docs-from-github.ts:22:const AGENT_DATA_URL = process.env.AGENT_DATA_URL || 'https://vps.incomexsaigoncorp.vn/api';
web/server/api/registry/health.get.ts:30:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/modules/directus/runtime/plugins/directus.ts:18:		'https://directus.incomexsaigoncorp.vn';
web/modules/directus/runtime/plugins/directus.ts:21:	// window.location.origin provides the current domain (e.g., https://vps.incomexsaigoncorp.vn)
web/server/api/registry/composition.get.ts:28:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/system-issues-subgroups.get.ts:31:	const baseUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/registry/refresh-counts.post.ts:34:	const directusUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/scripts/probe_directus.ts:16:const API_URL = process.env.DIRECTUS_URL || "https://directus-test-812872501910.asia-southeast1.run.app";
web/server/api/discovery/relations.get.ts:52:	const directusUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/scripts/setup_flows.ts:19:const API_URL = process.env.DIRECTUS_URL || "https://directus-test-812872501910.asia-southeast1.run.app";
web/server/api/transitive/[code].get.ts:22:	const directusUrl = config.directusInternalUrl || config.public?.directusUrl || 'https://directus.incomexsaigoncorp.vn';
web/server/api/health.get.ts:49:    'https://directus.incomexsaigoncorp.vn';
web/nuxt.config.ts:89:			'https://directus.incomexsaigoncorp.vn',
web/nuxt.config.ts:99:			siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://github-chatgpt-ggcloud.web.app',
web/nuxt.config.ts:103:					process.env.NUXT_PUBLIC_DIRECTUS_URL || process.env.DIRECTUS_URL || 'https://directus.incomexsaigoncorp.vn',
web/nuxt.config.ts:106:						process.env.NUXT_PUBLIC_DIRECTUS_URL || process.env.DIRECTUS_URL || 'https://directus.incomexsaigoncorp.vn',
web/nuxt.config.ts:107:					nuxtBaseUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://github-chatgpt-ggcloud.web.app',
web/nuxt.config.ts:112:				process.env.NUXT_PUBLIC_DIRECTUS_URL || process.env.DIRECTUS_URL || 'https://directus.incomexsaigoncorp.vn',
web/nuxt.config.ts:141:				'https://directus.incomexsaigoncorp.vn',
web/nuxt.config.ts:142:			nuxtBaseUrl: process.env.NUXT_PUBLIC_SITE_URL || 'http://localhost:3000',
web/nuxt.config.ts:160:		url: process.env.NUXT_PUBLIC_SITE_URL || 'https://vps.incomexsaigoncorp.vn',
web/nuxt.config.ts:178:			baseURL: `${process.env.NUXT_PUBLIC_DIRECTUS_URL || process.env.DIRECTUS_URL || 'https://directus.incomexsaigoncorp.vn'}/assets/`,
web/package.json:14:		"test:e2e:prod": "BASE_URL=https://vps.incomexsaigoncorp.vn playwright test",
web/server/utils/directusService.ts:115:		'https://directus.incomexsaigoncorp.vn'
web/components/ai/CreateDiscussionModal.vue:155:        executor_ai_webhook: executor?.id ? `https://vps.incomexsaigoncorp.vn/api/agent-webhook/${executor.id}` : null

Appendix C — Raw Critical Runtime Collection Names (106)

web/pages/[...permalink].vue:30:			readItems('pages', {
web/pages/posts/categories/[category].vue:10:			readItems('categories', {
web/pages/posts/categories/[category].vue:31:			readItems('posts', {
web/pages/knowledge/modules/[id].vue:39:			readItems('workflows', {
web/pages/posts/[slug].vue:17:			readItems('posts', {
web/pages/posts/index.vue:10:			readItems('posts', {
web/pages/posts/index.vue:23:			readSingleton('pages_blog', {
web/pages/index.vue:19:				readItems('pages', {
web/pages/index.vue:79:					readItems('pages', {
web/pages/projects.vue:11:			readItems('posts', {
web/pages/projects.vue:19:			readSingleton('pages_projects', {
web/pages/admin/users.vue:70:  return $directus.request($directus.readItems('directus_users', {
web/pages/admin/knowledge-tree.vue:11:    return $directus.request($directus.readItems('knowledge_documents', {
web/pages/knowledge/laws/index.vue:21:			readItems('governance_docs' as any, {
web/pages/knowledge/[...slug].vue:61:		readItems('knowledge_documents', {
web/pages/knowledge/[...slug].vue:206:				readItems('knowledge_documents', {
web/pages/knowledge/[...slug].vue:234:			readItems('knowledge_documents', {
web/pages/knowledge/registries/changelog/index.vue:43:					readItems('registry_changelog' as any, {
web/pages/knowledge/registries/changelog/index.vue:50:					readItems('meta_catalog' as any, {
web/pages/knowledge/registries/[entityType]/[id].vue:17:			readItems('meta_catalog', {
web/pages/knowledge/registries/[entityType]/[id].vue:36:			readItems('meta_catalog', {
web/pages/knowledge/registries/[entityType]/[id].vue:91:					readItems('entity_labels' as any, {
web/pages/knowledge/registries/[entityType]/[id].vue:98:					readItems('taxonomy_facets' as any, {
web/pages/knowledge/registries/[entityType]/[id].vue:109:				readItems('taxonomy' as any, {
web/pages/knowledge/registries/[entityType]/[id].vue:157:				readItems('entity_labels' as any, {
web/pages/knowledge/workflows/[id].vue:86:			readItems('workflows', {
web/pages/knowledge/workflows/[id].vue:134:			readItems('workflow_steps', {
web/pages/knowledge/workflows/[id].vue:199:			readItems('workflow_change_requests', {
web/pages/knowledge/registries/[entityType]/index.vue:48:	collection: 'tbl_registry_collections',
web/pages/knowledge/registries/[entityType]/index.vue:72:				readItems('meta_catalog' as any, {
web/pages/knowledge/registries/[entityType]/index.vue:133:			readItems('meta_catalog', {
web/pages/knowledge/registries/[entityType]/index.vue:162:				readItems('system_issues' as any, {
web/modules/directus/index.ts:174:				const redirects = await directus.request(readItems('redirects'));
web/modules/directus/index.ts:208:				const globals = await directus.request<Omit<Globals, 'id' | 'url'>>(readSingleton('globals'));
web/composables/useAgentViews.ts:144:			readItems('agent_views', {
web/composables/useAgentViews.ts:166:			readItems('agent_views', {
web/composables/useStepCheckpoints.ts:24:				readItems('task_checkpoints', {
web/composables/useKnowledgeHistory.ts:15:				readItems('knowledge_documents', {
web/composables/useKnowledge.ts:124:			readItems('knowledge_documents', {
web/composables/useKnowledge.ts:210:			readItems('knowledge_documents', {
web/pages/knowledge/registries/index.vue:110:				readItems('meta_catalog' as any, {
web/pages/knowledge/registries/index.vue:345:					readItems('registry_changelog' as any, {
web/pages/knowledge/registries/index.vue:352:					readItems('meta_catalog' as any, {
web/pages/knowledge/registries/index.vue:461:				readItems('dot_tools' as any, { fields: ['id'], limit: -1 }),
web/pages/knowledge/registries/index.vue:478:					readItems('entity_species' as any, {
web/pages/knowledge/registries/index.vue:484:					readItems('birth_registry' as any, {
web/composables/useContentRequests.ts:111:		readItems('content_requests', params),
web/composables/useContentRequests.ts:230:			collection: 'content_requests',
web/pages/knowledge/registries/taxonomy/[facetCode]/[level].vue:20:				readItems('taxonomy_facets' as any, {
web/pages/knowledge/registries/taxonomy/[facetCode]/[level].vue:30:				readItems('taxonomy' as any, {
web/composables/useTaxonomyTree.ts:63:			readItems('knowledge_documents', {
web/pages/knowledge/registries/taxonomy/index.vue:30:				readItems('taxonomy_facets' as any, {
web/pages/knowledge/registries/taxonomy/index.vue:37:				readItems('taxonomy_matrix' as any, {
web/pages/knowledge/registries/taxonomy/index.vue:43:				readItems('taxonomy' as any, {
web/pages/knowledge/pivot/index.vue:11:		readItems('meta_catalog' as any, {
web/pages/knowledge/pivot/index.vue:31:		readItems('pivot_definitions' as any, {
web/composables/useWorkflows.ts:36:			readItems('workflow_steps', {
web/composables/useWorkflows.ts:59:			readItems('workflow_step_relations', {
web/composables/useWorkflows.ts:112:	return await useDirectus<Workflow[]>(readItems('workflows', params));
web/composables/useTasks.ts:33:	return await useDirectus<Task[]>(readItems('tasks', params));
web/composables/useTasks.ts:60:		readItems('task_comments', {
web/composables/useTasks.ts:96:		readItems('tasks', {
web/composables/useKnowledgeTree.ts:26:		readItems('knowledge_documents', {
web/composables/useKnowledgeTree.ts:44:		readItems('knowledge_documents', {
web/composables/useKnowledgeTree.ts:109:		readItems('knowledge_documents', params),
web/composables/useKnowledgeTree.ts:181:			readItems('knowledge_documents', {
web/composables/useKnowledgeTree.ts:208:			readItems('knowledge_documents', {
web/pages/knowledge/index.vue:63:		readItems('knowledge_documents', {
web/composables/useUniversalEdges.ts:46:						readItems('universal_edges' as any, {
web/composables/useUniversalEdges.ts:53:						readItems('universal_edges' as any, {
web/composables/useBlueprints.ts:90:			readItems('knowledge_documents', {
web/composables/useBlueprints.ts:150:			readItems('knowledge_documents', {
web/pages/knowledge/registries/all/index.vue:40:			readItems('meta_catalog' as any, {
web/pages/knowledge/registries/all/index.vue:81:			readItems('meta_catalog' as any, {
web/composables/useCheckpoints.ts:15:		readItems('task_checkpoints', {
web/composables/useAgentData.ts:96:			readItems('knowledge_documents', {
web/components/Categories.vue:4:		readItems('categories', {
web/components/help/CollectionsDetail.vue:14:			readItems('help_collections', {
web/layers/portal/components/InvoiceWidget.vue:10:			readItems('os_invoices', {
web/layers/portal/pages/portal/billing/invoices/index.vue:35:			readItems('os_invoices', {
web/layers/portal/pages/portal/billing/invoices/index.vue:48:			readItems('os_invoices', {
web/server/utils/directusService.ts:155:		readItems('workflow_steps', {
web/server/utils/directusService.ts:166:		readItems('workflow_step_relations', {
web/server/utils/directusService.ts:185:		readItems('block_library', {
web/server/utils/directusService.ts:208:	return await createDirectusServiceClient().request(deleteItems('workflow_steps', stepIds));
web/server/utils/directusService.ts:239:	return await createDirectusServiceClient().request(deleteItems('workflow_step_relations', relationIds));
web/layers/portal/components/TaskList.vue:14:		readItems('os_tasks', {
web/components/help/CollectionsIndex.vue:14:			readItems('help_collections', {
web/components/help/ArticleDetail.vue:16:			readItems('help_articles', {
web/layers/portal/components/MessageList.vue:16:		readItems('conversations', {
web/layers/portal/components/MessageList.vue:49:		readItems('messages', {
web/layers/portal/pages/portal/projects/index.vue:10:			readItems('os_projects', {
web/layers/portal/components/TaskWidget.vue:24:			readItems('os_tasks', {
web/layers/portal/components/TaskWidget.vue:34:			readItems('os_tasks', {
web/components/shared/ApprovalWidget.vue:21:			readItems('task_checkpoints', {
web/components/shared/DirectusTable.vue:77:			readItems('table_registry', {
web/components/shared/DirectusTable.vue:246:				readItems('table_proposals', {
web/components/registries/DiscoveryView.vue:115:				readItems('entity_dependencies' as any, {
web/components/registries/DiscoveryView.vue:198:				readItems('meta_catalog' as any, {
web/components/registries/SectionDependency.vue:31:				readItems('entity_dependencies' as any, {
web/components/navigation/TheFooter.vue:45:			readItems('forms', {
web/components/blocks/Team.vue:12:		return useDirectus(readItems('team', {}));
web/components/templates/MatrixView.vue:36:			readItems('pivot_results' as any, {
web/components/modules/workflow-module/partials/ProcessRegistryView.vue:104:			readItems('workflows', params),
web/components/modules/workflow-module/partials/ProcessRegistryView.vue:114:				readItems('workflow_steps', {
web/components/modules/workflow-module/partials/WcrIntakePanel.vue:31:			readItems('workflow_change_requests', {

Appendix D — Raw Warning Tunable Numbers (106)

web/playwright.config.ts:44:			timeout: 180 * 1000,
web/playwright.config.ts:50:	timeout: 60000,
web/playwright.config.ts:53:		timeout: 10000,
web/pages/knowledge/modules/[id].vue:42:				limit: 10,
web/lib/agentDataClient.ts:47:				signal: AbortSignal.timeout(this.config.timeout || 5000),
web/lib/agentDataClient.ts:99:				signal: AbortSignal.timeout(this.config.timeout || 5000),
web/lib/agentDataClient.ts:159:				signal: AbortSignal.timeout(this.config.timeout || 3000),
web/lib/agentDataClient.ts:192:				signal: AbortSignal.timeout(this.config.timeout || 3000),
web/composables/useKnowledgeHistory.ts:23:					limit: 50, // Reasonable limit
web/scripts/verify_agent_connection.ts:67:			signal: AbortSignal.timeout(60000), // 60 second timeout (for cold starts)
web/scripts/verify_agent_connection.ts:122:				console.error('   Reason: Request timeout (10s)');
web/pages/admin/super-session.vue:45:        limit: 50
web/pages/blueprints/index.vue:44:				pageSize: 20,
web/composables/useKnowledge.ts:100:	const { page = 1, pageSize = 20, zone, subZone, topic, language = 'vn' } = options;
web/composables/useContentRequests.ts:103:		limit: 100,
web/pages/knowledge/[...slug].vue:316:			timeout: 3000,
web/pages/knowledge/[...slug].vue:324:			timeout: 3000,
web/pages/knowledge/[...slug].vue:349:			timeout: 3000,
web/pages/knowledge/[...slug].vue:357:			timeout: 3000,
web/scripts/e1-08_setup_maintenance_flows.ts:253:				timeout: 30000,
web/composables/useTaxonomyTree.ts:69:				limit: 1000, // Reasonable limit to avoid overwhelming the system
web/server/api/registry/species-matrix.get.ts:20:const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
web/server/api/ai/search.post.ts:26:const RATE_LIMIT = 100; // requests per window
web/server/api/ai/search.post.ts:27:const RATE_WINDOW = 60 * 1000; // 1 minute in ms
web/server/api/ai/search.post.ts:261:				timeout: 60000, // 60s timeout for RAG
web/server/api/ai/search.post.ts:270:			initialDelayMs: 2000, // 2s initial delay
web/server/api/ai/search.post.ts:271:			maxDelayMs: 15000, // 15s max wait
web/server/api/ai/search.post.ts:331:				retryAfter: 30,
web/pages/knowledge/registries/changelog/index.vue:18:const PAGE_SIZE = 50;
web/pages/knowledge/registries/changelog/index.vue:46:						limit: 1000,
web/composables/useAIDiscussions.ts:414:  const startPolling = (intervalMs = 10000) => {
web/pages/knowledge/workflows/[id].vue:206:				limit: 50,
web/server/api/registry/unmanaged.get.ts:17:const CACHE_TTL = 5 * 60 * 1000;
web/composables/useWorkflows.ts:105:		limit: 50,
web/pages/knowledge/registries/[entityType]/index.vue:166:					limit: 20,
web/server/api/ai/info.get.ts:24:const CACHE_TTL = 30 * 1000; // 30 seconds
web/server/api/ai/info.get.ts:28:const RATE_LIMIT = 200; // requests per window
web/server/api/ai/info.get.ts:29:const RATE_WINDOW = 60 * 1000; // 1 minute
web/server/api/ai/info.get.ts:115:					timeout: 30000,
web/server/api/ai/info.get.ts:120:				initialDelayMs: 1000,
web/server/api/ai/info.get.ts:121:				maxDelayMs: 5000,
web/server/api/registry/system-issues.get.ts:14:const CACHE_TTL = 2 * 60 * 1000;
web/scripts/e1-01_rbac_content_requests.ts:61:const DEFAULT_TIMEOUT_MS = 30000;
web/composables/useTasks.ts:26:		limit: 100,
web/composables/useTasks.ts:63:			limit: 200,
web/server/api/knowledge/list.get.ts:40:				timeout: 30000,
web/server/api/knowledge/list.get.ts:47:			initialDelayMs: 2000,
web/server/api/knowledge/list.get.ts:48:			maxDelayMs: 10000,
web/server/api/registry/matrix.get.ts:37:const CACHE_TTL = 5 * 60 * 1000;
web/server/api/registry/matrix.get.ts:42:		timeout: 15000,
web/composables/useCheckpoints.ts:19:			limit: 100,
web/server/api/registry/system-issues-detail.get.ts:2: * GET /api/registry/system-issues-detail?sub_class=orphan_dep_target&page=1&limit=50
web/server/api/registry/system-issues-detail.get.ts:12:const CACHE_TTL = 2 * 60 * 1000;
web/server/api/registry/system-issues-detail.get.ts:18:	const limit = Math.min(100, Math.max(1, Number(query.limit) || 50));
web/server/api/registry/system-issues-detail.get.ts:42:					'limit': 800,
web/composables/useKnowledgeTree.ts:30:			limit: 100,
web/composables/useKnowledgeTree.ts:48:			limit: 100,
web/composables/useKnowledgeTree.ts:101:		limit: 500, // Increased for full tree
web/pages/knowledge/registries/index.vue:348:						limit: 10,
web/server/api/knowledge/[...slug].get.ts:28:			timeout: 30000,
web/server/api/knowledge/[...slug].get.ts:90:			initialDelayMs: 2000,
web/server/api/knowledge/[...slug].get.ts:91:			maxDelayMs: 10000,
web/server/api/registry/system-issues-groups.get.ts:11:const CACHE_TTL = 2 * 60 * 1000;
web/composables/useAgentData.ts:41:		timeout: 5000,
web/composables/useAgentData.ts:68:	const { zone, subZone, topic, language = 'vn', limit = 20 } = options;
web/server/api/registry/health.get.ts:21:const CACHE_TTL = 2 * 60 * 1000;
web/pages/knowledge/pivot/index.vue:15:			limit: 10,
web/pages/knowledge/pivot/index.vue:35:			limit: 20,
web/server/api/registry/composition.get.ts:19:const CACHE_TTL = 5 * 60 * 1000;
web/composables/useUniversalEdges.ts:49:							limit: 200,
web/composables/useUniversalEdges.ts:56:							limit: 200,
web/composables/useBlueprints.ts:78:	const { page = 1, pageSize = 20, language = 'vn' } = options;
web/scripts/e1-07_setup_cache_warmer.ts:233:				timeout: 30000,
web/composables/useDirectusTable.ts:34:	const pageSize = options.pageSize || 25;
web/server/api/registry/refresh-counts.post.ts:58:		timeout: 15000,
web/server/api/registry/refresh-counts.post.ts:83:				timeout: 10000,
web/server/api/registry/refresh-counts.post.ts:135:				timeout: 10000,
web/layers/portal/components/FileCard.vue:52:						timeout: 3000,
web/server/api/agent/health.get.ts:42:			timeout: 60000,
web/server/api/workflows/[id]/steps/reorder.post.ts:37:	const SPACING = 10;
web/scripts/demo_agent_integration.ts:34:			signal: AbortSignal.timeout(60000),
web/scripts/demo_agent_integration.ts:52:				signal: AbortSignal.timeout(5000),
web/server/utils/retryWithBackoff.ts:19:	initialDelayMs: 2000, // 2 seconds - good for cold start
web/server/utils/retryWithBackoff.ts:20:	maxDelayMs: 15000, // 15 seconds max
web/server/utils/retryWithBackoff.ts:136:			signal: AbortSignal.timeout(10000),
web/server/api/transitive/[code].get.ts:47:					'limit': 50,
web/server/api/transitive/[code].get.ts:49:				timeout: 5000,
web/server/api/health.get.ts:54:      timeout: 5000,
web/server/api/health.get.ts:74:      timeout: 5000,
web/server/api/discovery/relations.get.ts:17:const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
web/server/api/discovery/relations.get.ts:62:			timeout: 10000,
web/scripts/debug_agent_connection.py:56:            response = requests.get(url, headers=headers, timeout=10)
web/server/utils/agentDataAuth.ts:37:// 			{ encoding: 'utf-8', timeout: 10000 },
web/scripts/setup_flows.ts:291:					timeout: 30000
web/scripts/setup_flows.ts:387:					timeout: 60000
web/components/shared/DirectusTable.vue:54:		pageSize: 25,
web/components/shared/DirectusTable.vue:253:					limit: 50,
web/components/registries/DiscoveryView.vue:88:						limit: 20,
web/components/registries/DiscoveryView.vue:120:					limit: 100,
web/components/registries/DiscoveryView.vue:246:					limit: 10,
web/components/registries/SectionDependency.vue:34:					limit: 100,
web/scripts/e1-01_rbac_fix_v2.ts:81:const DEFAULT_TIMEOUT_MS = 30000;
web/components/registries/SectionRelation.vue:41:				limit: 100,
web/components/ai/ActivityLog.vue:27:  limit: 20,
web/components/modules/workflow-module/partials/ProcessRegistryView.vue:15:		pageSize: 25,
web/components/modules/workflow-module/partials/WcrIntakePanel.vue:44:				limit: 100,

Appendix E — Raw Warning Infra URLs / CI / Docker Config (23) + prod test script (1)

.github/workflows/deploy-vps.yml:290:              if curl -sf --resolve vps.incomexsaigoncorp.vn:443:127.0.0.1 --connect-timeout 10 --max-time 20 -o /dev/null https://vps.incomexsaigoncorp.vn/knowledge 2>/dev/null; then
.github/workflows/deploy-vps.yml:320:              https://vps.incomexsaigoncorp.vn/api/registry/refresh-counts \
.github/workflows/deploy-vps.yml:504:              if curl -sf --resolve vps.incomexsaigoncorp.vn:443:127.0.0.1 --connect-timeout 10 --max-time 20 -o /dev/null https://vps.incomexsaigoncorp.vn/knowledge 2>/dev/null; then
.github/workflows/deploy-vps.yml:532:              https://vps.incomexsaigoncorp.vn/api/registry/refresh-counts \
.github/workflows/deploy-vps.yml:72:          NUXT_PUBLIC_SITE_URL: "https://vps.incomexsaigoncorp.vn"
.github/workflows/deploy-vps.yml:73:          NUXT_PUBLIC_DIRECTUS_URL: "https://directus.incomexsaigoncorp.vn"
.github/workflows/deploy.yml:117:          NUXT_PUBLIC_DIRECTUS_URL: "https://directus.incomexsaigoncorp.vn"
.github/workflows/dieu31-vps-setup.yml:35:            export DIRECTUS_URL=https://directus.incomexsaigoncorp.vn
.github/workflows/dieu31-vps-setup.yml:36:            export SITE_URL=https://vps.incomexsaigoncorp.vn
.github/workflows/e2e-test.yml:41:          NUXT_PUBLIC_DIRECTUS_URL: https://directus.incomexsaigoncorp.vn
.github/workflows/nuxt-ci.yml:41:          NUXT_PUBLIC_DIRECTUS_URL: "https://directus.incomexsaigoncorp.vn"
.github/workflows/nuxt-ci.yml:79:          DIRECTUS="https://directus.incomexsaigoncorp.vn"
.github/workflows/sync-check.yml:13:  VPS_DIRECTUS_URL: "https://directus.incomexsaigoncorp.vn"
.github/workflows/sync-check.yml:14:  VPS_AGENT_DATA_URL: "https://vps.incomexsaigoncorp.vn/api"
.github/workflows/sync-check.yml:15:  WEBSITE_URL: "https://vps.incomexsaigoncorp.vn"
docker-compose.local.yml:54:      test: ["CMD", "curl", "-f", "http://localhost:8055/server/health"]
docker-compose.local.yml:74:      NUXT_PUBLIC_DIRECTUS_URL: http://localhost:8055   # Browser calls (Host machine)
docker-compose.local.yml:75:      # To switch to VPS, change both to: https://directus.incomexsaigoncorp.vn
docker-compose.local.yml:76:      NUXT_PUBLIC_SITE_URL: http://localhost:3000
web/Dockerfile:32:ARG NUXT_PUBLIC_SITE_URL=https://ai.incomexsaigoncorp.vn
web/Dockerfile:33:ARG NUXT_PUBLIC_DIRECTUS_URL=https://directus.incomexsaigoncorp.vn
web/firebase.json:12:        "destination": "https://vps.incomexsaigoncorp.vn/",
web/firebase.json:17:        "destination": "https://vps.incomexsaigoncorp.vn/:path",
web/package.json:14:		"test:e2e:prod": "BASE_URL=https://vps.incomexsaigoncorp.vn playwright test",

Appendix F — Acceptable Config Surface (8)

docker-compose.override.yml:6:      DIRECTUS_ADMIN_EMAIL: ""
docker-compose.override.yml:7:      DIRECTUS_ADMIN_PASSWORD: ""
.env.local:11:DB_PORT=5432
.env.local:31:AGENT_DATA_URL=http://host.docker.internal:8000
.env.local:44:PUBLIC_URL=http://localhost:8055
.env.local:47:NUXT_PUBLIC_DIRECTUS_URL=http://localhost:8055
.env.local:48:NUXT_PUBLIC_SITE_URL=http://localhost:3000
web/.env.example:6:NUXT_PUBLIC_SITE_URL="http://localhost:3000"