KB-62E7

S125-INVESTIGATE — Claude Verification Report

9 min read Revision 1

S125-INVESTIGATE — Xác minh findings từ Re-Audit 3 agents

Agent: Claude | Date: 2026-03-15 | Loại: CHỈ ĐIỀU TRA — không sửa code/data


BẢNG TỔNG HỢP 11 FINDINGS

# Finding Agent báo Status Evidence
1 DOT-109..112 thiếu runtime trên VPS GPT CONFIRMED Scripts exist in git repo only. find /opt/incomex -name '*truth-gate*' = empty. Deploy workflow copies Nuxt build, not dot/bin/ scripts. PG functions (deprecate/retire) work but bash wrappers not on VPS.
2 CHECK 9 không chạy GPT FALSE POSITIVE CHECK 9 lives in sync-check.yml (file name ≠ workflow name). gh run list --workflow="Health Check" --limit 5 → all SUCCESS. Last scheduled: 2026-03-15T12:50 GREEN.
3A Nuxt fields count_b/count_c/cross_check GPT FALSE POSITIVE grep count_b|count_c|cross_check index.vue → NOT FOUND. These fields were removed in S116. GPT hallucinated or read stale code.
3B Nuxt status enum sai ('mở','đang_xử_lý') GPT CONFIRMED [entityType]/index.vue line 174: status: { _in: ['mở', 'đang_xử_lý'] }. DB has only open, archived. Per-entity issues panel always returns empty.
4A Agent Data API mở không auth GPT CONFIRMED (PARTIAL) POST /chat: 200 without key (can query knowledge). GET /kb/list: 200 (lists all docs). POST /documents: 401 (write protected). DELETE: 401. Read endpoints exposed, write protected.
4B Directus flows public GPT CONFIRMED GET /flows: 200, returns 100 flows with operations data. GET /items/system_issues: 200 (leaks error data). GET /items/v_registry_counts: 200 (acceptable). GET /items/directus_users: 403 (blocked).
4C PG superuser thừa GPT CONFIRMED workflow_admin role has rolsuper=true, rolcanlogin=true. This is a non-standard superuser role beyond the expected postgres.
5A deprecate_entity() RETURNING bug Claude CONFIRMED (MINOR) RETURNING $3 in EXECUTE returns the 3rd bind param. At that point $3 = v_collection (original name), so it actually returns correctly BY ACCIDENT. But the code overwrites v_collection with the RETURNING result, making it confusing. Works but fragile.
5B v_all_entity_codes thiếu 3 tables Claude CONFIRMED VIEW definition missing: table_proposals (CAT-014), checkpoint_instances (CAT-015), registry_changelog (CAT-016). These tables have entities with codes but are invisible to entity validation.
5C 119 dead links Claude+GPT CONFIRMED audit_dead_links() → 119 rows, all severity=error. Sample: FK relationships (workflow_steps→checkpoint_sets, workflows→parent_workflow) pointing to non-existent entity codes in entity_dependencies. Real data integrity issues.
5D count drift meta vs reg GPT CONFIRMED (PARTIAL) CAT-016: meta=1397, reg=1403 (drift -6). CAT-017: meta=738, reg=707 (drift 31 = archived issues not counted by reg trigger which counts only open). 17/20 OK, 2 drift explained.

CHI TIẾT TỪNG NHÓM

1. DOT-109..112 — CONFIRMED: Scripts not deployed

What exists:

  • dot_tools DB records: 4 entries with script_path = dot/bin/dot-*
  • PG functions: deprecate_entity(), retire_entity()
  • Git repo (local): 4 bash scripts in dot/bin/
  • VPS filesystem: NOTHING

Root cause: The Deploy workflow (deploy-vps.yml) runs rsync of the Nuxt build output (.output/), not the full repo. dot/bin/ scripts are in the repo but never deployed to VPS.

Impact:

  • DOT-109 (truth-gate): Can only run from developer machine via SSH, not from VPS directly
  • DOT-110 (coverage-inspector): Same
  • DOT-111 (deprecate): Bash wrapper not on VPS, but PG function deprecate_entity() works via psql
  • DOT-112 (retire): Same — PG function retire_entity() works via psql

Registry vs reality: Registry says script_path=dot/bin/dot-production-truth-gate but that path doesn't exist on VPS. This is a registry-reality mismatch.

2. CHECK 9 — FALSE POSITIVE: Running correctly

