Skip to content

Bản đồ skill, và những gì cần nâng cấp ngoài skill ​

Rà soát toàn repo conanplatform ngày 04.09.2026. Hai phần: (1) hệ skill sau khi nâng cấp, (2) những thứ không phải skill mà rà soát này phát hiện, phần lớn thuộc loại hỏng mà hệ vẫn trông như đang chạy.

Phần 1: hệ skill: 14 → 21 ​

Đã có, đã sửa ​

Mười bốn skill cũ đúng về nội dung: mọi đường dẫn mã nguồn chúng nhắc tới đều còn tồn tại, số liệu (EMAIL_CATALOG 9 loại, PROMPT_VERSIONS ở arena.ts:77, chuẩn v2.3) đều khớp. Sửa tám liên kết hỏng ở cloud-dev và tool-plane, chúng trỏ docs.conan.school/... mà thiếu tiền tố ../../../, nên không link nào mở được. Đây là loại lỗi im lặng: skill vẫn đọc được, chỉ là mọi đường dẫn sâu hơn đều cụt.

Bảy skill mới ​

Vấn đề của hệ cũ: 7/14 skill phủ nội dung khoá học, còn toàn bộ api.conan.school/src, 20 domain, 193 migration, ba lớp danh tính, đường tiền, chỉ có deploy-migrate chạm tới, và chỉ ở khâu deploy. Bảy skill dưới đây lấp đúng phần đó.

