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/** và 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 và .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 và §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"