Skip to content

US-P03: Quản trị trạng thái tool và nhóm tool ​

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.

FieldValue
US IDUS-P03
Role thực hiệnR2 - Admin CMS (đăng nhập CMS, có quyền tools / tool_groups) — Fact từ code
PhaseAs-built (đã triển khai)
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-P-02, NFR-P-04 — xem Overview §5
OQ liên quanOQ-P-12, OQ-P-14, OQ-P-16, OQ-P-17, OQ-P-18 — xem Overview §6

Nguồn inventory: A-10, A-11.

1. US Statement ​

text
As a Admin CMS
I want tạo / sửa / xoá tool và nhóm tool, bật/tắt, ẩn/hiện và đặt khoá bí mật cho từng tool
So that [Assumption] tôi quyết định tool nào trong workspace SAPP được mở cho người dùng tool và ở điều kiện nào (OQ-P-18)

2. Dependencies & Definition Of Ready ​

N/A — đã triển khai (Mode B).

Dependency runtime: tài khoản CMS có quyền tools:* (và tool_groups:* để quản lý nhóm).

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Quản trị tool yêu cầu đăng nhập CMS và quyền tools tương ứng (đọc / tạo / sửa / xoá); quản trị nhóm yêu cầu quyền tool_groupsM1, M2, M3AC-M1.1, EC-M1.1be/apps/api/src/tool/tool.controller.ts:35-137, be/apps/api/src/tool-group/tool-group.controller.ts:32-116
BR-02Mã tool là duy nhất; tạo hoặc đổi mã trùng bị từ chối (23002)M2 - field CodeAC-M2.2be/libs/modules/src/lib/tool/service.ts:35-44, :162-174
BR-03Mỗi tool có mã vĩnh viễn dạng sapp.NNN gắn với một route; mã không bao giờ bị dùng lại hay đánh số lại. FE chỉ giữ mã + tên, mọi trạng thái do bảng tools quyếtM2 - field CodeAC-M2.1fe/src/data/constants/tool-codes.ts:4-20, fe/CLAUDE.md:3-22
BR-04Gán tool vào nhóm không tồn tại bị từ chối (24001); gửi nhóm rỗng = gỡ tool khỏi nhómM3 - field NhómAC-M3.1be/libs/modules/src/lib/tool/service.ts:24-32, :171-174, :183
BR-05Bật/tắt, ẩn/hiện ở nhóm áp cho mọi tool con (hiệu lực = nhóm AND tool)M3 - nhómAC-M3.2be/libs/modules/src/lib/tool/service.ts:105-113, app/lib/screens/tool_group_form_screen.dart:181-190
BR-06Xoá nhóm → tool con trở thành "không thuộc nhóm" (không bị xoá)M3 - xoá nhómAC-M3.3be/libs/database/src/lib/entities/tool/tool.entity.ts:34-39
BR-07Form tạo tool (web): Code, Name bắt buộc; Enabled / Visible mặc định Yes; Secret Type mặc định none; Secret Value chỉ được gửi khi loại khoá khác none và có nhậpM2AC-M2.1, AC-M2.3fe/src/ui/components/cms/(tools)/create-form.tsx:25-86
BR-08Form sửa tool (web): chọn loại khoá none thì xoá giá trị khoá cũ; loại khác mà để trống Secret Value thì giữ nguyên giá trị khoá cũM2AC-M2.4fe/src/ui/components/cms/(tools)/update-form.tsx:78-95
BR-09Màn web không có trường nhóm — gán/gỡ nhóm và quản lý nhóm chỉ làm được trên app mobile (hoặc gọi API)M2, M3AC-M3.1fe/src/ui/components/cms/(tools)/create-form.tsx:25-70 (không có field nhóm), app/lib/screens/tool_form_screen.dart:187-191
BR-10Danh sách tool web hiện cột Code, Name, Enabled, Visible, Lock (badge loại khoá), Secret (che mặc định), Updated; lọc theo Enabled / Visible / Secret Type; phân trang mặc định 10M1AC-M1.1, AC-M1.2fe/src/ui/pages/cms/(tools)/page.tsx:46-78, :170-224
BR-11Xoá tool phải xác nhận "Delete tool?" — "… will be deleted. This cannot be undone."M1 - action XoáAC-M1.3fe/src/ui/pages/cms/(tools)/page.tsx:247-258
BR-12Tool mới seed qua migration mặc định bật + hiện + không khoá (13 mã sapp.001–sapp.013; 011–013 gắn nhóm sapp)Dữ liệuAC-M2.5be/libs/database/migrations/1783700000000-create-tools.ts:6-15, :33, :41, be/libs/database/migrations/1786300000000-seed-tool-sapp-26297.ts:14-19

