What's New: SDD
Luồng
api.conan.school/content/whats-new/2026-W41.json nguồn sự thật, viết tay, song ngữ
-> scripts/whats-new-draft.mjs sinh nháp từ PR đã merge (COMM-WN-04)
-> api.conan.school/scripts/whats_new_to_sql.py --check + biên dịch ra SQL
-> api.conan.school/migrations/*_whats_new_*.sql CI áp TRƯỚC deploy
-> D1 whats_new_entries
-> GET /api/public/whats-new gom theo tuần, lọc audience Ở ĐÂY
-> www.conan.school/app/routes/whats-new.tsx SSR, không cookie, chỉ thấy public
-> com.conan.school/app/routes/whats-new.tsx cùng origin, có cookie, thấy public + memberThành phần
| Thành phần | File | Ghi chú |
|---|---|---|
| Nội dung | api.conan.school/content/whats-new/YYYY-Www.json | Hiện có 2026-W41.json. Trường: week, entries[] (key, audience, category, published_at, url, title{vi,en}, description{vi,en}), retired[]. |
| Nháp | scripts/whats-new-draft.mjs | Đọc PR đã merge trong tuần ISO, để TODO ở mọi chỗ cần người viết. |
| Biên dịch | api.conan.school/scripts/whats_new_to_sql.py | --check từ chối TODO, thiếu audience, url không tuyệt đối, gạch dài. id là uuid5 của week/key. |
| Bảng | migration 20261106a_whats_new.sql | whats_new_entries(id, week_key, entry_key, audience CHECK IN ('public','member'), category, title, title_en, description, description_en, url, published_at, sort_order, is_active, ...), UNIQUE(week_key, entry_key). Dữ liệu: 20261106b, 20261106c. |
| API | api.conan.school/src/domains/public/whatsNew.ts | Hai route: GET / (gom theo tuần, trả audience, latest_week, weeks) và GET /latest. optionalAuthMiddleware khai trên chính router này vì router public mount trước optionalAuth của src/index.ts. |
| Cache | cùng file, setCacheHeaders | Thành viên: private, no-store. Khách: public, max-age=300 kèm Vary: Cookie. |
| www | www.conan.school/app/routes/whats-new.tsx | Khai trong PAGES của app/routes.ts, nên có cả /en/whats-new. |
| tokyo | com.conan.school/app/routes/whats-new.tsx, com.conan.school/app/lib/whats-new.ts | Chấm chưa đọc: so latest_week với localStorage['conan.whatsNew.lastSeenWeek']. |
| Ran | api.conan.school/src/workflows/ran-knowledge-index.ts | Đọc whats_new_entries (kind whats_new) vào chỉ mục. |
Quyết định thiết kế
- Bảng mới thay vì
changelogs. Hai bảng changelog cũ (legacy_changelogs,changelogs) đều rỗng và không xác minh được cả hai tồn tại trên production;ALTERvào bảng không tồn tại làm hỏng lượt áp migration, mà migration chạy trước deploy. - Ranh giới audience ở API, không ở giao diện: trang www không lọc gì.
- Mốc đã đọc ở localStorage là cố ý: mất mốc thì chấm hiện lại một lần, không hỏng gì.
Phụ thuộc
- Notifications: chưa có. What's New không đi qua email hay in-app inbox; chấm chưa đọc là tín hiệu in-app duy nhất, và nó sống ở máy khách. Xem in-app.