GPT likely ran gh run list without --workflow="Health Check" filter, or the workflow name sync-check.yml vs display name "Health Check" caused confusion.

Evidence: Health Check runs every 6 hours (cron), last 5 runs all SUCCESS, CHECK 9 returns "OK (20 collections tracked, DOT=112, taxonomy=55)".

3B. Status Enum Bug — CONFIRMED

The file web/pages/knowledge/registries/[entityType]/index.vue line 174 still uses the pre-S122 Vietnamese status values 'mở' and 'đang_xử_lý'. S122 migrated all statuses to English (open, archived) but this page was NOT updated.

Impact: When users navigate to a specific entity type page (e.g., /knowledge/registries/system_issue), the issues panel at the bottom always shows empty even though there are 707 open issues. This is a "rỗng giả" — appears empty but data exists.

4A. Agent Data API — CONFIRMED PARTIAL

Endpoint Auth required? Risk
POST /chat NO Anyone can query the knowledge base
GET /kb/list NO Anyone can list all document IDs
GET /health NO Acceptable (standard health check)
POST /documents YES (401) Write protected ✅
DELETE /documents YES (401) Delete protected ✅

Read endpoints are open. An attacker can enumerate all knowledge documents and query the AI chat endpoint without authentication.

4B. Directus Public Access — CONFIRMED

Collection Public? Risk
flows YES (100 flows + operations) Leaks internal automation architecture
system_issues YES Leaks error diagnostics
v_registry_counts YES Low risk (operational counts)
directus_users NO (403)
entity_labels NO (403)
taxonomy NO (403)

Flows exposure: Public can see all 100 flow names, their operations, and configuration. This reveals the entire automation architecture.

4C. PG Superuser — CONFIRMED

workflow_admin role has superuser privileges. This is likely a legacy role from the Agency OS template. It can bypass all PG security, modify any table, and drop databases.

5A. deprecate_entity RETURNING — CONFIRMED MINOR

The EXECUTE statement does RETURNING $3 where $3 is the v_collection variable. The RETURNING result is stored back INTO v_collection. This works by coincidence because $3 contains the collection name at that point. But the pattern is confusing and fragile — if someone changes the USING parameter order, it breaks silently.

5D. Count Drift — EXPLAINED

  • CAT-016 (changelog): meta_catalog.record_count=1397 vs v_registry_counts=1403. Drift=6. Cause: meta_catalog record_count is a manual/snapshot field, while v_registry_counts uses realtime PG trigger. New changelog entries arrived between last meta_catalog refresh and now.
  • CAT-017 (system_issues): meta_catalog=738 (total) vs v_registry_counts=707 (open only). Drift=31 = exactly the 31 archived issues. The custom count trigger only counts status='open'. This is BY DESIGN but meta_catalog doesn't reflect the filtered count.

PHÁT HIỆN MỚI (ngoài 11 findings)

NEW-1: meta_catalog.record_count not auto-refreshed

meta_catalog has a record_count column that is manually maintained (or refreshed by dot-catalog-sync). v_registry_counts has realtime PG triggers. The two can drift. This dual-source-of-truth for counts is confusing.

NEW-2: system_issues entity_type filter uses Vietnamese values

Line 174 uses entity_type: { _eq: entityType.value } which maps to Directus entity_type (e.g., 'system_issue'). But the filter also checks status in Vietnamese. If someone fixes the status enum, they must also verify entity_type mapping works correctly.


TÓM TẮT

Category CONFIRMED FALSE POSITIVE PARTIAL
Runtime/Deployment 1 0 0
Monitoring 0 1 0
Code Bugs 1 1 0
Security 0 0 3
PG Logic 1 0 1
Data Integrity 1 0 1
Total 4 2 5

Priority fix order:

  1. 🔴 Status enum bug (3B) — affects user-visible UI
  2. 🔴 DOT scripts not deployed to VPS (1) — registry-reality mismatch
  3. 🟡 Agent Data read endpoints open (4A) — security
  4. 🟡 Directus flows public (4B) — info disclosure
  5. 🟡 v_all_entity_codes missing 3 tables (5B) — data completeness
  6. 🟡 PG superuser workflow_admin (4C) — security posture
  7. 🟡 119 dead links (5C) — data integrity
  8. 🟢 deprecate_entity RETURNING (5A) — code quality
  9. 🟢 meta_catalog count drift (5D) — explained by design