Giao diện
US-P02: Truy cập tool đang bật / ẩn / khoá (mở khoá bằng mã bí mật) ​
Thuộc FS: 00-overview.md — Nền tảng dùng chung của cụm tool SAPP (as-built @
e77c47a) Phần chung (tổng quan, roles, flow tổng, related features, NFR, Open Questions, References) xem ở Overview. File này chỉ chứa nội dung riêng của US.
| Field | Value |
|---|---|
| US ID | US-P02 |
| Role thực hiện | R1 - Người dùng tool — Assumption (OQ về G-01), xem OQ-P-13 |
| Phase | As-built (đã triển khai) |
| Priority | N/A — as-built |
| Status | Draft |
| NFR liên quan | NFR-P-01, NFR-P-02, NFR-P-05 — xem Overview §5 |
| OQ liên quan | OQ-P-04, OQ-P-05, OQ-P-06, OQ-P-07, OQ-P-11, OQ-P-14 — xem Overview §6 |
Nguồn inventory: A-02, A-08 (và trạng thái cổng chặn A-07).
1. US Statement ​
text
As a Người dùng tool [Assumption — OQ-P-13 / G-01]
I want biết tool tôi mở đang dùng được hay đang ẩn / tắt / khoá, và mở khoá được bằng mã bí mật khi tool bị khoá
So that [Assumption] quản trị viên giới hạn được ai dùng tool nào mà không cần tài khoản đăng nhập2. Dependencies & Definition Of Ready ​
N/A — đã triển khai (Mode B).
Dependency runtime:
| # | Cần sẵn sàng | Ai cung cấp | Trạng thái |
|---|---|---|---|
| D1 | Dòng tools + nhóm cho mã tool (trạng thái bật/hiện/khoá do Admin đặt ở US-P03) | Admin CMS | ❓ Trạng thái thật trên prod chưa biết (OQ-P-14) |
| D2 | API GET /api/v1/tools/public, POST /api/v1/tools/public/code/:code/verify | BE | Đã có |
3. Business Rules ​
| ID | Rule | Áp dụng ở | Đã cover bởi (AC) | Nguồn code (Mode B/C) |
|---|---|---|---|---|
| BR-01 | Trạng thái mọi tool được tải một lần khi vào workspace (tối đa 1000 tool, chờ tối đa 10 giây) và dùng chung cho mọi tool, không tải lại khi chuyển tool | A1 | AC-M1.1 | fe/src/ui/components/works/shared/use-tools-state.ts:40-77, fe/src/ui/pages/works/sapp/tools/shell.tsx:74, :426 |
| BR-02 | Trạng thái hiệu lực của tool = trạng thái nhóm và trạng thái tool (bật/hiện); tool không thuộc nhóm coi như nhóm bật + hiện | A1 | AC-M1.2 | be/libs/modules/src/lib/tool/service.ts:105-113 |
| BR-03 | Danh sách public chỉ gồm tool đang hiện và thuộc nhóm đang hiện (hoặc không nhóm); không trả id hay giá trị khoá | A1 | AC-M1.2 | be/libs/modules/src/lib/tool/common.service.ts:113-119, be/libs/modules/src/lib/tool/service.ts:105-123 |
| BR-04 | Đóng khi không chắc (fail-closed): tool không có trong danh sách public — kể cả tool có trong danh mục FE nhưng chưa có dòng trong bảng tools — bị coi là đóng | M1 | AC-M1.3 | fe/src/ui/components/works/shared/tool-availability.ts:9-28, fe/src/ui/components/works/shared/tool-gate.tsx:144-156 |
| BR-05 | Không đọc được danh sách (mạng, timeout, lỗi 4xx/5xx) → mọi tool đóng, hiện lý do | M1 | AC-M1.4 | fe/src/ui/components/works/shared/use-tools-state.ts:41-76, fe/src/ui/components/works/shared/tool-gate.tsx:130-142 |
| BR-06 | Cổng chặn xét theo thứ tự: đang tải → không kiểm tra được → chưa mở (không có / ẩn) → đã tắt → đang khoá → nội dung tool. Tool chỉ mở khi hiện và bật (và đã mở khoá nếu có khoá) | M1 | AC-M1.3, AC-M1.5, AC-M1.6 | fe/src/ui/components/works/shared/tool-gate.tsx:120-266, fe/src/ui/components/works/shared/tool-availability.ts:26-28 |
| BR-07 | Ba loại khoá: không khoá (luôn hợp lệ) · giá trị cố định (khớp chính xác) · năm của ngày (năm của ngày nhập phải bằng giá trị khoá). Ngày không đọc được → lỗi 23005 | A2 | AC-M1.7, AC-M1.8, EC-M1.3 | be/libs/modules/src/lib/tool/service.ts:235-260 |
| BR-08 | Loại "năm của ngày" hiện ô chọn ngày (không xoá được); loại "giá trị cố định" hiện ô chữ "Mã bí mật", Enter để gửi | M1 - field | AC-M1.7 | fe/src/ui/components/works/shared/tool-gate.tsx:221-250 |
| BR-09 | Bấm "Mở khoá" khi ô rỗng → "Vui lòng nhập mã bí mật." và không gọi API | A2 | AC-M1.9 | fe/src/ui/components/works/shared/tool-gate.tsx:188-191 |
| BR-10 | Kiểm tra mã bị từ chối nếu nhóm tắt (24003) hoặc tool tắt (23003) — xét trước khi so mã; mã tool không tồn tại → 23001 | A2 | EC-M1.1 | be/libs/modules/src/lib/tool/service.ts:214-233 |
| BR-11 | Mã đúng → tool mở khoá cho phiên trình duyệt hiện tại, theo từng mã tool; đóng tab/phiên thì phải nhập lại | A2 | AC-M1.8, EC-M1.4 | fe/src/ui/components/works/shared/tool-gate.tsx:12, :109-113, :197-200 |
| BR-12 | Thông báo lỗi mở khoá theo mã: sai mã "Mã bí mật không đúng. Vui lòng thử lại." · tool tắt "Tool này đã bị tắt." · nhóm tắt "Nhóm tool này đã bị tắt." · tool không còn "Tool này không còn tồn tại." · sai định dạng "Mã bí mật không đúng định dạng. Vui lòng kiểm tra lại." · lỗi dạng đăng nhập → câu báo lỗi cấu hình máy chủ · khác → thông điệp máy chủ hoặc "Không xác thực được mã bí mật." | A2 | AC-M1.10, EC-M1.1, EC-M1.2 | fe/src/ui/components/works/shared/tool-gate.tsx:49-67, :202 |
⚠️ Observed (không phải BR — xem EC và OQ): khoá chỉ chặn ở giao diện (OQ-P-04), mở khoá chỉ lưu ở trình duyệt (OQ-P-04), kiểm mã không giới hạn tần suất (OQ-P-05), tool ẩn vẫn đọc trạng thái / kiểm mã được (OQ-P-06), sortBy của danh sách public (OQ-P-07), component khoá cũ không dùng (OQ-P-11).
4. Design ​
a. Mối liên hệ giữa các màn & User Flow ​
text
[Vào workspace] → A1 tải trạng thái (1 lần)
[Mở tool <code>] → M1 Cổng chặn
├─ đang tải ─────────────→ "Đang tải…"
├─ đọc lỗi ──────────────→ "Không kiểm tra được trạng thái tool"
├─ không có / ẩn ────────→ "Tool chưa mở"
├─ tắt ──────────────────→ "Tool đã bị tắt"
├─ có khoá, chưa mở khoá → "Tool đang khoá" ──A2 đúng──→ nội dung tool
│ └─A2 sai───→ ở lại, hiện lỗi
└─ hiện + bật (+ không khoá / đã mở khoá) → nội dung toolb. Chi tiết từng màn ​
Màn M1 - Cổng chặn tool ​
| Field | Value |
|---|---|
| Figma frame | N/A — as-built, không có Figma |
| Trigger vào màn | Mở bất kỳ route tool /works/sapp/tools/<slug> |
| Mô tả ngắn | Panel trạng thái chiếm vùng nội dung, thay nội dung tool cho tới khi tool mở được |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Loading | Chưa có kết quả trạng thái | Spinner "Đang tải…" | N/A |
| Error | Đọc trạng thái lỗi | "Không kiểm tra được trạng thái tool" + "Chưa đọc được trạng thái tool từ máy chủ nên tool tạm thời bị khoá. Vui lòng tải lại trang." | N/A |
| Empty (chưa mở) | Mã tool không có trong danh sách, hoặc đang ẩn | "Tool chưa mở" + "Tool này hiện không khả dụng." | N/A |
| Disabled (đã tắt) | Tool/nhóm tắt | "Tool đã bị tắt" + "Tool này đã bị quản trị viên tắt." | N/A |
| Locked | Có khoá, phiên chưa mở khoá | "Tool đang khoá" + "Nhập mã bí mật để mở tool này." (hoặc "Nhập ngày được yêu cầu để mở tool này."), ô nhập, nút "Mở khoá", dòng lỗi đỏ nếu có | N/A |
| Has data | Tool mở | Nội dung tool | N/A |
Fields ​
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
| Mã bí mật | Yes | Text | rỗng | Tự do | Không rỗng (BR-09); so khớp ở BE (BR-07) | "Vui lòng nhập mã bí mật." / "Mã bí mật không đúng. Vui lòng thử lại." | Loại khoá = giá trị cố định | secretType |
| Ngày | Yes | Date (DatePicker) | rỗng | Ngày | Năm của ngày = giá trị khoá (BR-07) | Như trên; ngày không đọc được → "Mã bí mật không đúng định dạng…" | Loại khoá = năm của ngày | secretType |
Filter / Search / Sort ​
N/A — không phải màn List.
Actions ​
A1 - Tải trạng thái tool (hệ thống) ​
| Item | Description |
|---|---|
| Trigger | Người dùng vào workspace /works/sapp/tools/* |
| Behavior | Gọi GET /api/v1/tools/public?page=1&limit=1000, timeout 10 s (BR-01); tính hiệu lực theo BR-02/BR-03. Chỉ đọc DB mind_keep (bảng tools, tool_groups); không ghi |
| Success Result | Kết quả chia sẻ cho sidebar (US-P01), trang chọn tool đích và cổng chặn |
Error cases:
| Case | Expected Handling |
|---|---|
| Mạng lỗi / timeout / 4xx / 5xx | Mọi tool đóng (BR-05) |
A2 - Mở khoá ​
| Item | Description |
|---|---|
| Trigger | Nhập mã / chọn ngày rồi bấm "Mở khoá" (hoặc Enter ở ô chữ) |
| Behavior | Gọi POST /api/v1/tools/public/code/:code/verify; BE áp BR-10 rồi BR-07. Không ghi DB; đúng mã → ghi cờ mở khoá vào bộ nhớ phiên trình duyệt theo mã tool (BR-11) |
| Success Result | Nội dung tool hiện |
Error cases:
| Case | Expected Handling |
|---|---|
Sai mã (valid=false) | "Mã bí mật không đúng. Vui lòng thử lại." |
| Tool/nhóm tắt, tool không còn, sai định dạng ngày | Câu theo BR-12 |
| Route trả lỗi dạng đăng nhập (401/permission) | "Không mở khoá được do lỗi cấu hình phiên bản máy chủ (endpoint xác thực đang đòi đăng nhập). Vui lòng báo quản trị viên — không phải do mã bạn nhập." |
Acceptance Criteria của màn M1 ​
AC-M1.1 - Tải trạng thái một lần ​
gherkin
Given người dùng vào workspace và chuyển qua lại giữa 3 tool
When quan sát các lời gọi API
Then chỉ có một lời gọi danh sách trạng thái tool public cho cả phiên xem trangMaps to:
- Business Rule: BR-01
AC-M1.2 - Nhóm tắt làm tool con đóng ​
gherkin
Given tool sapp.011 bật + hiện nhưng nhóm "sapp" của nó đang tắt
When người dùng mở /works/sapp/tools/sapp-26297
Then cổng chặn hiện "Tool đã bị tắt"Maps to:
- Business Rule: BR-02, BR-06
AC-M1.3 - Fail-closed khi chưa có dòng DB ​
gherkin
Given mã sapp.013 có trong danh mục FE nhưng chưa có dòng trong bảng tools
When người dùng mở /works/sapp/tools/econtract-error-stats
Then cổng chặn hiện "Tool chưa mở" — "Tool này hiện không khả dụng."Maps to:
- Business Rule: BR-03, BR-04
AC-M1.4 - Không đọc được trạng thái ​
gherkin
Given API danh sách trạng thái trả 500
When người dùng mở một tool bất kỳ
Then cổng chặn hiện "Không kiểm tra được trạng thái tool" và không hiện nội dung toolMaps to:
- Business Rule: BR-05
AC-M1.5 - Tool ẩn ​
gherkin
Given tool đang ẩn (không có trong danh sách public)
When người dùng mở link của tool
Then cổng chặn hiện "Tool chưa mở"Maps to:
- Business Rule: BR-04, BR-06
AC-M1.6 - Tool tắt ​
gherkin
Given tool hiện nhưng tắt
When người dùng mở tool
Then cổng chặn hiện "Tool đã bị tắt" — "Tool này đã bị quản trị viên tắt."Maps to:
- Business Rule: BR-06
AC-M1.7 - Hiện đúng ô nhập theo loại khoá ​
gherkin
Given tool bật + hiện, khoá loại "năm của ngày"
When người dùng mở tool
Then panel "Tool đang khoá" hiện ô chọn ngày và câu "Nhập ngày được yêu cầu để mở tool này."
And với khoá "giá trị cố định" thì hiện ô chữ "Mã bí mật"Maps to:
- Business Rule: BR-07, BR-08
AC-M1.8 - Mở khoá thành công, nhớ trong phiên ​
gherkin
Given tool khoá "giá trị cố định" với giá trị X
When người dùng nhập đúng X và bấm "Mở khoá"
Then nội dung tool hiện
And tải lại trang trong cùng tab thì không phải nhập lạiMaps to:
- Business Rule: BR-07, BR-11
AC-M1.9 - Ô rỗng ​
gherkin
Given panel "Tool đang khoá"
When người dùng bấm "Mở khoá" khi chưa nhập gì
Then hiện "Vui lòng nhập mã bí mật." và không có lời gọi API kiểm mãMaps to:
- Business Rule: BR-09
AC-M1.10 - Sai mã ​
gherkin
Given tool khoá "giá trị cố định"
When người dùng nhập sai mã và bấm "Mở khoá"
Then hiện "Mã bí mật không đúng. Vui lòng thử lại." và tool vẫn khoáMaps to:
- Business Rule: BR-12
Negative AC / Edge Cases của màn M1 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M1.1 | Admin tắt tool sau khi người dùng đã thấy panel khoá, rồi người dùng bấm "Mở khoá" | BE trả 23003 → "Tool này đã bị tắt." (BR-10, BR-12) |
| EC-M1.2 | Route kiểm mã bị cấu hình đòi đăng nhập | Câu báo lỗi cấu hình máy chủ, không đổ lỗi cho mã (BR-12) |
| EC-M1.3 | Khoá "năm của ngày" nhận chuỗi ngày không đọc được (gọi API trực tiếp) | Lỗi 23005 → "Mã bí mật không đúng định dạng. Vui lòng kiểm tra lại." (BR-07) |
| EC-M1.4 | Mở tool đã mở khoá ở tab mới / sau khi đóng trình duyệt | Phải nhập lại (bộ nhớ theo phiên, BR-11) |
| EC-M1.5 | ⚠️ Observed — Gọi thẳng API /api/v1/sapp/* của một tool đang tắt/khoá | API vẫn chạy: không route SAPP nào kiểm trạng thái tool hay mã bí mật (be/apps/api/src/tool/tool-public.controller.ts:74-77; NFR-P-01, NFR-P-02, OQ-P-04) |
| EC-M1.6 | ⚠️ Observed — Tự đặt cờ mở khoá trong bộ nhớ phiên trình duyệt | Cổng chặn coi tool đã mở khoá; FE không gửi bằng chứng mở khoá lên API (fe/src/ui/components/works/shared/tool-gate.tsx:109-113; OQ-P-04) |
| EC-M1.7 | ⚠️ Observed — Thử mã liên tục (khoá "năm của ngày" chỉ vài trăm giá trị khả dĩ) | Route kiểm mã public, không giới hạn tần suất (be/apps/api/src/tool/tool-public.controller.ts:79-97; OQ-P-05) |
| EC-M1.8 | ⚠️ Observed — Tool đang ẩn: gọi GET /tools/public/code/:code hoặc verify | Vẫn trả trạng thái / vẫn kiểm mã (be/libs/modules/src/lib/tool/service.ts:125-134, :214-221; OQ-P-06, DR-P-07) |
| EC-M1.9 | ⚠️ Observed — Tham số sắp xếp sortBy của danh sách public là chuỗi tự do ghép vào câu sắp xếp | Hành vi hiện tại; FE không gửi sortBy (be/libs/modules/src/lib/tool/common.service.ts:109, :128; OQ-P-07) |
| EC-M1.10 | ⚠️ Observed — Component khoá cũ (năm cố định 2003, kiểm ở trình duyệt) có trong code | Không tool nào dùng; không phải cơ chế khoá đang chạy (fe/src/ui/components/works/sapp/secret-gate.tsx:14-47; OQ-P-11) |
5. Cross-feature AC ​
AC-X.1 - Khoá tool không bảo vệ API của FS nhóm ​
gherkin
Given một tool của FS nhóm (vd sapp.005 Retry econtract) đang khoá hoặc tắt
When ai đó gọi trực tiếp route /api/v1/sapp/... của tool đó
Then route vẫn thực thi (hành vi hiện tại, ⚠️ Observed — NFR-P-01, OQ-P-01, OQ-P-04)Maps to:
- REL-01…REL-06 (Be Affected - 6 FS nhóm tool)
AC-X.2 - Workspace naucode-kahrs dùng chung cổng chặn ​
gherkin
Given cổng chặn là component dùng chung với workspace /works/naucode-kahrs
When hành vi cổng chặn thay đổi
Then workspace kia cũng bị ảnh hưởng (ngoài phạm vi dự án)Maps to:
- REL-07 (Be Affected - workspace naucode-kahrs)