Skip to content

SDD — System Design Document

Thiết kế hệ thống cho tokyo.conan.school. Trả lời "làm thế nào" cho các yêu cầu trong Requirements. Trạng thái: v1.0 · Nguyên tắc nền tảng: Cloudflare-only.

1. Tổng quan kiến trúc

Tokyo là một ứng dụng React Router (framework mode) phục vụ qua Cloudflare Pages, gọi backend api.conan.school (Cloudflare Workers) qua same-origin /api proxy để giữ cookie phiên member. Dữ liệu sống nằm hoàn toàn trên Cloudflare D1.

Ánh xạ triển khai: thư mục com.conan.school/ → Cloudflare Pages project conan-com → phục vụ cả com.conan.schooltokyo.conan.school. Proxy /api cùng origin chuyển tiếp cookie member tới api.conan.school.

2. Thành phần

Thành phầnCông nghệVai trò
Tokyo UIReact Router 7, ViteRender trải nghiệm Builder; route theo app/routes/*
HostingCloudflare Pages (conan-com)Phục vụ static + SSR/edge
APICloudflare Workers (api.conan.school)Auth, dữ liệu khóa học, membership
DatabaseCloudflare D1Nguồn dữ liệu sống duy nhất
WorkflowCloudflare WorkflowsĐối soát chuyển khoản → kích hoạt paid
AI phụWorkers AI (@cf/llava-1.5-7b-hf)OCR biên lai best-effort (không phải nguồn sự thật)

3. Mô hình dữ liệu — Course Information

Mô hình khóa học là additive: bảng mới đặt cạnh courses hiện có, không phá pipeline curriculum/quiz cũ.

Cấu trúc phân cấp

Course → Unit → Learning Experience → Activity

Chạy song song: Concepts · Capabilities · Artifacts · Assessments · Capstone.

Thực thể chính

Thực thểKhóa/quan hệTrường tiêu biểu
Coursegốcid, slug, title, subtitle, description, status, version; clarity_question, core_problem, promise, course_outcome; clarity_area, course_kind, difficulty, target_audience
Concept (course-owned)course_idname, definition, description, sort_orderkhông dùng chung
Capability (course-owned)course_idname, description, target_level, sort_order
Unitcourse_idunit_number, title, subtitle, unit_question, description, unit_outcome
Learning Experienceunit_idtitle, description, experience_type, expected_output
Activitytrong LEbước nhỏ (MVP: tùy chọn)
Artifactcourse_id/unit_idname, description, artifact_type
Capstonecourse_idtitle, description, outputs[]
Assessment/Rubriccourse_idtiêu chí có trọng số (course_rubric_criteria)
ReflectionUnitreflection_prompt

Enum quan trọng:

  • clarity_areaLEARN_THINK · UNDERSTAND · CHOOSE_CREATE · COMMUNICATE_SELL · BUILD
  • course_kindFOUNDATION · CORE · APPLIED · STUDIO
  • experience_typeCASE · INQUIRY · READING · DISCUSSION · INTERVIEW · OBSERVATION · SIMULATION · WRITING · BUILD · CRITIQUE · REFLECTION · ASSESSMENT
  • assessmentDIAGNOSTIC · FORMATIVE · SUMMATIVE · CAPSTONE · PEER_REVIEW · SELF_REFLECTION

Quy tắc cứng: Concepts thuộc đúng một Course. Không có bảng concept global many-to-many. Nhờ vậy mỗi khóa tự chứa ngữ nghĩa, sửa/xóa không ảnh hưởng khóa khác.

Lưu ý D1 legacy: client D1 của api.conan.school tiền tố nhiều bảng bằng legacy_. Tuy nhiên nhóm Course Information dùng bảng không tiền tố (courses, course_concepts, course_enrollments, users) — hai họ bảng cùng tồn tại; migration raw-SQL phải nhắm đúng họ bảng.

4. Membership & Trial — thiết kế

Suy diễn nhóm quyền (tại request time)

isPaidTier(tier) = tier != null && lower(trim(tier)) != 'free'

group =
  paid   nếu isPaidTier(membership_tier)
  trial  nếu (không paid) và now < trial_expires_at
  free   nếu (không paid) và (trial thiếu hoặc hết hạn)

Nguồn: users.membership_tier, users.trial_started_at, users.trial_expires_at. Trả cho frontend qua /api/user/me: profile.entitlement_group, trial_expires_at, trial_days_left.

Lazy-init trial

Ở request xác thực đầu tiên khi chưa paid và trial_started_at IS NULL: trial_started_at = now, trial_expires_at = now + 7 ngày. Idempotent — thao tác chỉ đặt khi còn NULL.

Kích hoạt trả phí (Workflow — phone match)

OCR biên lai (@cf/llava-1.5-7b-hf) chỉ là bằng chứng phụ. Model @cf/meta/llama-3.2-11b-vision-instruct bị license-gate (5016) nên không nằm trên đường kích hoạt tự động.

5. Xác thực & phiên

  • Đăng nhập qua /login/auth/callback; đăng xuất /logout.
  • Cookie phiên HttpOnly + Secure, gửi kèm qua same-origin /api.
  • Phân quyền thực thi ở backend theo entitlement_group; UI chỉ ẩn/hiện.

6. Cấu trúc route (frontend)

Route nằm ở com.conan.school/app/routes/* (React Router). Nhóm chính: học tập (courses, my-courses, my-journey, concepts), thực hành (challenges, battles, workshops, programs, classes), sản phẩm (portfolio, *-brands, brand-model), cộng đồng (events, online-events, insiders, feedback, calendars, affiliate), tiến bộ (score, badges, member-intelligence, membership, profile, portrait). Bản đồ đầy đủ: Bản đồ tính năng.

7. Deploy & CI/CD

  • Trigger: push main → GitHub Actions (path-filter theo thư mục app).
  • Cơ chế: workflow per-app gọi reusable _deploy-cloudflare.yml, chạy wrangler pages deploy với Cloudflare API token.
  • Docs site này: app_dir docs.conan.school, build npm run build (VitePress), output .vitepress/dist, Pages project docs-conan-schooldocs.conan.school.

8. Ràng buộc & invariant

  • Cloudflare-only: không thêm phụ thuộc Supabase mới (có kiểm tra tự động check:cloudflare-only).
  • Same-origin API: UI không gọi thẳng api.conan.school cross-origin cho hành động cần cookie.
  • Course Information additive: không sửa phá pipeline curriculum/quiz cũ.
  • Concepts course-owned: tuyệt đối không global.

9. Liên kết

Cập nhật lần cuối:

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