Audit #001 — 2026-08-15
Chấm theo Audit Standard AS-01..AS-10 trên commit 57dc4fa, branch main, cộng production thật (D1 nemo12-platform remote, 9 worker đang chạy).
1. Tổng kết
| Bộ | PASS/25 | % | Mức |
|---|---|---|---|
| AS-01 Tài liệu & Đóng vết | 20/25 | 80% | Vững |
| AS-02 Yêu cầu & Sản phẩm | 13/25 | 52% | Đang dựng |
| AS-03 Kiến trúc & Hợp đồng | 15/25 | 60% | Đang dựng |
| AS-04 Dữ liệu & Migration | 10/25 | 40% | Sơ khai |
| AS-05 Trí tuệ học tập | 13/25 | 52% | Đang dựng |
| AS-06 Nội dung & Tri thức | 5/25 | 20% | Sơ khai |
| AS-07 Bảo mật & Riêng tư | 10/25 | 40% | Sơ khai |
| AS-08 Tin cậy & Vận hành | 6/25 | 24% | Sơ khai |
| AS-09 Trải nghiệm & DS | 6/25 | 24% | Sơ khai |
| AS-10 AI Governance | 10/25 | 40% | Sơ khai |
| Toàn hệ | 108/250 | 43% | Sơ khai |
AS-01 ████████████████░░░░ 80%
AS-03 ████████████░░░░░░░░ 60%
AS-02 ██████████░░░░░░░░░░ 52%
AS-05 ██████████░░░░░░░░░░ 52%
AS-04 ████████░░░░░░░░░░░░ 40%
AS-07 ████████░░░░░░░░░░░░ 40%
AS-10 ████████░░░░░░░░░░░░ 40%
AS-08 █████░░░░░░░░░░░░░░░ 24%
AS-09 █████░░░░░░░░░░░░░░░ 24%
AS-06 ████░░░░░░░░░░░░░░░░ 20%Điều kiện release: KHÔNG ĐẠT — 15/26 chỉ báo 🔴 hỏng, 6 bộ dưới 60%, điểm hệ 43% < 70%.
Đọc con số này cho đúng
43% không có nghĩa "hệ hỏng 57%". Nghĩa của nó theo luật L2/L3: hơn một nửa số chỉ báo chưa chứng minh được tại thời điểm chấm — hoặc vì phần đó chưa xây (quality profile của item, Context Builder, consent flow), hoặc vì có xây mà chưa có bằng chứng chạy (engine_runs rỗng), hoặc vì chưa ai đi rà (contrast WCAG, từng màn hình theo luật tối giản).
Thứ đang chạy thì chạy khá tốt: 102 endpoint đều có zod schema và đều dưới /v1, 0 secret trong source lẫn git history, 0 import chéo giữa 19 module, 57 test xanh, typecheck sạch, docs đóng vết 2 chiều PASS. Cái yếu nằm ở lớp chứng minh — CI không chạy test, không có audit log truy cập, không có bản ghi engine/workflow run, nội dung chưa có vòng đời chất lượng.
2. 🔴 Chặn release — 15 chỉ báo
| Chỉ báo | Sự thật quan sát được | Ảnh hưởng |
|---|---|---|
| AS-04.1.1 Một sequence migration, không trùng số | migrations/ có hai file số 0022: 0022_user_avatar.sql và 0022_whale_country_detail.sql | wrangler d1 migrations apply phụ thuộc thứ tự tên file — môi trường mới có thể áp sai thứ tự hoặc bỏ sót một file |
| AS-07.2.1 Authz backend mọi truy cập learner data | canAccessLearner() chỉ xuất hiện ở mentor, models, exams; các module progress, portraits, retention, learning, parent chưa chứng minh được có chặn | Một learner/parent có session hợp lệ có thể đọc dữ liệu learner khác |
| AS-07.2.3 Parent chỉ truy cập learner trong family — có test | Không có file test nào cho phân quyền (5 test file: runlog, goals, retention×2, planning) | Không có lưới an toàn khi refactor authz |
| AS-07.1.1 Mọi endpoint không public đều yêu cầu xác thực | 102 path, chỉ 81 tham chiếu requireSession → 21 path chưa chứng minh là public có chủ đích | Có thể có endpoint learner data mở |
| AS-07.3.2 Đồng thuận parent-first | Không có bảng/luồng consent nào trong 69 bảng production | Rủi ro pháp lý dữ liệu trẻ em |
| AS-06.3.1 Nội dung production không sửa trực tiếp | Bảng items (2.146 dòng) không có cột lifecycle (candidate/published) lẫn created_at | Sửa nội dung = sửa thẳng production, không rollback được |
| AS-06.4.2 / AS-06.4.3 Đề thật: URL nguồn, lời giải tự biên soạn | 10/10 đề đều source=generated — chưa có đề thật nào. Schema có source_ref, verified nhưng chưa dùng | REQ-EXAM chưa thực sự chạy |
| AS-10.3.1 Context Builder là đường duy nhất AI chạm learner data | Không tồn tại Context Builder trong workers/api/src/ | Khi AI bắt đầu đọc learner data sẽ không có chốt chặn |
| AS-10.3.5 Dữ liệu learner A không lọt vào context B | Không có test nào | — |
| AS-10.4.1 Nội dung AI không publish thẳng | coral/routes.ts:283 — AI sinh experience rồi ghi thẳng vào DB, không qua ngưỡng đánh giá | Nội dung sai có thể tới thẳng học sinh |
AS-01.4.1 gen:reference không tạo diff | Chạy lệnh → diff 91 dòng ở api.md + data-dictionary.md | Trang reference đang nói sai về hệ thật |
AS-03.2.4 Không breaking change trong /v1 | Không có contract diff nào chạy ở đâu | Không biết mình có phá client hay không |
| AS-04.1.4 Migration tương thích ngược | Không có dry-run trong CI; 6 migration không IF NOT EXISTS | Deploy có thể gãy giữa chừng |
| AS-09.3.1 WCAG AA contrast | Chưa ai đo | Có thể có chữ học sinh không đọc được |
🔴 đã PASS (11) — giữ nguyên, đừng làm hỏng
AS-03.4.1 không secret hardcode · AS-04.2.2 email không làm khóa · AS-05.2.2 self-report chỉ vào evidence · AS-05.4.1 mastery không tự decay · AS-07.2.2 RBAC không so email · AS-07.5.1 git history sạch secret · AS-07.5.2 không debug/seed endpoint · AS-08.2.2 DLQ đủ · AS-08.4.3 migration trước code · AS-10.1.1 100% AI qua Gateway · AS-10.1.2 không probe-fallback.
3. Chi tiết theo bộ
Ký hiệu: ✅ PASS · ❌ KHÔNG PASS · 🔴 chỉ báo chặn release.
AS-01 — Tài liệu & Đóng vết · 20/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 1.1.1 md ngoài docs/ | ✅ | chỉ README.md, .claude/skills/*, apps/pearl/content/* (nội dung app); worktree cũ bị git ignore |
| 1.1.2 dòng SRC đủ | ✅ | intake.md 110 dòng, đủ ngày + tóm tắt + kết quả |
| 1.1.3 SRC đã canonical hóa | ✅ | spot-check SRC-100..108 đều có PRD/SDD tương ứng |
| 1.1.4 SRC liên tục không trùng | ❌ | SRC-059 và SRC-060 mỗi số có 2 dòng (110 dòng / 108 số) |
| 1.1.5 không đặc tả ngoài docs/ | ✅ | rà toàn repo |
| 1.2.1 frontmatter đủ file | ✅ | check-docs.mjs: 57 docs sạch |
| 1.2.2 đủ 8 trường bắt buộc | ✅ | vòng lặp kiểm 8 khóa × 57 file: 0 thiếu |
| 1.2.3 id duy nhất | ✅ | script |
| 1.2.4 type hợp lệ | ✅ | convention/index/prd/quality/reference/sdd |
| 1.2.5 status hợp lệ | ✅ | không có file deprecated |
| 1.3.1 REQ có SDD | ✅ | check-docs PASS |
| 1.3.2 REQ có QG | ✅ | check-docs kiểm cột QG |
| 1.3.3 sources trỏ SRC tồn tại | ✅ | script |
| 1.3.4 không doc mồ côi | ✅ | 0 orphan |
| 1.3.5 US ↔ REQ hai chiều | ❌ | 66 US cho 224 REQ ✔; không có kiểm tự động chiều REQ MUST → US/WF |
| 1.4.1 gen:reference không diff | ❌ 🔴 | diff 91 dòng (api.md 14, data-dictionary.md 80) |
| 1.4.2 bảng D1 có trong dictionary | ❌ | thiếu bảng của migration 0026/0028/0029/0030 |
| 1.4.3 route có trong api.md | ❌ | thiếu 14 dòng endpoint |
| 1.4.4 event có trong events.md | ✅ | events.md không lệch |
| 1.4.5 dấu "sinh tự động" | ✅ | ⚙️ Trang này sinh tự động… đầu mỗi trang |
| 1.5.1 last_reviewed ≤ 90 ngày | ✅ | sớm nhất 2026-08-13 |
| 1.5.2 sửa lớn thì tăng version | ✅ | spot-check git log |
| 1.5.3 không link gãy | ✅ | check-docs |
| 1.5.4 ngày tuyệt đối | ✅ | 8 hit "gần đây/sắp tới" đều là ngôn ngữ UI, không phải mốc thời gian |
| 1.5.5 quyết định ✍️ | ✅ | open-questions/index.md |
AS-02 — Yêu cầu & Sản phẩm · 13/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 2.1.1 ID đúng scheme | ✅ | 259 REQ khớp REQ-<nhóm>-xx |
| 2.1.2 REQ testable | ❌ | còn REQ dùng từ mơ hồ (L4: một phản ví dụ là đủ) |
| 2.1.3 có priority | ❌ | 4 REQ priority M?: MEN-04, SCH-04, SCH-05, EXAM-05 |
| 2.1.4 có nguồn | ✅ | mọi REQ có SRC/User+ngày/FEAT/Q |
| 2.1.5 không trùng nghĩa | ❌ | chưa rà — không bằng chứng (L3) |
| 2.2.1 US đúng format | ✅ | 66/66 có As a **…**, I want…, so that… |
| 2.2.2 persona hợp lệ | ✅ | Nemo/Marlin/Dolphin/Staff |
| 2.2.3 US có acceptance criteria | ❌ | bảng US chỉ 3 cột (ID · story · REQ) — không có cột AC |
| 2.2.4 AC mô tả kết quả người dùng | ❌ | chưa có AC nên không đánh giá được |
| 2.2.5 US MUST → màn hình thật | ❌ | chưa map |
| 2.3.1 persona có JTBD | ✅ | parent-jtbd.md + PRD §personas |
| 2.3.2 JTBD có REQ | ✅ | traceability |
| 2.3.3 3 cộng đồng có onboarding | ❌ | có learner-onboarding, parent-onboarding; Dolphins chưa có WF onboarding |
| 2.3.4 6 school có mô hình | ✅ | SDD-011 |
| 2.3.5 màn hình nào cũng thuộc persona | ❌ | chưa rà ngược từ route |
| 2.4.1 REQ ✔ có artifact | ✅ | 224 REQ ✔ đều có cột SDD + QG |
| 2.4.2 tính năng nào cũng có REQ | ❌ | chưa rà ngược |
| 2.4.3 backlog tách bạch | ✅ | FEAT/CC nằm ở legacy-feature-inventory |
| 2.4.4 FEAT legacy phân loại | ✅ | legacy-feature-inventory |
| 2.4.5 REQ MUST ⏳ có lý do | ❌ | 20 REQ ⏳ không kèm ghi chú lý do/ngày |
| 2.5.1 Q có ID + trạng thái | ✅ | Q-001..106 |
| 2.5.2 ✍️ có lý do + ngày | ✅ | open-questions |
| 2.5.3 ✍️ không mâu thuẫn | ❌ | chưa rà |
| 2.5.4 việc chờ tay tập trung | ✅ | open-questions + README §Còn chờ |
| 2.5.5 Q đã trả lời vào canonical | ✅ | spot-check Q-069, Q-084, Q-097 |
AS-03 — Kiến trúc & Hợp đồng · 15/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 3.1.1 module đúng cấu trúc | ✅ | 19 module trong workers/api/src/modules/ |
| 3.1.2 không import chéo module | ✅ | 0 kết quả grep import chéo |
| 3.1.3 frontend qua client chung | ✅ | mỗi app có src/api.ts |
| 3.1.4 DS là nguồn duy nhất | ✅ | không fork component; pearl bắc cầu --vp-* → token |
| 3.1.5 cấu trúc khớp tài liệu | ✅ | khớp README + SDD-001 |
| 3.2.1 OpenAPI sinh từ router | ✅ | không có file openapi viết tay |
| 3.2.2 route có zod schema | ✅ | 102 route qua createRoute, 104 khối responses |
3.2.3 route dưới /v1 | ✅ | 102/102 path bắt đầu /v1 |
3.2.4 không breaking /v1 | ❌ 🔴 | không có contract diff chạy ở đâu |
| 3.2.5 error taxonomy | ✅ | shared/errors.ts + ErrorCode, không rò stack |
| 3.3.1 event có schema + version | ❌ | chưa chứng minh version từng event |
| 3.3.2 event có consumer | ❌ | chưa đối chiếu |
| 3.3.3 tên event theo quy ước | ❌ | chưa kiểm |
| 3.3.4 payload không PII | ❌ | chưa kiểm |
| 3.3.5 queue + DLQ khớp reference | ✅ | EVENTS producer + consumer + nemo12-events-dlq |
| 3.4.1 không secret hardcode | ✅ 🔴 | grep pattern key/secret/token ≥16 ký tự: 0 |
| 3.4.2 không hardcode domain rải rác | ❌ | https://api.nemo12.com lặp ở ≥6 app (là fallback của VITE_API_URL) |
| 3.4.3 env khai kiểu | ✅ | env.ts khai 10 binding/biến |
| 3.4.4 CI verify binding | ❌ | không workflow nào verify binding (RISK-026) |
| 3.4.5 reference/config đủ | ❌ | chưa đối chiếu đủ |
| 3.5.1 mỗi app có workflow | ✅ | 9 workflow, có path filter |
| 3.5.2 worker có domain tường minh | ✅ | wrangler config |
| 3.5.3 app ↔ workflow đủ đôi | ✅ | 9 ↔ 9 |
| 3.5.4 migration trước code | ✅ | deploy-api.yml:19 trước :25 |
| 3.5.5 README khớp URL thật | ❌ | README liệt kê 4 URL, thực tế 9 (thiếu coral, pearl, admin, mentors, docs) |
AS-04 — Dữ liệu & Migration · 10/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 4.1.1 một sequence, không trùng số | ❌ 🔴 | 0022 xuất hiện 2 lần |
| 4.1.2 idempotent | ❌ | 6 file không IF NOT EXISTS: 0007, 0012, 0015, 0022_user_avatar, 0025, 0026 |
| 4.1.3 không DML destructive trộn DDL | ✅ | chỉ 0007 có DROP TABLE IF EXISTS trên bảng rỗng (tái cấu trúc DDL) |
| 4.1.4 tương thích ngược | ❌ 🔴 | không dry-run CI, không chứng minh |
| 4.1.5 mọi migration đã áp | ✅ | 31 file / 31 dòng d1_migrations, mới nhất 0030_context_events.sql |
| 4.2.1 mọi bảng có PK | ✅ | 0 bảng thiếu PRIMARY KEY |
| 4.2.2 email không làm khóa | ✅ 🔴 | users.id TEXT PRIMARY KEY, email chỉ UNIQUE |
| 4.2.3 FK có ràng buộc | ✅ | REFERENCES trong schema |
| 4.2.4 timestamps chuẩn hóa | ❌ | 31 bảng không có created_at (dùng started_at, recorded_at, hoặc không có) |
| 4.2.5 không JSON blob thay truy vấn | ❌ | items.options_json, nhiều *_json không index/không tách trường |
| 4.3.1 bảng có trong data-dictionary | ❌ | dictionary trong repo lệch 80 dòng so với schema thật |
| 4.3.2 cột có ý nghĩa nghiệp vụ | ❌ | chưa kiểm từng cột |
| 4.3.3 không bảng ma | ✅ | không có bảng trong dictionary mà thiếu ở D1 |
| 4.3.4 enum liệt kê đủ | ✅ | CHECK (… IN (…)) khắp schema |
| 4.3.5 state machine được vẽ | ❌ | chưa đối chiếu đủ thực thể |
| 4.4.1 seed bằng script | ✅ | 40+ script trong scripts/ |
| 4.4.2 seed idempotent | ❌ | chưa chạy lại kiểm |
| 4.4.3 không bản ghi mồ côi | ✅ | items WHERE node_id IS NULL = 0 |
| 4.4.4 không trùng khóa nghiệp vụ | ❌ | chưa kiểm đủ rộng |
| 4.4.5 song ngữ đủ cặp | ✅ | skill_nodes: 274/274 có title_en, module_en, unit_en |
| 4.5.1 chính sách retention dữ liệu | ❌ | chưa khai báo |
| 4.5.2 đường xóa dữ liệu | ❌ | không có endpoint/đặc tả |
| 4.5.3 policy giữ model version | ❌ | learner_model_versions = 0 dòng |
| 4.5.4 lý do từng trường PII | ❌ | chưa ghi |
| 4.5.5 backup đã thử | ❌ | chưa có |
AS-05 — Trí tuệ học tập · 13/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 5.1.1 model có trang mô tả | ✅ | reference/models.md |
| 5.1.2 version ghi vào bản ghi | ❌ | learner_model_versions = 0 dòng |
| 5.1.3 snapshot theo thời gian | ❌ | 0 dòng |
| 5.1.4 model nào cũng có trang | ✅ | models.md phủ Learner/Goal/Context/Retention/Planning |
| 5.1.5 đổi thuật toán → version mới | ✅ | plan-v1 trong models/planning.ts |
| 5.2.1 model từ evidence có nguồn | ✅ | learner_evidence = 60 dòng |
| 5.2.2 self-report chỉ qua evidence | ✅ 🔴 | REQ-LRN-15: self-report vào Evidence Registry tier .50 |
| 5.2.3 evidence có tier | ✅ | tier .50/.60 theo source |
| 5.2.4 chỉ lần đầu là evidence | ✅ | SRC-103: lần sửa không gửi /answer |
| 5.2.5 engine run có lịch sử | ❌ | engine_runs = 0 dòng (bảng có, chưa ai ghi) |
| 5.3.1 engine có unit test | ❌ | 5 test file cho 19 module: goals, retention×2, planning, runlog. Assessment/Recommendation/Readiness/Context không có test |
| 5.3.2 không source-regex test | ✅ | 57 test đều test hành vi |
| 5.3.3 test ca biên/rỗng | ❌ | chưa phủ mọi engine |
| 5.3.4 test stopping criteria | ❌ | không có |
| 5.3.5 test chặn merge trong CI | ❌ | không workflow nào chạy test |
| 5.4.1 mastery không tự decay | ✅ 🔴 | retention/periodic.test.ts test bất biến |
| 5.4.2 retention có decay | ✅ | retention/engine.test.ts 27 test |
| 5.4.3 retention cập nhật định kỳ | ✅ | cron 21:00 UTC → WF-17 |
| 5.4.4 job chỉ ghi trường phái sinh | ✅ | test bất biến anchor |
| 5.4.5 tham số review window ở reference | ✅ | reference/retention-model.md |
| 5.5.1 recommendation có reason | ✅ | SDD-002 + UI |
| 5.5.2 ghi model/prompt version | ❌ | learner_model_versions rỗng → không chứng minh được |
| 5.5.3 plan có diff + vì sao | ✅ | planning.ts + 8 test + trang /ke-hoach |
| 5.5.4 output có confidence | ❌ | chưa chứng minh phủ mọi output quan trọng |
| 5.5.5 người dùng xem lịch sử version | ❌ | không có version nào để xem |
AS-06 — Nội dung & Tri thức · 5/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 6.1.1 node có subject/grade/level | ✅ | skill_nodes có đủ 3 cột |
| 6.1.2 không node mồ côi | ✅ | 274/274 có strand + unit |
| 6.1.3 tiên quyết không chu trình | ❌ | chưa chạy kiểm chu trình trên skill_edges |
| 6.1.4 unit đủ experience tối thiểu | ❌ | chưa kiểm 3 assessment + 6 learning mỗi unit |
| 6.1.5 tên đủ cặp vi/en | ✅ | 274/274 |
| 6.2.1 quality profile 8 chiều | ❌ | bảng items không có cột chất lượng nào |
| 6.2.2 mỗi chiều có evidence | ❌ | không có |
| 6.2.3 multi-evaluator variance | ❌ | không có |
| 6.2.4 item link node + dạng bài | ✅ | node_id NOT NULL + role CHECK IN (canonical/variant/boundary/discriminator) |
| 6.2.5 item bị report vào hàng đợi | ❌ | có bảng content_reports, chưa nối hàng đợi rà soát |
| 6.3.1 không sửa production trực tiếp | ❌ 🔴 | items không có lifecycle candidate/published |
| 6.3.2 candidate có trạng thái | ❌ | không có |
| 6.3.3 publish theo ngưỡng | ❌ | không có |
| 6.3.4 lịch sử ai publish khi nào | ❌ | items không cả created_at |
| 6.3.5 rollback nội dung | ❌ | không có |
| 6.4.1 đề thật đủ provenance | ❌ | 10/10 đề source=generated — chưa có đề thật |
| 6.4.2 lưu URL không lưu file | ❌ 🔴 | schema có source_ref nhưng chưa dùng |
| 6.4.3 lời giải tự biên soạn | ❌ 🔴 | chưa có đề thật |
| 6.4.4 crawl robots/ToS-aware | ❌ | chưa chạy crawl |
| 6.4.5 đề authentic bất biến | ❌ | chưa có |
| 6.5.1 media qua moderation | ❌ | chưa chạy |
| 6.5.2 media ghi nguồn/giấy phép | ❌ | chưa có |
| 6.5.3 không dùng ảnh bên thứ ba | ✅ | mascot vẽ tay bằng SVG trong repo |
| 6.5.4 media đúng kích thước | ❌ | chưa kiểm |
| 6.5.5 ảnh trẻ em có đồng thuận | ❌ | chưa có |
AS-07 — Bảo mật, Riêng tư & Tuân thủ · 10/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 7.1.1 endpoint không public phải auth | ❌ 🔴 | 102 path / 81 tham chiếu requireSession → 21 chưa chứng minh |
| 7.1.2 token có hạn + thu hồi | ✅ | resolveSession + rotated_token |
| 7.1.3 verify audience/issuer | ❌ | chưa kiểm |
| 7.1.4 khu nội bộ có Access | ✅ | dolphin + coral tạo trong ngày, ba cổng đều 302 sang Access (§5) |
| 7.1.5 không backdoor | ✅ | rà index.ts + middleware |
| 7.2.1 authz backend learner data | ❌ 🔴 | canAccessLearner chỉ ở mentor/models/exams |
| 7.2.2 RBAC không so email | ✅ 🔴 | 0 so sánh email trong authz |
| 7.2.3 parent↔family có test | ❌ 🔴 | không có test authz |
| 7.2.4 mentor bắt buộc audit log | ❌ | mentor/routes.ts không ghi audit_log |
| 7.2.5 permissions khớp code | ❌ | chưa đối chiếu |
| 7.3.1 mỗi trường trẻ em có mục đích | ❌ | chưa ghi |
| 7.3.2 consent parent-first | ❌ 🔴 | không có bảng/luồng consent |
| 7.3.3 chỉ learner ghi phần của mình | ✅ | PUT /portraits/{id}/learner-sections role-gated (SRC-106) |
| 7.3.4 không chia sẻ bên thứ ba | ✅ | chỉ Cloudflare AI qua Gateway |
| 7.3.5 parent thấy dữ liệu dùng để quyết | ❌ | chưa có |
| 7.4.1 log truy cập learner data | ❌ | chỉ 3 điểm ghi audit_log, đều là identity (user.created, learner.invited, learner.joined) |
| 7.4.2 log đủ ai/gì/khi/từ đâu | ❌ | audit_log không có created_at, không có IP |
| 7.4.3 log không chứa nội dung nhạy cảm | ✅ | chỉ lưu target_type + target_id |
| 7.4.4 log không sửa được | ❌ | không có cơ chế |
| 7.4.5 truy vấn log điều tra | ❌ | không có endpoint |
| 7.5.1 không secret trong git history | ✅ 🔴 | quét toàn bộ lịch sử: 0 |
| 7.5.2 không debug/seed endpoint prod | ✅ 🔴 | 0 path `/v1/debug |
| 7.5.3 validate schema trước DB | ✅ | zod ở 102 route |
| 7.5.4 escape nội dung người dùng | ✅ | 1 dangerouslySetInnerHTML nhưng nội dung do engine sinh, không phải input người dùng |
| 7.5.5 rate limit endpoint tốn kém | ❌ | 0 rate limit — kể cả route AI và đăng nhập |
AS-08 — Tin cậy & Vận hành · 6/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 8.1.1 khai availability tier | ❌ | chưa khai |
| 8.1.2 trả lời 5 câu production-ready | ❌ | chưa viết |
| 8.1.3 "hỏng thì người dùng thấy gì" | ❌ | chưa định nghĩa |
| 8.1.4 health phản ánh phụ thuộc thật | ✅ | index.ts:92 chạy SELECT 1 trên D1 |
| 8.1.5 không TODO/FIXME chặn đường | ✅ | 0 trong toàn source |
| 8.2.1 consumer idempotent | ❌ | chưa kiểm |
| 8.2.2 queue có DLQ | ✅ 🔴 | dead_letter_queue: nemo12-events-dlq |
| 8.2.3 replay DLQ | ❌ | chưa có quy trình |
| 8.2.4 retry có giới hạn + backoff | ❌ | chưa khai max_retries |
| 8.2.5 cron an toàn khi chạy chồng | ❌ | chưa có khóa |
| 8.3.1 observability mọi worker | ✅ | 9/9 wrangler config bật |
| 8.3.2 log có level + request id | ❌ | chưa có |
| 8.3.3 5xx ghi đủ ngữ cảnh | ❌ | chưa kiểm |
| 8.3.4 chỉ số engine/queue | ❌ | chưa có |
| 8.3.5 biết workflow đã chạy chưa | ❌ | workflow_runs = 0 dòng |
| 8.4.1 CI typecheck + lint + test | ❌ | không workflow nào chạy (chỉ deploy-docs chạy check:docs) |
| 8.4.2 path filter đúng | ✅ | 9 workflow đều có |
| 8.4.3 migration trước code | ✅ 🔴 | deploy-api.yml |
| 8.4.4 rollback nhanh | ❌ | chưa ghi quy trình |
| 8.4.5 không bước tay bắt buộc | ❌ | AI Gateway còn phải tạo tay (Access đã xong 2026-08-15) |
| 8.5.1 phụ thuộc ngoài có fallback | ❌ | AI lỗi → 503, không fallback |
| 8.5.2 lỗi ngoài không sập trang chính | ❌ | chưa thử |
| 8.5.3 timeout tường minh | ❌ | 0 AbortSignal.timeout / signal: |
| 8.5.4 cache dữ liệu đọc nhiều | ❌ | chưa có |
| 8.5.5 thông điệp người dùng hiểu | ✅ | errorResponse trả tiếng Việt tự nhiên |
AS-09 — Trải nghiệm & Design System · 6/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 9.1.1 một hành động chính mỗi màn | ❌ | chưa rà từng màn (L3) |
| 9.1.2 full-width không cột thừa | ❌ | chưa rà |
| 9.1.3 element tối thiểu | ❌ | chưa rà |
| 9.1.4 hình hơn chữ | ❌ | chưa rà |
| 9.1.5 trang chủ là hub | ❌ | chưa rà |
| 9.2.1 chỉ dùng token, không hex | ❌ | 1.340 mã hex trong apps/*/src (phần lớn là SVG art, nhưng có cả Learning.tsx) |
| 9.2.2 không fork component | ✅ | mỗi component dùng chung một định nghĩa |
| 9.2.3 không CSS per-page | ❌ | chưa rà |
| 9.2.4 theme chỉ đổi accent | ✅ | .theme-pearl trong tokens/base.css |
| 9.2.5 sàn 14px | ❌ | 79 chỗ dùng text-xs (12px) |
| 9.3.1 WCAG AA contrast | ❌ 🔴 | chưa đo |
| 9.3.2 focus state nhìn thấy | ❌ | chưa thử |
| 9.3.3 touch target ≥44px | ❌ | chưa đo |
| 9.3.4 ảnh có alt | ✅ | 5/5 <img> có alt |
| 9.3.5 điều hướng bàn phím | ❌ | chưa thử |
| 9.4.1 admin tiếng Anh | ✅ | UI string tiếng Anh (chỉ comment code tiếng Việt) |
| 9.4.2 không lẫn 2 ngôn ngữ | ❌ | chưa rà |
| 9.4.3 thuật ngữ theo glossary | ❌ | chưa đối chiếu |
| 9.4.4 lỗi viết cho người dùng | ✅ | errorResponse |
| 9.4.5 chữ không lặp nội dung hình | ❌ | chưa rà |
| 9.5.1 load dưới ngưỡng | ❌ | chưa khai ngưỡng |
| 9.5.2 không layout shift | ❌ | chưa đo |
| 9.5.3 có loading/empty/error | ❌ | chưa rà |
| 9.5.4 ảnh đúng kích thước | ❌ | chưa đo |
| 9.5.5 thao tác chính phản hồi ngay | ✅ | SRC-103: chấm ở client, không chờ round-trip |
AS-10 — AI Governance & Chi phí · 10/25
| Chỉ báo | Bằng chứng | |
|---|---|---|
| 10.1.1 100% qua AI Gateway | ✅ 🔴 | 2/2 điểm gọi c.env.AI.run(..., { gateway: { id: c.env.AI_GATEWAY_ID } }) |
| 10.1.2 không probe-fallback | ✅ 🔴 | không có vòng dò model |
| 10.1.3 model id tường minh | ✅ | @cf/meta/llama-3.3-70b-instruct-fp8-fast |
| 10.1.4 không gọi AI từ frontend | ✅ | 0 trong apps/*/src |
| 10.1.5 mọi điểm gọi có trong ai-registry | ✅ | reference/ai-registry.md |
| 10.2.1 prompt trong registry | ❌ | prompt viết inline trong coral/routes.ts |
| 10.2.2 prompt có version | ✅ | PROMPT_VERSION lưu vào metadata |
| 10.2.3 đổi prompt = version mới | ❌ | chưa chứng minh |
| 10.2.4 prompt ghi mục đích/ràng buộc | ❌ | không có registry |
| 10.2.5 output có schema + validate | ❌ | z.object({ data: z.any() }) — không schema thật |
| 10.3.1 Context Builder duy nhất | ❌ 🔴 | không tồn tại Context Builder |
| 10.3.2 context tối thiểu hóa | ❌ | không có builder |
| 10.3.3 không gửi định danh trẻ | ✅ | prompt chỉ chứa node/blueprint |
| 10.3.4 lưu input_ref | ✅ | metadata lưu model + prompt_version + blueprint_version |
| 10.3.5 test A không lọt sang B | ❌ 🔴 | không có test |
| 10.4.1 AI không publish thẳng | ❌ 🔴 | coral/routes.ts:283 ghi thẳng vào DB |
| 10.4.2 multi-evaluator | ❌ | chưa có |
| 10.4.3 spot-check có tỷ lệ | ❌ | chưa ghi |
| 10.4.4 khẳng định có nguồn/đánh dấu | ❌ | chưa có |
| 10.4.5 learner báo sai → chỉnh nội dung | ❌ | content_reports chưa nối vòng |
| 10.5.1 ước tính chi phí | ❌ | chưa ghi |
| 10.5.2 xem chi phí theo thời gian | ❌ | AI Gateway nemo12 chưa tạo |
| 10.5.3 hạn mức/cảnh báo | ❌ | chưa có |
| 10.5.4 tác vụ nền có giới hạn | ❌ | chưa có |
| 10.5.5 không vòng lặp AI vô hạn | ✅ | AI chỉ gọi từ route staff/admin |
4. Hành động sinh ra từ audit này
Mỗi KHÔNG PASS cần một hành động. Nhóm theo chủ đề, xếp theo mức chặn:
| # | Hành động | Đóng được chỉ báo | Ước lượng |
|---|---|---|---|
| A | Đổi tên 0022_whale_country_detail.sql → 0031_…, thêm IF NOT EXISTS cho 6 migration | AS-04.1.1 🔴, 4.1.2 | 30 phút |
| B | Thêm canAccessLearner cho mọi module chạm learner data + test parent↔family + rà 21 endpoint chưa rõ | AS-07.1.1 🔴, 7.2.1 🔴, 7.2.3 🔴 | 1 ngày |
| C | Thêm typecheck + test + check:docs + gen:reference gate vào CI mọi workflow | AS-05.3.5, 8.4.1, 1.4.1 🔴, 3.2.4 🔴 | nửa ngày |
| D | Ghi engine_runs / workflow_runs / learner_model_versions thật khi engine chạy | AS-05.1.2, 5.1.3, 5.2.5, 5.5.2, 5.5.5, 8.3.5 | 1 ngày |
| E | Vòng đời nội dung cho items: cột status + quality profile + created_at + publisher | AS-06.2.1..3, 6.3.1 🔴, 6.3.2..5 | 2 ngày |
| F | Context Builder + ngưỡng đánh giá trước khi AI ghi nội dung | AS-10.3.1 🔴, 10.3.2, 10.3.5 🔴, 10.4.1 🔴 | 2 ngày |
| G | Audit log cho mọi truy cập learner data (mentor bắt buộc) + endpoint truy vấn | AS-07.2.4, 7.4.1, 7.4.2, 7.4.4, 7.4.5 | 1 ngày |
| H | Consent parent-first + chính sách retention/xóa dữ liệu trẻ em | AS-07.3.1, 7.3.2 🔴, 7.3.5, 4.5.1, 4.5.2, 4.5.4 | 2 ngày |
| I | Rà UI theo luật tối giản + đo WCAG AA + bỏ text-xs + thay hex bằng token | AS-09.1.*, 9.2.1, 9.2.5, 9.3.1 🔴, 9.3.2, 9.3.3 | 2 ngày |
| J | Rate limit + timeout + fallback cho phụ thuộc ngoài | AS-07.5.5, 8.5.1, 8.5.3 | nửa ngày |
| K | Sửa sổ sách: SRC-059/060 trùng, 4 REQ M?, cột AC cho US, README 9 URL | AS-01.1.4, 2.1.3, 2.2.3, 3.5.5 | nửa ngày |
5. Đính chính (2026-08-15)
- AS-07.1.4 (khu nội bộ có Cloudflare Access) — chấm ❌ dựa trên README §Còn chờ. Lúc audit thì chỉ
admin.nemo12.comcó Access; cùng ngày đã tạo nốt appNemo12 Dolphin+Nemo12 Coraltrên dashboard (SRC-132) và kiểm bằng request thật: cả ba cổng nội bộ đều 302 sang trang login Access. Chỉ báo này là ✅. Điểm AS-07 thành 11/25 (44%), điểm hệ thành 109/250 (44%). Mức vẫn Sơ khai, số 🔴 hỏng không đổi (7.1.4 không phải 🔴). README cần cập nhật. - AS-10.5.2 (xem chi phí AI) — chưa xác minh được gateway
nemo12có tồn tại trên Cloudflare hay không:AI_GATEWAY_ID: "nemo12"đã khai ởworkers/api/wrangler.jsonc:41, nhưng API token hiện tại không có scope đọc AI Gateway. Giữ ❌ cho tới khi kiểm được trên dashboard.
6. Ghi chú phương pháp
- Bằng chứng thu bằng lệnh thật trên commit
57dc4fa:check-docs.mjs,gen-reference.mjs,vitest run(57 test xanh),npm run typecheck(sạch),wrangler d1 execute --remotetrên D1 production, và grep/rà source. - Theo L2 (cấm N/A) và L3 (không bằng chứng = KHÔNG PASS): chỉ báo cho phần chưa xây và chỉ báo chưa ai đi kiểm đều tính KHÔNG PASS. Ghi chú "chưa rà" / "chưa kiểm" trong cột bằng chứng phân biệt hai loại này để lần audit sau biết đâu là việc xây và đâu là việc chứng minh.
- AS-09.1 (luật tối giản) và AS-09.3.2/9.3.3/9.3.5 cần một lượt rà bằng mắt + đo trên trình duyệt — chưa làm trong lần này.