Appearance
Legacy Audit & Migration Risk Register
Kết quả rà soát 2026-08-13: chuyenchon (→ Turtle + Shark) và sutucon.com (→ Octopus). Mỗi rủi ro có mã RISK-xxx được trích dẫn trong PRD/SDD; cột Đối sách chỉ tới nơi Nemo12 xử lý.
Severity: 🔴 blocker · 🟠 major · 🟡 minor.
1. Identity & Data
| ID | Sev | Repo | Rủi ro | Đối sách |
|---|---|---|---|---|
| RISK-001 | 🔴 | chuyenchon | Không có canonical learner identity — owner_key = email lowercase là PK của ~40 bảng (111 vị trí SQL); family↔learner join bằng so khớp chuỗi email | REQ-ACC-04, SDD-001 §7: users.id/learners.id UUID, email chỉ là thuộc tính login |
| RISK-002 | 🔴 | sutucon | Schema thật không nằm trong repo — ~70 bảng (users, courses, evidence registry, learner models…) có DDL ở repo ngoài api.conan.school | Nemo12 thiết kế schema mới từ SDD; nếu migrate data cần truy cập repo đó (Q-054) |
| RISK-003 | 🟠 | cả hai | Knowledge/skill định nghĩa trùng lặp ×3 (TS graphs 6.5k LOC → mori seed → learning_graph_nodes) | SDD-003 §3: một registry duy nhất, seed từ TS graphs |
| RISK-004 | 🔴 | chuyenchon | Một D1 dùng chung 4 workers với 3 chuỗi migration đánh số trùng nhau từ 0001 | REQ-PLT-11, SDD-001 §7: một sequence duy nhất |
| RISK-005 | 🟠 | cả hai | 4+ hệ rubric song song (rubric_, quality_rubric_, le_rubric_, question_quality_) + 2 framework .mjs root | SDD-003 §7: một rubric registry, gốc CC-QAF-1.0 |
| RISK-006 | 🟠 | cả hai | 4 item banks không tương thích (assessment_item, math_diagnostic_item, diagnosis_question_registry, exam_problems) | SDD-004 §9: một Item Bank; exam_problems là registry Shark riêng có liên kết |
| RISK-007 | 🟠 | sutucon | 2 learner model cạnh tranh (learner_*_models course-scoped vs member_* 10-dimension) + model thứ 3 chỉ có trong docs kiara | SDD-002 §2 là canonical; member intelligence → REQ-PAR-08 ⏳ |
| RISK-008 | 🔴 | sutucon | DB production dùng chung conan-platform-production với sản phẩm khác; tenancy = UUID literal hardcode 5+ files | Nemo12 dùng D1 mới nemo12-platform, không đụng DB cũ; school_id là cột có ràng buộc |
| RISK-017 | 🟡 | cả hai | Schema nặng JSON blob (~113 cột *_json), enum tiếng Việt literal (chac/lung_lay/hong), timestamps TEXT không kỷ luật | SDD-001 §7 chuẩn hóa; enum tiếng Việt chỉ ở presentation layer |
2. Architecture
| ID | Sev | Repo | Rủi ro | Đối sách |
|---|---|---|---|---|
| RISK-009 | 🔴 | chuyenchon | Onboarding ép mọi learner khai mục tiêu thi chuyên (exam_year, target_school NOT NULL; app gate toàn bộ sau onboarding) — learner Turtle không thể tồn tại | REQ-LRN-08: onboarding không ép goal thi chuyên |
| RISK-010 | 🟠 | cả hai | Không Hono: router tay ~6.7k LOC (chuyenchon); 35 Pages Functions copy-paste HMAC làm BFF (sutucon) — port = rewrite | SDD-001 §5: Hono + zod-openapi từ đầu |
| RISK-011 | 🟠 | chuyenchon | 4 paradigm frontend trộn lẫn: Astro SSR, Vite MPA 19 entries + 310 islands, vanilla TS, custom Node builder | SDD-001 §4: một chuẩn Vite+React SPA per app |
| RISK-012 | 🟠 | cả hai | Frontend nguyên khối: App.tsx 5.1k/8.3k LOC; admin là fork byte-level của www (~25k LOC nhân ba) | Design System package + cấu trúc route chuẩn; cấm fork app |
| RISK-018 | 🟠 | chuyenchon | Không Queues — cron poll bảng D1 + hand-rolled lease/lock (12+ crons, có cron * * * * *) | SDD-003 §10, SDD-006 §5: Cloudflare Queues + DLQ |
| RISK-019 | 🟠 | cả hai | Cross-school skill state fragmentation (turtle.algebra vs shark.algebra) | SDD-007 §5: canonical skill + school context |
| RISK-020 | 🟠 | sutucon | Mentor domain là proxy rỗng 42 dòng → api.conan.school (router ~1200 dòng + workflows nằm ngoài repo) nhưng rafiki 8.3k LOC phụ thuộc nó | App mentors Nemo12 xây mới theo REQ-MEN; không port proxy |
| RISK-026 | 🟠 | sutucon | Bug tiềm ẩn: MEMBER_INTELLIGENCE_WORKFLOW gọi nhưng không bind (TypeError mỗi final submission); 1 workflow bind sang worker ngoài (script_name=api-conan-school) | Không mang sang; CI check binding tồn tại (QG-009) |
| RISK-030 | 🟡 | cả hai | Phụ thuộc ngoài không kiểm soát: CAPOS (capos.internal), upstream conan.school; docs legacy mâu thuẫn (2 cặp system-design khác nhau, ADR đánh số trùng) | Intake + ADR registry mới; CAPOS → Q-043 |
3. Security & Config
| ID | Sev | Repo | Rủi ro | Đối sách |
|---|---|---|---|---|
| RISK-013 | 🔴 | chuyenchon | Owner email dac2205@gmail.com hardcode 5 files; 2 Access audience hex hardcode; không có RBAC — "admin" = so sánh email | REQ-ACC-05 RBAC + REQ-SEC-06 cấm hardcode |
| RISK-021 | 🟠 | cả hai | 2 bản Google OAuth khác nhau (app vs family, cookie host-only không SSO); sutucon thì ổn hơn (GSI id_token) | SDD-001 §6: một auth module, GSI id_token (không cần client secret), cookie .nemo12.com + rotation |
| RISK-022 | 🟠 | chuyenchon | AI Gateway "probe-then-fallback": ping lỗi 1 lần → cả isolate bypass gateway âm thầm; exam-planning gọi AI không qua gateway | REQ-PLT-09: gateway bắt buộc, fail = fail rõ ràng |
| RISK-023 | 🟠 | cả hai | Domain hardcode ở 45 files (chuyenchon) / ~30 files (sutucon); cookie domain, CORS regex, school_id literal | REQ-SEC-06 + config package |
| RISK-024 | 🟡 | sutucon | openapi.json sinh từ danh sách route viết tay, không từ router; route không có zod validation | REQ-PLT-04: OpenAPI sinh từ code |
| RISK-025 | 🟡 | sutucon | Observability không bật cho api worker production | SDD-006 §10: bật cho mọi worker |
| RISK-027 | 🟠 | sutucon | HMAC service auth không ký body, không chống replay (60s window); Access JWT forward mà không verify; session không rotation | SDD-001 §6 thiết kế lại; không mang HMAC scheme sang |
| RISK-028 | 🟠 | sutucon | Media = base64 lưu trong D1 (≤200KB), IMAGES/R2 khai báo nhưng không dùng | SDD-009 Media Service (R2 + Cloudflare Images) |
4. Process & Hygiene
| ID | Sev | Repo | Rủi ro | Đối sách |
|---|---|---|---|---|
| RISK-014 | 🟠 | chuyenchon | Content ship dưới dạng migration SQL (15.9k LOC trộn DDL + data + repair scripts) | SDD-004 §3: content là data qua API/pipeline, không phải migration |
| RISK-015 | 🟠 | cả hai | Test = regex trên source text (29 files chuyenchon; 1 file sutucon) — vỡ khi refactor, không có safety net hành vi | QG-005/QG-009: behavior tests bắt buộc, cấm source-regex tests |
| RISK-016 | 🟠 | cả hai | Migration không idempotent (bare ALTER TABLE, DELETE destructive), áp tay ngoài CI; www migrations_dir trỏ thư mục không tồn tại | QG-004: migration idempotent, áp qua CI |
| RISK-029 | 🟡 | cả hai | Build junk + stale trees commit vào repo (dist-worker ×4, tmp 6.1M, backups gitignored, node_modules 2, 200 file evidence audit); repo đang mid-refactor chưa commit | .gitignore kỷ luật; không mang junk sang |
5. Tài sản đáng kế thừa (carry-overs)
| Tài sản | Nguồn | Dùng cho |
|---|---|---|
ARCHITECTURE-SUBSYSTEMS.md — mô hình 6 subsystem | chuyenchon docs | khớp module map SDD-001 §2 |
DATA-MODEL.md (bản aspirational normalized) + docs/requirements/ (actor catalog, use cases, user stories, traceability) | chuyenchon docs | PRD-001 §3–4 |
4 quality frameworks .mjs: CC-QAF-1.0, requirements-assessment, story-acceptance, learning-experience-quality | chuyenchon root | QG-002/QG-006 rubric gốc |
| TS knowledge graphs Toán/Văn/Anh (6.5k LOC) | chuyenchon app/lib | seed canonical graph (SDD-003) |
| Blueprint→experience→rubric content pipeline + 18 Workflows | mori | SDD-003/004 tham chiếu thiết kế |
| Evidence registry + idempotency key pattern; GSI id_token auth; onboarding data gates; 4F reflection engines; product submission rubric hóa; gateway hardening | sutucon | SDD-001/002/005; REQ-SCH-05 |
| Kiara docs set (PRD/SDD/ADR/DATA-MODEL/PRIVACY…) — cấu trúc tốt nhất trong legacy | sutucon kiara/docs | tham chiếu Marlins app |
| Octopus curriculum spec: 5 Academies × 16 courses, Future Lion Journey, ai-teen | sutucon docs | PRD Octopus (REQ-SCH-05) |
| Exam & school intelligence suite (kho đề, registry trường, workflows) | chuyenchon api+data | REQ-SCH-04 (Shark) |
| Tailwind v4 CSS-first toàn bộ (không cần migrate v3→v4) | cả hai | DS-001 |
6. Chiến lược migration (tóm tắt)
- Không đụng production cũ — hai hệ legacy tiếp tục chạy; Nemo12 xây trên tài nguyên mới hoàn toàn (D1/R2/Queues mới, zone nemo12.com).
- Docs-first: mọi capability legacy đáng giữ đi qua Feature Inventory → REQ → SDD → code mới. Không port code trực tiếp trừ tài sản thuần logic (graphs, frameworks, rubric content).
- Data migration (khi được yêu cầu): export từ legacy → transform (email→learner_id mapping, dedupe skill states) → import qua pipeline có kiểm chứng; giữ evidence provenance.
- Cutover từng school; redirect chuyenchon.com/sutucon.com sau khi Nemo12 ổn định (Q-055).