4. Design ​

a. Mối liên hệ giữa các màn & User Flow ​

text
[CMS web /cms/tools]  M1 Danh sách tool ──Create/Edit──→ M2 Form tool ──Submit──→ M1 (reload + toast)
                                        └─Delete─→ xác nhận → M1
[App mobile — quản trị tool]  M3 Danh sách tool + nhóm ──→ form tool (có "Nhóm") / form nhóm
Kết quả → bảng tools / tool_groups (DB mind_keep) → US-P02 đọc qua /tools/public

b. Chi tiết từng màn ​

Màn M1 - Danh sách tool (web /cms/tools) ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànAdmin mở /cms/tools ("Manage tool availability, visibility, and secret locks")
Mô tả ngắnBảng tool có lọc, tạo / sửa / xoá
UI States ​
StateKhi nàoHiển thịFigma frame
Default / Has dataTải xongBảng "Tools" với các cột BR-10N/A
LoadingĐang tải (timeout 10 s)Trạng thái tải của bảng chungN/A
EmptyKhông có tool khớp lọcBảng rỗng của template chungN/A
ErrorAPI lỗiHộp lỗi "Failed to load tools" + thông điệp; lỗi token → nút "Login again" chuyển /loginN/A
DisabledN/A—N/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Code—Text (mono)—sapp.NNN——Always—
Name—Text————Always—
Enabled / Visible—Boolean—Yes/No——Always—
Lock—BadgeNonetên loại khoá——AlwaysSecret Type
Secret—Giá trị cheche———Always (che)⚠️ Observed — giá trị khoá trả về dạng rõ qua API admin (OQ-P-12)
Updated—Datetime————Always—
Filter / Search / Sort ​
LoạiTheo fieldKiểuDefaultNotes
FilterEnabledYes / No (chọn đúng 1 mới lọc)Tất cảfe/src/ui/pages/cms/(tools)/page.tsx:31-35, :59-66
FilterVisibleYes / NoTất cả:67-73
FilterSecret Typenone / fixed_value / year_of_dateTất cả:74-77
Searchcode hoặc namefree-text—Placeholder "Search by code or name…" (:174)
Sort——Mặc định của APIKhông có điều khiển sắp xếp trên màn
Pagination——10 / trang:46-47
Actions ​
A1 - Tạo tool ​
ItemDescription
TriggerBấm "Create tool" → M2
BehaviorPOST /api/v1/tools (BR-02, BR-07). Ghi bảng tools — DB mind_keep (một DB, không theo môi trường SAPP)
Success ResultBảng tải lại, "Tool created — The tool has been created successfully."

Error cases:

CaseExpected Handling
Mã trùngLỗi 23002 "Tool code already exists"
Không có quyềnLỗi quyền của CMS
A2 - Sửa tool ​
ItemDescription
TriggerBấm sửa một dòng → M2 (điền sẵn)
BehaviorPATCH /api/v1/tools/:id (BR-02, BR-08). Ghi bảng tools — DB mind_keep
Success Result"Tool updated — The tool has been updated successfully."

Error cases:

CaseExpected Handling
Đổi mã trùng tool khác23002
Tool đã bị xoá23001 "Tool not found"
A3 - Xoá tool ​
ItemDescription
TriggerBấm xoá → xác nhận "Delete tool" (BR-11)
BehaviorDELETE /api/v1/tools/:id. Xoá dòng trong bảng tools — DB mind_keep
Success Result"Tool deleted — The tool has been deleted successfully." Tool đó trở thành "chưa mở" với người dùng (fail-closed, US-P02 BR-04)

Error cases:

CaseExpected Handling
Tool không tồn tại23001
Acceptance Criteria của màn M1 ​
AC-M1.1 - Xem và lọc danh sách ​
gherkin
Given Admin có quyền tools:read
When mở /cms/tools và chọn lọc Enabled = No
Then bảng chỉ hiện tool đang tắt, đủ cột Code, Name, Enabled, Visible, Lock, Secret, Updated

Maps to:

  • Business Rule: BR-01, BR-10
AC-M1.2 - Giá trị khoá được che ​
gherkin
Given một tool có khoá "fixed_value"
When Admin xem bảng
Then cột Secret hiển thị dạng che; cột Lock hiện badge "fixed value"

Maps to:

  • Business Rule: BR-10
