PRD 12 · Yêu cầu phi chức năng
Hiệu năng, bảo mật, tuân thủ bảo vệ dữ liệu cá nhân theo Nghị định 13/2023/NĐ-CP, kiểm soát truy cập theo vai trò, nhật ký, sao lưu, bản địa hoá và khả năng tiếp cận. Các yêu cầu này áp dụng cho mọi mô-đun và là tiêu chí chấp nhận để phát hành.
Xuất xứ / Prompt / Giới hạn
Tài liệu do trợ lý AI soạn trong một phiên làm việc ngày 10/09/2026, theo yêu cầu gốc được trích nguyên văn ở trang mục lục; mục Thiết kế đề xuất được bổ sung ngày 16/09/2026. Đây là bản đề xuất để đội thảo luận, chưa phải quyết định của đội sản phẩm.
Nguồn
- Nghiên cứu công khai về đối thủ cạnh tranh (PSE ONE, pse4.one), mã nguồn
center-crm-frontendvà đặc tả OpenAPI/v3trên staging (182 endpoint), tính đến ngày 10/09/2026.
Giới hạn
- Cần xác minh khi khảo sát trực tiếp trong ứng dụng, vì đăng nhập tự động vào sản phẩm tham chiếu chưa được cấp phép trong phiên soạn:
- Cách đối thủ xử lý khả năng xem dữ liệu theo từng chi nhánh cho một người dùng quản lý nhiều chi nhánh (bộ chuyển đổi hay giao diện gộp).
- Liệu nhật ký thao tác của họ có hiển thị cho tenant hay chỉ dành cho đội hỗ trợ của họ.
- Những gì họ trình bày là "sao lưu hằng ngày" với khách hàng (tự khôi phục hay phải gửi ticket).
- Hành vi hết phiên đăng nhập và liệu số lượt đăng nhập đồng thời có bị giới hạn theo gói bản quyền hay không.
Thiết kế đề xuất
PRD này không có màn hình riêng: nội dung là nền tảng dùng chung. Thiết kế của từng tính năng nằm ở mục "Thiết kế đề xuất" đầu mỗi PRD mô-đun (00 đến 10 và 13 đến 19).
1Mục đích và phạm vi
Trường Số xử lý dữ liệu cá nhân của trẻ em, số điện thoại của phụ huynh và tiền bạc. Tài liệu này quy định mức tối thiểu cho cách sản phẩm vận hành dưới tải, cách sản phẩm bảo vệ dữ liệu, và cách sản phẩm chứng minh ai đã làm gì. Tài liệu bao quát ứng dụng web (Next.js 16 trên Cloudflare Pages / Node), API Rust của FLYER (/v3), gateway GraphQL v2, dịch vụ tải tệp lên, và các tích hợp thông báo (Zalo OA / ZNS, email, trong ứng dụng). Tài liệu không bao quát các ứng dụng người học của FLYER (exam.flyer.us, study.flyer.us) ngoài phạm vi ranh giới định danh.
2Hiệu năng và năng lực
| Chỉ số | Mục tiêu | Cách đo |
|---|---|---|
| Quy mô tenant được hỗ trợ | Tối đa 5 chi nhánh, 3.000 học viên đang học, 300 lớp học, 150 nhân sự cho mỗi tenant mà giao diện không bị suy giảm | Tenant staging đã tạo sẵn dữ liệu mẫu "Big Center" |
| Các trang danh sách (học viên, học phí, điểm danh) | Thời gian đến khi tương tác được (time to interactive) ≤ 2,0 giây trên laptop tầm trung đời 2023 qua mạng 4G; p95 API ≤ 400 ms cho trang 50 dòng | Playwright trace + p95 API từ log gateway |
| Tổng quan (PRD 09) | p95 ≤ 1,5 giây với 12 widget; các widget tải độc lập, mỗi widget có khung skeleton riêng | Tương tự |
| Điểm danh (PRD 04) | Lưu một buổi điểm danh 30 học viên ≤ 300 ms p95; giao diện optimistic, thử lại khi thất bại | API p95 |
| Nhập từ Excel (PRD 11) | 5.000 dòng được kiểm tra hợp lệ trong ≤ 60 giây; tác vụ chạy bất đồng bộ kèm tiến độ; giao diện không bao giờ bị chặn | Mẫu tác vụ /v3/crm/imports đã có sẵn |
| Sinh thời khoá biểu (PRD 03) | Sinh 200 buổi học cho một lớp ≤ 2 giây; kiểm tra trùng lịch cho một chi nhánh theo tuần ≤ 500 ms | Đo thời gian API |
| Thông báo hàng loạt (PRD 07) | 1.000 tin nhắn ZNS được đưa vào hàng đợi trong ≤ 10 giây; việc gửi diễn ra bất đồng bộ và báo cáo theo từng người nhận | Số liệu hàng đợi |
| Xuất dữ liệu | CSV/XLSX tối đa 50.000 dòng được tạo phía server và gửi dưới dạng liên kết tải xuống trong vòng 60 giây | Trạng thái tác vụ |
| Khả dụng | 99,5% hằng tháng cho ứng dụng web và API trong khung giờ 06:00–23:00 giờ Việt Nam; các khung bảo trì được thông báo trước 48 giờ ngay trong ứng dụng | Giám sát uptime qua /api/health |
| Bundle | JS ban đầu cho route dashboard ≤ 350 KB đã nén gzip; chia tách code theo từng route ở cấp mô-đun | Kết quả next build |
Quy tắc thiết kế
- Mọi endpoint danh sách đều được phân trang (
page,limit≤ 200) và lọc phía server; không lọc phía client trên toàn bộ tập dữ liệu. - Các số liệu tổng hợp được đọc thường xuyên (tồn kho, số dư học viên, tỷ lệ điểm danh) được lưu dưới dạng bảng tổng hợp được duy trì, không tính lại ở mỗi lượt đọc.
- Các thao tác kéo dài (nhập liệu, xuất dữ liệu, thông báo hàng loạt, sinh thời khoá biểu) là các tác vụ có kiểm tra trạng thái định kỳ; mẫu này đã có sẵn cho
ImportJob. - ISR/caching không được dùng cho dữ liệu của tenant; mọi lượt đọc dữ liệu tenant đều theo từng request kèm auth token.
3Bảo mật
Xác thực
- Nhân sự đăng nhập bằng tài khoản FLYER (email hoặc số điện thoại + mật khẩu, OTP cho số điện thoại) như hiện tại; token phiên đăng nhập được gửi qua header
Auth Tokenđã có sẵn thông qua proxy/api/v3của ứng dụng để token không bao giờ đến được các origin bên thứ ba. - Token hết hạn sau 30 ngày không hoạt động; đổi mật khẩu sẽ thu hồi toàn bộ các phiên đăng nhập khác.
- Vai trò chủ trung tâm và kế toán phải bật yếu tố xác thực thứ hai (OTP qua số điện thoại hoặc TOTP) trước khi truy cập mục xuất dữ liệu Tài chính và Cài đặt → Người dùng. Giai đoạn P2.
- Phụ huynh xác thực trên cổng phụ huynh chỉ bằng OTP qua số điện thoại; không có mật khẩu. Mỗi mã OTP có hiệu lực 5 phút, tối đa 5 lần thử.
Phân quyền
- Mọi request đều được giới hạn phạm vi theo tenant (
school_id/center_id) được xác định từ token, không bao giờ từ một id do client cung cấp. Id thuộc tenant khác trả về 404, không phải 403. - Mã quyền (PRD 10) được kiểm tra phía server cho từng endpoint; giao diện ẩn các điều khiển nhưng không bao giờ chỉ dựa vào việc ẩn đó để đảm bảo an toàn.
- Phạm vi chi nhánh: người dùng mang theo một danh sách id chi nhánh; các dòng dữ liệu mang
branch_id; các endpoint danh sách tự động áp dụng phần giao giữa hai danh sách đó. - Giáo viên chỉ thấy các lớp được phân công và học viên trong các lớp đó; phụ huynh chỉ thấy các tài khoản người học đã được liên kết.
Bảo mật ứng dụng
- Dùng OWASP ASVS cấp độ 2 làm checklist. Kiểm tra dữ liệu đầu vào trên API bằng schema có kiểu dữ liệu (đã theo hướng OpenAPI).
- Tải tệp lên: danh sách cho phép các loại MIME (pdf, jpg, png, xlsx, docx), 20 MB cho mỗi tệp, quét virus trước khi phục vụ, bucket riêng tư với URL có chữ ký hiệu lực 15 phút.
- Giới hạn tần suất: 60 request ghi/phút cho mỗi người dùng, 10 request OTP/giờ cho mỗi số điện thoại, khoá 15 phút sau 5 lần đăng nhập thất bại.
- Secret (token Zalo OA, khoá SePay, thông tin xác thực nhà cung cấp hoá đơn điện tử) được lưu mã hoá theo từng tenant; không bao giờ trả về cho client sau khi lưu (chỉ hiển thị 4 ký tự cuối).
- CSP, HSTS, cookie SameSite=Lax, không có script bên thứ ba chèn trực tiếp (inline) trên các trang đã đăng nhập.
- Quét dependency hằng tuần; các CVE nghiêm trọng được vá trong vòng 7 ngày.
4Bảo vệ dữ liệu cá nhân (Nghị định 13/2023/NĐ-CP)
Trường Số xử lý dữ liệu cá nhân cơ bản (họ tên, ngày sinh, số điện thoại, địa chỉ) và dữ liệu cá nhân nhạy cảm của trẻ em dưới 16 tuổi (ghi chú sức khoẻ, nếu có nhập). Trung tâm là bên kiểm soát dữ liệu; FLYER là bên xử lý dữ liệu. Sản phẩm phải giúp bên kiểm soát dữ liệu dễ dàng thực hiện các nghĩa vụ liên quan.
| Nghĩa vụ | Yêu cầu sản phẩm | Mô-đun |
|---|---|---|
| Sự đồng ý của chủ thể dữ liệu hoặc người giám hộ (Điều 11) | Biểu mẫu nhập học và luồng khởi tạo tài khoản trên cổng phụ huynh ghi nhận một bản ghi đồng ý (id phiên bản nội dung, thời gian, kênh, danh tính phụ huynh). Nội dung đồng ý có thể chỉnh sửa theo từng tenant, kèm nội dung mặc định của FLYER. Có thể thu hồi từ cổng phụ huynh và bởi nhân sự. | 02, 07 |
| Dữ liệu của trẻ em (Điều 20) | Bản ghi học viên lưu sự đồng ý của phụ huynh trước khi gửi bất kỳ thông báo nào trực tiếp cho trẻ; sản phẩm không bao giờ nhắn tin trực tiếp cho một học viên dưới 16 tuổi, chỉ gửi cho phụ huynh. | 02, 07 |
| Giới hạn mục đích sử dụng | Các trường dữ liệu được nhóm theo mục đích trong tài liệu schema (PRD 11) và nội dung đồng ý liệt kê các mục đích: nhập học, điểm danh, tính phí, báo cáo học tập, marketing (đồng ý riêng). | 11 |
| Quyền truy cập và chỉnh sửa (Điều 9) | Cổng phụ huynh hiển thị toàn bộ dữ liệu đã lưu về người học và phụ huynh, và cho phép gửi yêu cầu chỉnh sửa, yêu cầu này trở thành một công việc cho giáo vụ. | 07 |
| Quyền yêu cầu xoá dữ liệu | Nhân sự có thể ẩn danh hoá một học viên và phụ huynh (tên đổi thành "Học viên đã xoá", số điện thoại/email được xoá, tài liệu bị xoá) trong khi vẫn giữ lại bản ghi tài chính theo thời hạn luật định 10 năm. Hành động này cần quyền students.anonymise và được ghi vào nhật ký. | 02, 10 |
| Hồ sơ xử lý dữ liệu và đánh giá tác động (Điều 24) | FLYER duy trì hồ sơ xử lý dữ liệu; quản trị viên tenant có thể tải một mẫu "Hồ sơ đánh giá tác động" đã điền sẵn từ Cài đặt. | 10 |
| Thông báo sự cố (72 giờ) | Quy trình xử lý sự cố (runbook) kèm mẫu email thông báo cho tenant; nhật ký hỗ trợ xác định phạm vi các tenant bị ảnh hưởng. | Nền tảng |
| Chuyển dữ liệu xuyên biên giới | Lưu trữ chính tại ap-southeast-1 (Singapore) là một lượt chuyển dữ liệu xuyên biên giới; hợp đồng với tenant và nội dung đồng ý có công bố điều này. Lộ trình: tuỳ chọn khu vực Việt Nam cho các tenant doanh nghiệp. | Nền tảng |
| Lưu trữ dữ liệu | Lead (PRD 01) không được chuyển đổi trong vòng 24 tháng sẽ tự động bị ẩn danh hoá; dữ liệu điểm danh và học tập được giữ trong suốt thời gian học viên còn đang học cộng thêm 5 năm; chứng từ tài chính giữ 10 năm. | 01, 05 |
Sự đồng ý nhận marketing tách biệt với sự đồng ý sử dụng dịch vụ. Các biểu mẫu ghi nhận lead phục vụ PRD 01 phải có một ô tick riêng cho marketing; bản ghi lead lưu marketing_consent_at.
5Kiểm soát truy cập theo vai trò
Ma trận đầy đủ nằm ở PRD 10. Các quy tắc ở cấp nền tảng gồm:
- Quyền là các chuỗi
<module>.<action>, được cung cấp quaGET /v3/crm/permissions-catalog(EXISTING cho CRM; mở rộng thêm các mô-đun mới). Vai trò là các gói quyền do tenant tự định nghĩa; FLYER cung cấp sẵn các vai trò mặc định không thể xoá nhưng có thể nhân bản. - Quyền có hiệu lực = hợp của các quyền trong vai trò, giao với phạm vi chi nhánh và với các quy tắc sở hữu bản ghi (giáo viên với lớp được phân công, tư vấn viên với lead được phân công).
- Vai trò chủ trung tâm không thể bị gỡ khỏi chủ trung tâm cuối cùng; chuyển quyền sở hữu là một hành động tường minh kèm xác nhận qua email.
- Các sự kiện nâng quyền (đổi vai trò, chỉnh sửa quyền, đổi phạm vi chi nhánh) được ghi vào nhật ký và người dùng bị ảnh hưởng được thông báo ngay trong ứng dụng.
6Nhật ký
CRM hiện đã cung cấp GET /v3/crm/customers/{id}/audit-logs cho một đối tượng. Yêu cầu ở cấp nền tảng tổng quát hoá điều này cho toàn bộ hệ thống.
| Trường | Kiểu dữ liệu | Ghi chú |
|---|---|---|
| id | uuid | |
| tenant_id, branch_id | int64 / uuid | |
| actor_user_id, actor_display_name, actor_role_code | ảnh chụp tại thời điểm thực hiện hành động | |
| action | text | student.update, tuition.pay, attendance.mark, role.permissions.put ... |
| entity_type, entity_id | text, text | |
| before, after | jsonb | chỉ các trường đã thay đổi; các trường liên quan đến tiền và trạng thái luôn được bao gồm |
| ip, user_agent | text | |
| request_id | text | liên kết với log API |
| created_at | timestamptz | không thể chỉnh sửa; bảng chỉ cho phép ghi thêm (append-only), không cấp quyền UPDATE/DELETE |
- Lưu trữ 5 năm; chủ trung tâm có thể xuất theo từng tenant dưới dạng CSV.
- Các hành động bắt buộc phải ghi nhật ký: mọi thao tác ghi vào tài chính (tạo, thanh toán, huỷ, hoàn tiền, giảm giá), chỉnh sửa điểm danh sau ngày diễn ra buổi học, thay đổi trạng thái học viên, thay đổi thông tin liên hệ phụ huynh, thay đổi quyền và vai trò, xuất dữ liệu cá nhân, đăng nhập từ một thiết bị mới.
- Màn hình xem: Cài đặt → Nhật ký (PRD 10) kèm bộ lọc người thực hiện, hành động, đối tượng, ngày; mỗi dòng mở rộng thành bảng so sánh trước/sau.
7Sao lưu, khôi phục và khả năng chuyển dữ liệu
- Postgres: lưu trữ WAL liên tục, khôi phục về bất kỳ thời điểm nào trong vòng 14 ngày gần nhất (point-in-time recovery); snapshot đầy đủ hằng đêm giữ 35 ngày; snapshot hằng tháng giữ 12 tháng.
- Lưu trữ đối tượng (tài liệu, PDF phiếu thu): bucket có quản lý phiên bản, xoá mềm trong 30 ngày.
- Mục tiêu khôi phục: RPO 5 phút, RTO 4 giờ cho sự cố mất toàn bộ khu vực (region); kiểm thử hai lần một năm kèm báo cáo bằng văn bản.
- Xuất dữ liệu tenant: chủ trung tâm có thể yêu cầu xuất toàn bộ dữ liệu (CSV cho từng đối tượng cộng với file zip tài liệu) từ Cài đặt; được tạo trong vòng 24 giờ dưới dạng liên kết tải xuống có chữ ký; đây cũng là sản phẩm bàn giao theo hợp đồng khi kết thúc sử dụng dịch vụ.
- Xoá tenant: có 30 ngày gia hạn sau khi hợp đồng kết thúc, sau đó xoá vĩnh viễn kèm chứng nhận khi có yêu cầu.
8Bản địa hoá (vi / en)
- Ứng dụng hỗ trợ hai locale qua next-intl:
vi(mặc định, giao diện sản phẩm) vàen. Mọi chuỗi mới được thêm vào cảsrc/i18n/messages/vi.jsonvàen.jsondưới namespace của mô-đun tương ứng; một bước kiểm tra CI sẽ làm build thất bại khi hai bộ key không khớp nhau. - Nhãn từ API (trạng thái, nhãn quyền, thông báo lỗi) tuân theo header
X-Locale, giống như các endpoint hiện có đã làm. - Ngày hiển thị theo định dạng
dd/MM/yyyy, giờ theoHH:mm24 giờ, múi giờ Asia/Ho_Chi_Minh mặc định theo từng tenant; lưu trữ theo UTC. - Tiền tệ: VND không có phần thập phân, dấu phân cách hàng nghìn là "." trong locale vi và "," trong locale en; ký hiệu "đ" đặt sau số trong locale vi.
- Tên tiếng Việt: thứ tự hiển thị là "Họ Tên" theo đúng như đã nhập; sắp xếp dùng collation theo locale (ICU vi) để "Đ" và "D" được xếp thứ tự đúng, và dấu được bỏ qua khi tìm kiếm.
- Số điện thoại được chuẩn hoá theo E.164 (
+84...) khi lưu; hiển thị dưới dạng0xxx xxx xxx. - Từ điển thuật ngữ giao diện tiếng Việt (liên kết ở trang chủ) là nguồn tham chiếu chính thức cho các nhãn; nội dung sản phẩm dùng ngôn ngữ trang trọng (Quý phụ huynh, học viên, giáo viên).
9Khả năng tiếp cận và hỗ trợ thiết bị
- Đạt WCAG 2.1 AA cho giao diện web của nhân sự: độ tương phản ≥ 4.5:1 (bảng màu Cloud đạt chuẩn với màu chữ #212B36 trên nền trắng và #637381 cho chữ phụ), vòng focus hiển thị rõ, mọi thao tác truy cập được bằng bàn phím, bảng biểu có header đúng chuẩn, biểu mẫu có nhãn và thông báo lỗi liên kết qua
aria-describedby. - Trạng thái không bao giờ chỉ thể hiện qua màu sắc; chip điểm danh luôn kèm chữ (Có mặt / Muộn / Vắng / Có phép) và một biểu tượng.
- Kích thước màn hình tối thiểu được hỗ trợ là 1280 px cho console của nhân sự; luồng điểm danh của giáo viên và cổng phụ huynh ưu tiên di động (360 px) và có thể cài đặt như một PWA. Ứng dụng di động gốc không nằm trong phạm vi giai đoạn P1.
- Trình duyệt: hai phiên bản gần nhất của Chrome, Edge, Safari, Firefox; trình duyệt tích hợp của Zalo cho các liên kết gửi phụ huynh.
- Cỡ chữ tuân theo Cloud theme (13,5 px cho bảng dày đặc, 15,5 px cho tài liệu); công tắc "Cỡ chữ lớn" ở cấp tenant phóng to console lên 110%.
10Giám sát và vận hành
- Log có cấu trúc kèm
tenant_id,user_id,request_id; không có dữ liệu cá nhân trong log (số điện thoại và tên được che). - Theo dõi lỗi ở phía front end kèm source map; lỗi hiển thị cho người dùng có kèm một mã ngắn (ví dụ
TS-4021) để bộ phận hỗ trợ tra cứu. - Các sự kiện phân tích sản phẩm được liệt kê trong từng PRD được gửi đến pipeline phân tích đã có sẵn kèm
tenant_idvà vai trò; không có dữ liệu cá nhân của học viên trong payload sự kiện. - Endpoint kiểm tra sức khoẻ hệ thống
/api/healthkiểm tra database, hàng đợi và lưu trữ đối tượng. - Cờ tính năng theo từng tenant (theo mẫu
GET /v3/teacher/feature-configsđã có sẵn) kiểm soát việc mở các mô-đun giai đoạn P2: điểm danh, tài chính v2, nhân sự, kho, cổng phụ huynh.
11Checklist nghiệm thu trước khi phát hành
- Các mục tiêu hiệu năng ở mục 2 đạt được trên tenant "Big Center" đã tạo sẵn dữ liệu mẫu, số liệu được ghi lại trong release note.
- Bảo mật: quét dependency tự động không còn lỗi nghiêm trọng; kiểm tra thủ công tính cách ly giữa các tenant trên từng endpoint mới (thử id thuộc tenant khác phải trả về 404).
- Bảo vệ dữ liệu cá nhân: có ghi nhận sự đồng ý ở mọi điểm nhập dữ liệu mới cho phụ huynh và học viên; luồng ẩn danh hoá đã được kiểm thử.
- Nhật ký: mọi hành động bắt buộc ở mục 6 đều ghi một dòng nhật ký; đã xác minh theo kế hoạch kiểm thử (xem Kế hoạch kiểm thử).
- i18n: bộ key của vi và en giống hệt nhau; đính kèm ảnh chụp màn hình của cả hai locale.
- Khả năng tiếp cận: chạy axe không còn lỗi nghiêm trọng nào trên các màn hình chính của mô-đun; đã ghi lại việc thao tác thử bằng bàn phím.
- Sao lưu: diễn tập khôi phục snapshot của tuần phát hành thành công trên staging.
Trường Số (truongso.net) · Nội bộ FLYER