SkillChỗ hỏng mà hệ vẫn trông như đang chạy
api-serviceapp.use khai sau app.route cùng tiền tố → route chạy bình thường, không qua gác nào, không log gì. Và hai họ bảng (legacy_* qua d1Client, không tiền tố qua SQL thô) cùng nằm trong một D1, viết nhầm họ thì câu lệnh hợp lệ, chỉ trả rỗng.
auth-accessTEST_MODE === 'true' là dòng đầu của authMiddleware và bỏ qua sạch mọi xác thực. Khoá toàn vẹn học tập (423) nằm trong đường xác thực, đường mới nào bỏ qua nó là cửa sau cho tài khoản đang khoá.
membership-paymentsAuto-duyệt chạy bằng khớp số điện thoại trong nội dung chuyển khoản, không phải OCR biên lai. Hai cửa vào (webhook ngân hàng / đơn người học) gặp nhau ở một bảng, sửa một cửa mà quên cửa kia là hai hành vi cho cùng một tình huống.
admin-portalTrang không khai vào nav.ts TAXONOMY thì build xanh và không URL nào dẫn tới nó. Router admin không khai DOMAIN_BY_PATH rơi về settings.manage → 403 cho tất cả trừ owner, trông y hệt lỗi phân quyền vô cớ.
mentors-albumsDanh sách mentor công khai từng là 5 slug viết cứng: admin thêm người mới, www vẫn hiện năm người cũ. Hai truy vấn lọc theo is_active, một cột không tồn tại: admin trả 500, còn misc/home trả mentors: [] với mã 200.
ci-guardsvite build không kiểm type. npm ci hỏng chỉ sinh warning nên CI vẫn xanh với phụ thuộc không ghim. Gác so nhánh mà thiếu fetch-depth: 0 thì xanh mà chưa kiểm gì.
docs-portalSidebar có hai chỗ phải khai; thiếu một chỗ là trang mồ côi và VitePress không cảnh báo.
play-gameRoute api.conan.school/play/* thắng api gateway nhờ độ cụ thể; làm nó kém cụ thể đi là 404 toàn bộ trong khi worker vẫn deploy xanh.

Sáu skill thêm sau đó (04.09 → 08.09.2026) ​

Bảng trên là ảnh chụp ngày 04.09. Bốn skill dưới đây thêm vào sau, và trang này đã không được cập nhật cùng lúc, chính là loại lệch tài liệu ↔ mã mà rà soát 08.09.2026 đi tìm.

SkillChỗ hỏng mà hệ vẫn trông như đang chạy
story-worldHai kho nằm cạnh nhau nhưng luật ngược nhau: content/brands/ là thương hiệu CÓ THẬT (bịa là sai sự thật), content/personas/ là nhân vật HƯ CẤU (bịa là mục đích). Lẫn chiều nào cũng ra nội dung trông hợp lý.
book-packSách mức 1 sinh xong nhưng không publish, nên kệ trông rỗng trong khi dữ liệu đã có đủ.
book-coversBìa đủ khối mà không kể chuyện vẫn qua mọi cửa kiểm; và vật tiền cảnh đặt lên mặt tủ tối trông như lơ lửng, chỉ thấy khi chụp ảnh ra nhìn.
book-illustrationsẢnh không lưu thành tệp nên không có gì trong repo để "nhìn": phải chạy preview mới thấy. Và vật thiếu NATURAL_TOP bị cắt đỉnh im lặng.
big-idea-auditMột tiêu chí chấm thô kéo điểm xuống mà không ai nghi: "trả lời được Essential Question" chấm bằng khớp chuỗi ra 16%, chấm đúng ra 74%. Và regex tách tuple SQL gãy ở context_json, bản đầu chỉ đọc 8/579 unit mà vẫn in ra một phần trăm trông bình thường.
course-coversSVG đọc từ D1 chèn thẳng vào DOM, hai bẫy nằm ở chỗ ĐỌC, không ở chỗ ghi. (Thế hệ trước; nay là đường lùi.)
course-artMinh hoạ khoá học ba khổ + bộ ảnh cộng đồng: phân cảnh trước khi vẽ, bốn màu token, prompt trong repo.
business-model-canvasGác Pro đặt ở giao diện thay vì ở API → tab BMC khoá bằng CSS, dữ liệu vẫn trả về đầy đủ cho mọi người.
jtbd-libraryNguồn sự thật là content/jtbd/*.json trong git, còn thứ CHẠY là migration, sửa JSON mà quên biên dịch thì repo trông đầy đủ, PR xanh, và trên tokyo không có gì đổi. Kèm tám khuôn Opportunity Gap, vì hai Set đầu đã rơi bốn trên năm vào cùng một khuôn.
i18n-wwwBản /en mở được và công tắc đổi được, nên nó trông như đã song ngữ trong khi phần lớn chữ vẫn tiếng Việt; và một <Link to> quên bọc localizePath ném người đọc về sai ngôn ngữ mà không lỗi gì.
playbook-packCái tên gợi ý một engine, nhưng KHÔNG có engine nào ghi vào seo_content_*: content-factory là hệ khác và router của nó chưa từng được mount (0 dòng). Và D1 có hai họ bảng seo_* giống nhau, ghi vào họ không tiền tố là câu lệnh hợp lệ mà site không bao giờ đọc tới.
seo-wwwcatch quanh một lời gọi mạng biến 500, 404 và sai hình dạng dữ liệu thành cùng một danh sách rỗng, mà giao diện của danh sách rỗng là "đang được cập nhật", thông điệp của một trang KHOẺ MẠNH. Bốn trang của www cùng rỗng theo khuôn đó. Và headers() ở route con thay thế header của root, gỡ sạch header bảo mật của đúng trang đó.

| live-workspace | Ba ranh giới quyền của phòng học trực tiếp (activity draft, đáp án đúng, hạn vote) đều là loại "sửa ở giao diện thì trông như đã xong": đáp án gửi xuống rồi ẩn bằng CSS vẫn nằm nguyên trong DevTools của mọi người học. |

Hệ skill hiện tại (29) ​

NhómSkill
Nội dung khoá học (16)course-content · course-pack · lesson-docs · course-seed · quality-rule · engine-prompt · content-ops-risks · learner-stories · story-world · book-pack · book-covers · book-illustrations · course-covers · course-art · playbook-pack · big-idea-audit
Nền tảng (11)deploy-migrate · design-system · emails · tool-plane · cloud-dev · api-service · auth-access · admin-portal · ci-guards · docs-portal · seo-www
Tính năng (6)communities · ran-assistant · membership-payments · play-game · business-model-canvas · live-workspace

Nguồn sự thật của con số này là ls .claude/skills/, mục "Skills" của CLAUDE.md và bảng này phải khớp với nó. Thêm skill thì sửa cả ba chỗ.

Tiêu chí đã dùng, để lần sau còn dùng lại ​

Skill đáng làm không phải skill mô tả mã nguồn, mã nguồn tự đọc được. Skill đáng làm là skill ghi lại một chỗ hỏng mà hệ vẫn trông như đang chạy. Bảy skill trên đều có ít nhất một; những ứng viên không có (một skill "dựng site mới", một skill "cách viết skill") thì chưa làm.

Phần 2: ngoài skill, cần nâng cấp gì ​

Xếp theo mức nghiêm trọng. Bốn mục đầu là quyết định của người soạn, không phải việc agent tự làm, nêu ra để quyết, không lặng lẽ sửa.

A. Cần quyết định ​

A1. Mã kích hoạt chạy trên mặc định cứng, mức cao. ĐÃ KIỂM 05.09.2026.platform_settings.membership_activation_codes không tồn tại trên production (truy vấn trả results: []), nên POST /api/user/membership/activate-code đang dùng mặc định cứng trong mã: ['1108'].

Đo tiếp cho thấy đây là kênh đang hoạt động thật, không phải lỗ hổng bị bỏ quên: 18 tài khoản kích hoạt bằng activation_code, rải liên tục từ 12.08.2026 tới 04.09.2026. Vậy nên không tự đổi mặc định, đổi là chặn đứng đường mà 18 người đã đi.

Bốn hệ quả của việc chạy trên mặc định cứng thay vì hàng cấu hình:

  1. Không xoay được mã nếu không deploy, mã lộ thì chỉ có một đường sửa là sửa mã nguồn.
  2. Không có rate limit trên endpoint; 1108 là một trong 10.000, dò được.
  3. Mã không hết hạn và không giới hạn số lượt dùng.
  4. Không có hàng cấu hình thì không có updated_by, không truy được ai đặt mã.

Đính chính 06.09.2026, bản đầu của trang này mô tả sai đường đi. Nó viết "ghi mã mới → xác nhận chạy → rồi mới gỡ mặc định cứng", hàm ý hai mã cùng sống một thời gian. Đọc lại mã nguồn thì không phải:

ts
const codes = (setting?.value ? setting.value.split(/[,\s]+/) : ['1108'])

Hàng cấu hình thay thế mặc định chứ không cộng thêm. Chỉ cần hàng tồn tại và có giá trị là 1108 ngừng hiệu lực ngay, không có giai đoạn chuyển tiếp. Vì 1108 đang lưu hành thật, ghi một mã mới mà không kèm nó sẽ chặn mọi người đang cầm mã cũ, im lặng.

Đường đi đúng: đặt giá trị là danh sách gồm cả hai, 1108, <mã mới> (ngăn bằng dấu phẩy hoặc khoảng trắng) → phát mã mới → khi đợt phát cũ kết thúc thì gỡ 1108 khỏi danh sách, chỉ là sửa một hàng, không cần deploy. Lúc đó "gỡ mặc định cứng trong mã nguồn" mới là việc an toàn.

Bẫy phụ: giá trị rỗng là falsy nên rơi ngược về ['1108'], xoá nội dung ô cấu hình không tắt mã cũ, nó bật lại mã cũ.

Bước rate limit đã làm 05.09.2026. Bảng membership_activation_code_attempts (migration 20260905za), 5 lượt sai / 15 phút cho mỗi tài khoản và 20 / 15 phút cho mỗi IP, kiểm trước khi so mã, chỉ đếm lượt sai. Hai bước còn lại vẫn cần người soạn: điểm 1 (mã lộ thì không xoay được) và điểm 3 (mã không hết hạn) chưa đóng.

A2. TEST_MODE không có gác, mức cao. ĐÃ LÀM 04.09.2026.wrangler.toml khai TEST_MODE = "false", đúng, nhưng nó là một [vars] thường, sửa một ký tự là mọi route bảo vệ mở toang và không script nào bắt. Đã thêm scripts/check-no-auth-bypass.mjs (quét mọi wrangler.toml, ngoại lệ duy nhất là wrangler.migration-smoke.toml) và nối vào job guards. Gác đã được kiểm cả chiều đỏ, không chỉ chiều xanh. Từ 03.10.2026 có thêm lớp thứ hai lúc chạy: src/shared/testModeGuard.ts làm api trả 500 TEST_MODE_IN_PRODUCTION cho mọi request khi cờ bật trên host api.conan.school hoặc ENVIRONMENT=production, phòng khi cờ đến từ secret hay dashboard chứ không qua wrangler.toml.

A3. play.conan.school mở ba chỗ, mức trung bình, có thể là cố ý. CORS app.use('*', cors()) không giới hạn origin; GET /api/debug/room/:pin trả trạng thái phòng cho ai đoán được PIN; tạo phòng và nối WebSocket không cần danh tính. wrangler.toml có ghi chú rằng chính sách Access "nên" gắn cho api.conan.school/play/*, chưa rõ đã gắn chưa. Với một trò chơi trong lớp thì có thể chấp nhận; siết mà không hỏi sẽ làm hỏng phòng đang chạy.

A4. Bí danh /api/community, nợ có hạn. Mounted song song /api/events với chú thích "gỡ khi mọi front-end chuyển xong". Cần một lượt kiểm xem front-end nào còn gọi, rồi đặt hạn gỡ. Để lâu thì hai đường phân kỳ ngầm.

B. Việc kỹ thuật rõ ràng, làm được ngay ​

B1. Job admin trong CI thiếu bước tsc. ĐÃ LÀM 04.09.2026. Chỉ chạy npm run build, mà vite build không kiểm type, đúng cái lỗi mà chính file workflow đó ghi lại ngày 03.09.2026, còn sót ở một job. Đã thêm bước npm run typecheck chạy trước build; chạy thử tại chỗ, hiện xanh (tsc -b, exit 0).

B2. Năm site không có job CI nào.play, mam, video, mentors, docs không xuất hiện trong ci-checks.yml. PR sửa chúng không được kiểm gì cả. Ưu tiên play (có worker, có DO) và docs (build VitePress hỏng là mất cổng tài liệu).

B3. Hình dạng lỗi API có hai loại. Chuẩn là errorResponse() (code + message, ánh xạ status trong app.onError). Nhưng middlewares/tenant.ts trả c.json({ error: … }, 400) và domains/user/membership.ts trả { error } cho 404/409/422. Front-end đọc code sẽ không thấy gì. Việc dọn nhỏ, nên làm cùng lúc để không sinh loại thứ ba.

B4. npm ci hỏng chỉ là warning. Mọi job dùng npm ci || { echo "::warning::…"; npm install; }. Lockfile lệch không làm đỏ CI, job vẫn xanh, chỉ khác là dựng bằng phiên bản không ghim. Hiện play.conan.school/frontend/package-lock.json đang có thay đổi chưa commit, đúng loại lệch này. Đề nghị: giữ fallback nhưng nâng warning thành lỗi cho các job có deploy tương ứng.

B5. video.conan.school chưa có Tailwind. Chép token màu bằng tay. Đã ghi trong CLAUDE.md là nợ, không phải ngoại lệ (rà soát 03.09.2026) và vẫn còn nguyên. Đổi --color-primary không lan tới site này.

C. Không phải vấn đề (đã kiểm, để khỏi kiểm lại) ​

  • node_modules/ và dist/ không bị theo dõi trong git (0 file). Dung lượng thư mục lớn là do đĩa làm việc, không phải do repo.
  • Mọi đường dẫn mã nguồn được 14 skill cũ nhắc tới đều còn tồn tại.
  • Các số liệu trong skill cũ đều khớp mã hiện tại.

Việc kế tiếp, nếu chọn làm ​

A2 và B1 đã làm 04.09.2026; A1 đã kiểm 05.09.2026 và cần người soạn quyết (ghi mã mới vào platform_settings trước, đừng đổi mặc định trước). Còn lại theo thứ tự chi phí/lợi ích: B2 (job CI cho play và docs) → B3 (dọn hình dạng lỗi) → B4/B5 → A3/A4.

Rủi ro nào trong số trên xảy ra thật thì ghi vào sổ rủi ro, không ghi vào trang này, trang này là ảnh chụp một lượt rà soát.

Tài liệu nội bộ nền tảng Conan School.