AC-M1.3 - Xoá có xác nhận ​
gherkin
Given Admin bấm xoá tool "SAPP 23954…" (sapp.008)
When hộp xác nhận "Delete tool?" hiện và Admin bấm "Delete tool"
Then tool bị xoá và bảng tải lại

Maps to:

  • Business Rule: BR-11
Negative AC / Edge Cases của màn M1 ​
IDTình huốngHành vi mong đợi
EC-M1.1Phiên CMS hết hạnHộp lỗi "Failed to load tools" + nút "Login again" → /login
EC-M1.2Xoá một tool sapp.NNN đang dùngTool bị đóng ngay với người dùng ở lần tải trang sau; mã không được dùng lại cho tool khác (BR-03)

Màn M2 - Form tạo / sửa tool (web) ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào màn"Create tool" hoặc sửa một dòng ở M1
Mô tả ngắnModal "Create New Tool" / sửa tool
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultMở formCác field ở bảng dưới; sửa thì điền sẵnN/A
LoadingĐang gửiTrạng thái gửi của form chungN/A
ErrorAPI từ chốiHộp lỗi với thông điệp BEN/A
Empty / Has data / DisabledN/A — form—N/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
CodeYesText— (placeholder "e.g. sapp.001")<family>.NNNDuy nhất (BR-02)"Tool code already exists"Always—
NameYesText— ("Human-readable name")—Bắt buộcBắt buộc của formAlways—
EnabledYesSelect Yes/NoYes———Always—
VisibleYesSelect Yes/NoYes———Always—
Secret TypeYesSelect none / fixed_value / year_of_datenone———Always—
Secret ValueNoTextrỗng ("Backing lock value (leave blank for no lock)")Với year_of_date: một năm, vd 2026Chỉ gửi khi loại ≠ none (BR-07/BR-08)—AlwaysSecret Type
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Submit form &ZeroWidthSpace;
ItemDescription
TriggerBấm "Create" / "Update"
BehaviorNhư M1 A1 / A2
Success ResultForm đóng, M1 tải lại

Error cases:

CaseExpected Handling
Thiếu Code / NameForm không gửi
Lỗi BEHộp lỗi
Acceptance Criteria của màn M2 &ZeroWidthSpace;
AC-M2.1 - Tạo tool mặc định &ZeroWidthSpace;
gherkin
Given Admin mở "Create New Tool"
When nhập Code "sapp.014", Name và giữ mặc định
Then tool được tạo với Enabled = Yes, Visible = Yes, Secret Type = none, không có giá trị khoá

Maps to:

  • Business Rule: BR-03, BR-07
AC-M2.2 - Mã trùng &ZeroWidthSpace;
gherkin
Given đã có tool mã sapp.001
When Admin tạo tool mới mã sapp.001
Then bị từ chối với lỗi 23002 "Tool code already exists"

Maps to:

  • Business Rule: BR-02
AC-M2.3 - Đặt khoá năm của ngày &ZeroWidthSpace;
gherkin
Given Admin chọn Secret Type = year_of_date và Secret Value = "2026"
When lưu
Then người dùng mở tool phải chọn một ngày thuộc năm 2026 để mở khoá (US-P02 BR-07)

Maps to:

  • Business Rule: BR-07
AC-M2.4 - Bỏ khoá / giữ khoá khi sửa &ZeroWidthSpace;
gherkin
Given tool đang khoá fixed_value
When Admin sửa và chọn Secret Type = none
Then giá trị khoá cũ bị xoá
And nếu Admin chỉ đổi Name mà để trống Secret Value (loại vẫn fixed_value) thì giá trị khoá cũ được giữ

Maps to:

  • Business Rule: BR-08
AC-M2.5 - Tool seed sẵn &ZeroWidthSpace;
gherkin
Given DB vừa chạy migration tạo bảng tools
When Admin mở /cms/tools
Then thấy các mã sapp.001–sapp.013 ở trạng thái bật, hiện, không khoá (trừ khi đã được sửa sau đó — OQ-P-14)

Maps to:

  • Business Rule: BR-12
Negative AC / Edge Cases của màn M2 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M2.1Chọn fixed_value nhưng để trống Secret Value khi tạoTool lưu với loại khoá nhưng không có giá trị; mọi mã nhập đều sai (không có giá trị khoá để khớp) — hành vi suy từ code be/libs/modules/src/lib/tool/service.ts:239-240
EC-M2.2⚠️ Observed — giá trị khoá lưu dạng rõ trong DB và trả lại qua API adminHành vi hiện tại (be/libs/database/src/lib/entities/tool/tool.entity.ts:31-32; OQ-P-12)

Màn M3 - Quản trị tool và nhóm tool (app mobile) &ZeroWidthSpace;

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànAdmin mở màn quản trị tool trên app mobile
Mô tả ngắnDanh sách tool + nhóm; form tool có trường "Nhóm"; form nhóm có bật/tắt, ẩn/hiện toàn bộ tool trong nhóm. Inventory chỉ ghi điểm vào — chi tiết UI ngoài phạm vi truy vết
UI States &ZeroWidthSpace;

N/A — ngoài phạm vi truy vết chi tiết (inventory §1 chỉ ghi điểm vào app/lib/screens/tool_admin_list_screen.dart:17).

Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Nhóm (form tool)NoDropdown"Không thuộc nhóm"—Nhóm phải tồn tại (BR-04)24001 "Tool group not found"Always—
Mã nhóm (code)YesText— ("ví dụ sapp")—Duy nhất (24002)"Tool group code already exists"Form nhóm—
Tên nhóm / Mô tảTên: YesText————Form nhóm—
Bật / Hiện (nhóm)—SwitchBật / Hiện—Áp cho mọi tool con (BR-05)—Form nhóm—

Nguồn: app/lib/screens/tool_form_screen.dart:167-242, app/lib/screens/tool_group_form_screen.dart:152-190, be/libs/database/src/lib/entities/tool/tool-group.entity.ts:5-24.

Filter / Search / Sort &ZeroWidthSpace;

N/A — ngoài phạm vi truy vết chi tiết.

Actions &ZeroWidthSpace;
A1 - Gán / gỡ nhóm cho tool &ZeroWidthSpace;
ItemDescription
TriggerChọn "Nhóm" trong form tool rồi lưu
BehaviorPATCH /api/v1/tools/:id với nhóm (BR-04). Ghi bảng tools — DB mind_keep
Success ResultTool thuộc nhóm; hiệu lực theo BR-05

Error cases:

CaseExpected Handling
Nhóm không tồn tại24001
A2 - Tạo / sửa / xoá nhóm &ZeroWidthSpace;
ItemDescription
TriggerForm nhóm / "Xoá nhóm" (xác nhận "Xoá nhóm")
Behavior/api/v1/tool-groups CRUD. Ghi bảng tool_groups — DB mind_keep
Success ResultNhóm cập nhật; xoá nhóm → tool con không nhóm (BR-06)

Error cases:

CaseExpected Handling
Mã nhóm trùng24002
Acceptance Criteria của màn M3 &ZeroWidthSpace;
AC-M3.1 - Gán và gỡ nhóm &ZeroWidthSpace;
gherkin
Given tool sapp.001 không thuộc nhóm
When Admin chọn nhóm "sapp" trên app và lưu, rồi sau đó chọn "Không thuộc nhóm"
Then lần đầu tool thuộc nhóm "sapp"; lần sau tool không còn nhóm
And trên màn web /cms/tools không có trường nào để làm việc này

Maps to:

  • Business Rule: BR-04, BR-09
AC-M3.2 - Tắt nhóm tắt mọi tool con &ZeroWidthSpace;
gherkin
Given nhóm "sapp" chứa sapp.011–sapp.013, cả ba đang bật
When Admin tắt nhóm "sapp"
Then người dùng mở một trong ba tool thấy "Tool đã bị tắt"

Maps to:

  • Business Rule: BR-05
AC-M3.3 - Xoá nhóm không xoá tool &ZeroWidthSpace;
gherkin
Given nhóm "sapp" chứa 3 tool
When Admin xoá nhóm
Then 3 tool vẫn còn, ở trạng thái không thuộc nhóm

Maps to:

  • Business Rule: BR-06
Negative AC / Edge Cases của màn M3 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M3.1Ẩn nhómMọi tool con biến mất khỏi danh sách public (US-P02 BR-03)
EC-M3.2⚠️ Observed — Tool ẩn vẫn kiểm mã / đọc trạng thái qua route theo mãHành vi hiện tại (OQ-P-06)

5. Cross-feature AC &ZeroWidthSpace;

AC-X.1 - Trạng thái admin quyết định tool nào mở cho mọi FS nhóm &ZeroWidthSpace;

gherkin
Given Admin tắt tool sapp.008
When người dùng mở tool 23954
Then cổng chặn (US-P02) hiện "Tool đã bị tắt" — nhưng API của FS 23954 vẫn gọi được trực tiếp (⚠️ Observed, NFR-P-01)

Maps to:

  • REL-04 (Be Affected - FS 23954), áp tương tự REL-01…REL-06