Giao diện
Feature Inventory — Nền tảng dùng chung của cụm tool SAPP (/works/sapp/tools) ​
Kiểm kê tính năng đã triển khai, dựng từ code. Đầu vào cho FS as-built (Mode B). Mọi dòng có bằng chứng
file:dòng; không có bằng chứng → §8 Câu hỏi.Công thức truy vết:
ba/system-profile.md§3. Mọi đường dẫn tính từ root repomind_keep/. AI draft — chưa qua Gate R1. Không gọi API chạy thật; mọi hành vi suy từ đọc source tại commit dưới. Phạm vi là phần dùng chung — FS của từng nhóm sub-tool (HubSpot, 20603, 24395, 23954, 26878, 26297) tham chiếu ID ở đây (E-/A-/R-) thay vì mô tả lại.
| Field | Value |
|---|---|
| Project | ba/projects/2026-SAPP-Works-tools |
| Mode | B – As-built |
| Ngày đọc code | 2026-09-30 |
| Commit | e77c47a |
| Điểm vào BA cung cấp | Trang hub /works/sapp + /works/sapp/tools, registry TOOL_CODES họ sapp.*, cơ chế trạng thái/khoá tool, env_systems, auto-login SAPP Ops, SAP log trace, Ops passthrough, Ops SQL runner |
| Thành phần chạm tới | FE (CMS web) · BE (apps/api) · APP (chỉ màn quản trị tool, không có màn SAPP) · hệ ngoài: HubSpot CRM API, SAPP Ops REST API, SAP service, Postgres của SAPP Ops, Redis |
| Status | Draft |
1. Phạm vi đã truy vết ​
- Trong phạm vi:
- Điều hướng:
/works/sapp(chuyển hướng),/works/sapp/tools(chọn tool đích), khung (shell) chung cho mọi route tool: sidebar theo nhóm, breadcrumb, theme, ghi nhớ tool dùng gần nhất. - Registry tool FE (
registry.ts— nhóm/slug/nhãn) vàTOOL_CODES(mã vĩnh viễnsapp.NNN). - Trạng thái runtime của tool do BE giữ theo
code: bật/tắt, ẩn/hiện, khoá bí mật, nhóm tool; API public/tools/public*+ API quản trị/tools,/tool-groups; màn quản trị/cms/tools(web) và màn quản trị tool trên app mobile (chỉ ghi nhận điểm vào). - Cổng chặn tool phía FE (
ToolGate) và componentSecretGate(không được dùng). - Cấu hình môi trường: literal
prod|staging|devtrong route, bảngenv_systems, các bộ key theo hệ ngoài. - Dịch vụ BE dùng chung: auto-login SAPP Ops (
SappAuthCommonService), SAP log trace (SapLogCommonService), SAPP Ops passthrough (SappOpsCommonService+SappOpsController), Ops SQL runner (SappOpsSqlCommonService), route thêm option property HubSpot dev, wiring module. - Component UI dùng chung:
SapLogTrace/SapLogTraceSummary,Select,Checkbox,DatePicker,HubspotPropertyField,shared.tsx,utils.ts(chỉ liệt kê, không đi sâu). - Quyền truy cập của toàn bộ controller
be/apps/api/src/sapp/*.controller.ts.
- Điều hướng:
- Ngoài phạm vi (dừng truy vết tại đây):
- Hành vi riêng của 13 sub-tool (sapp.001–013) — do 6 inventory nhóm khác đảm nhận.
- Logic nghiệp vụ trong
SappCommonService(econtract, 23954, 24395, 26878) vàSapp26297CommonService— chỉ ghi phần credential dùng chung. - Nội dung catalogue SQL (
SAPP_26878_SQL_STATEMENTS,SAPP_26297_SQL_STATEMENTS) — chỉ ghi cơ chế chạy. - Hệ ngoài (HubSpot, SAP, SAPP Ops, LMS) bên trong; workspace
/works/naucode-kahrs(dùng chungToolGatenhưng ngoài dự án). - Chi tiết UI admin
/cms/toolsvà màn app mobile (chỉ ghi điểm vào).
2. Điểm vào (Entry points) ​
| ID | Loại | Tên / đường dẫn người dùng thấy | Bằng chứng |
|---|---|---|---|
| E-01 | Màn web | /works/sapp — không có màn riêng, chuyển thẳng sang /works/sapp/tools | fe/app/works/sapp/page.tsx:17-19 |
| E-02 | Màn web | /works/sapp/tools — màn "chọn tool đích" (đang mở tool… / không kiểm tra được / chưa có tool nào được mở) | fe/app/works/sapp/tools/page.tsx:10-12, fe/src/ui/pages/works/sapp/tools/index-redirect.tsx:35-91 |
| E-03 | Màn web (khung chung) | Shell "SAPP Tools · HubSpot · Ops · SAP" bọc mọi route /works/sapp/tools/*: sidebar, breadcrumb Works › SAPP › <tool>, nút "Về Works", công tắc giao diện tối | fe/app/works/sapp/tools/layout.tsx:25-27, fe/src/ui/pages/works/sapp/tools/shell.tsx:72-442 |
| E-04 | Màn web | 13 route tool /works/sapp/tools/<slug> xếp trong 6 nhóm (xem §4 bảng registry) | fe/src/ui/pages/works/sapp/tools/registry.ts:39-111, fe/src/ui/pages/works/sapp/tools/registry.ts:124-126 |
| E-05 | Màn web (admin) | /cms/tools — "Manage tool availability, visibility, and secret locks" | fe/app/cms/(tools)/tools/page.tsx:7-18 |
| E-06 | Màn mobile (admin) | Màn danh sách/sửa tool và nhóm tool (gọi /api/v1/tools, /api/v1/tool-groups) | app/lib/screens/tool_admin_list_screen.dart:17, app/lib/services/tool_service.dart:19, app/lib/services/tool_group_service.dart:20 |
| E-07 | API | GET /api/v1/tools/public — danh sách tool hiệu lực đang hiện (không cần đăng nhập) | be/apps/api/src/tool/tool-public.controller.ts:29-45 |
| E-08 | API | GET /api/v1/tools/public/code/:code — trạng thái hiệu lực của một tool | be/apps/api/src/tool/tool-public.controller.ts:47-64 |
| E-09 | API | POST /api/v1/tools/public/code/:code/verify — kiểm tra mã bí mật | be/apps/api/src/tool/tool-public.controller.ts:79-97 |
| E-10 | API (admin) | GET/POST /api/v1/tools, GET /api/v1/tools/code/:code, POST /api/v1/tools/code/:code/verify, GET/PATCH/DELETE /api/v1/tools/:id | be/apps/api/src/tool/tool.controller.ts:35-137 |
| E-11 | API (admin) | /api/v1/tool-groups (list, code/:code, :id, CRUD) | be/apps/api/src/tool-group/tool-group.controller.ts:25-116 |
| E-12 | API (admin) | /api/v1/env-systems CRUD — nơi nhập URL/credential hệ ngoài | be/apps/api/src/env-system/env-system.controller.ts:25-100 |
| E-13 | API | POST /api/v1/sapp/{prod|dev|staging}/sap-log/trace | be/apps/api/src/sapp/sapp.controller.ts:3841, :3856, :3871 |
| E-14 | API | POST /api/v1/sapp/{prod|dev|staging}/sap-log/scan-runs | be/apps/api/src/sapp/sapp.controller.ts:3886, :3901, :3916 |
| E-15 | API | GET /api/v1/sapp/{dev|staging}/sap-log/manual-scan (không có bản prod) | be/apps/api/src/sapp/sapp.controller.ts:3991, :4003 |
| E-16 | API | POST /api/v1/sapp/{dev|staging}/sap-log/sign-callback (không có bản prod) | be/apps/api/src/sapp/sapp.controller.ts:4017-4047 |
| E-17 | API | POST /api/v1/sapp/dev/hubspot/{deals|contacts}/properties/{property}/options (chỉ dev) | be/apps/api/src/sapp/sapp.controller.ts:821-846, :1101 |
| E-18 | API | SAPP Ops passthrough /api/v1/sapp/{prod|staging|dev}/sapp-ops/… — 33 thao tác × 3 môi trường (dev/staging thêm 2 route SQL) | be/apps/api/src/sapp/sapp-ops.controller.ts:73, :634-2386 |
| E-19 | API | GET /api/v1/sapp/{prod|staging|dev}/sapp-ops/ping | be/apps/api/src/sapp/sapp-ops.controller.ts:634, :645, :656 |
| E-20 | API | GET /api/v1/sapp/{dev|staging}/sapp-ops/sql/status | be/apps/api/src/sapp/sapp-ops.controller.ts:2404, :2430 |
| E-21 | API | POST /api/v1/sapp/{dev|staging}/sapp-ops/sql/run | be/apps/api/src/sapp/sapp-ops.controller.ts:2416, :2442 |
| E-22 | Dịch vụ nội bộ (không có route) | Auto-login SAPP Ops — cố ý không mở endpoint login | be/apps/api/src/sapp/sapp-ops.controller.ts:68-70, be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:39-134 |
3. Hành động người dùng / hệ thống ​
"Viewer" = bất kỳ ai mở /works/* (không có tường đăng nhập — xem R-18, Q-04).
| ID | Ai (role) | Làm gì | Điểm vào | Kết quả quan sát được | Bằng chứng |
|---|---|---|---|---|---|
| A-01 | Viewer | Mở /works/sapp | E-01 | Bị chuyển thẳng sang /works/sapp/tools | fe/app/works/sapp/page.tsx:17-19 |
| A-02 | Hệ thống (shell) | Tải trạng thái mọi tool một lần khi vào workspace | E-03 → E-07 | Gọi GET /tools/public?page=1&limit=1000, timeout 10 s; kết quả chia sẻ cho mọi route con, không gọi lại | fe/src/ui/components/works/shared/use-tools-state.ts:40-77, fe/src/ui/pages/works/sapp/tools/shell.tsx:74, :426 |
| A-03 | Hệ thống | Chọn tool đích khi vào /works/sapp/tools | E-02 | Mở tool dùng gần nhất nếu còn mở; nếu không, tool mở đầu tiên theo thứ tự registry; không có → "Chưa có tool nào được mở"; lỗi đọc → "Không kiểm tra được trạng thái tool". Điều hướng kiểu thay thế (Back không quay về trang chọn) | fe/src/ui/pages/works/sapp/tools/index-redirect.tsx:41-90, fe/src/ui/components/works/shared/tool-availability.ts:41-54 |
| A-04 | Viewer | Xem sidebar danh sách tool | E-03 | Tool xếp theo 6 nhóm; tool không có trong danh sách public bị ẩn; tool đóng hiện nhãn "Off" và không bấm được; nhóm không còn tool nào bị ẩn cả tiêu đề; trong lúc tải: tool hiện mờ, không bấm được | fe/src/ui/pages/works/sapp/tools/shell.tsx:254-395 |
| A-05 | Viewer | Thu/mở một nhóm trong sidebar | E-03 | Lựa chọn được nhớ trên trình duyệt; nhóm chứa tool đang mở không thu được | fe/src/ui/pages/works/sapp/tools/shell.tsx:272-305, :506-550 |
| A-06 | Viewer | Thu sidebar thành thanh icon; bật/tắt giao diện tối | E-03 | Cả hai lựa chọn được nhớ; trên điện thoại sidebar thành ngăn kéo phủ màn | fe/src/ui/pages/works/sapp/tools/shell.tsx:81-105, :151-168, :210-224 |
| A-07 | Viewer | Mở một tool (qua sidebar hoặc link chia sẻ) | E-04 | Cổng chặn hiển thị theo thứ tự: đang tải → không kiểm tra được → "Tool chưa mở" (không có/ẩn) → "Tool đã bị tắt" → "Tool đang khoá" → nội dung tool | fe/src/ui/components/works/shared/tool-gate.tsx:88-267 |
| A-08 | Viewer | Nhập mã bí mật (ô chữ hoặc chọn ngày) để mở khoá tool | E-04 → E-09 | Đúng → mở khoá cho phiên trình duyệt hiện tại (theo code); sai → "Mã bí mật không đúng"; lỗi khác → thông báo theo mã lỗi | fe/src/ui/components/works/shared/tool-gate.tsx:184-264, fe/src/data/services/cms/(tools)/verify-secret.service.ts:24-37 |
| A-09 | Hệ thống | Ghi nhớ tool vừa mở | E-03 | Lưu slug vào trình duyệt để lần sau A-03 quay lại đúng tool | fe/src/ui/pages/works/sapp/tools/shell.tsx:122-126, fe/src/ui/components/works/shared/last-tool.ts:10-26 |
| A-10 | Admin (quyền tools:*) | Tạo/sửa/xoá tool: bật/tắt, ẩn/hiện, loại + giá trị khoá, gán/gỡ nhóm | E-05, E-06 → E-10 | Mã trùng bị từ chối; nhóm không tồn tại bị từ chối; groupId rỗng = gỡ nhóm | be/libs/modules/src/lib/tool/service.ts:34-63, :154-193 |
| A-11 | Admin (quyền tool_groups:*) | Quản lý nhóm tool (ô dù bật/tắt, ẩn/hiện cho mọi tool con) | E-05, E-06 → E-11 | Xoá nhóm → tool con thành không nhóm (không bị xoá) | be/apps/api/src/tool-group/tool-group.controller.ts:32-116, be/libs/database/src/lib/entities/tool/tool.entity.ts:37-39 |
| A-12 | Admin (quyền env_systems:*) | Nhập URL/credential các hệ ngoài theo môi trường | E-12 | Mọi dịch vụ SAPP đọc giá trị lúc gọi, không cần khởi động lại | be/apps/api/src/env-system/env-system.controller.ts:32-100, be/libs/modules/src/lib/env-system/env-system-map.common.service.ts:38-55 |
| A-13 | Sub-tool (hiện chỉ 26878) | Tra vết log SAP theo deal / event / entry / class / transaction | E-13 | BE ký HMAC rồi trả nguyên dữ liệu các bảng log; FE hiện bảng + dòng thời gian có chấm màu trạng thái | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:165-188, fe/src/ui/components/works/sapp/sap-log-trace.tsx:301-452, fe/src/ui/components/works/sapp/sapp-26878-tool.tsx:37 |
| A-14 | Sub-tool | Xem tiến độ các đợt quét ghi nhận doanh thu | E-14 | Trả danh sách lượt quét | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:191-213, fe/src/ui/components/works/sapp/sap-log-trace.tsx:517 |
| A-15 | Sub-tool | Kích hoạt quét doanh thu ngay (không chờ cron tuần) | E-15 | triggered=false = tính năng đang tắt (không phải lỗi); prod bị từ chối | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:227-271 |
| A-16 | Sub-tool | Dựng callback SAP đã ký để đóng vai SAP | E-16 | Trả lệnh/callback dùng được 1 lần; credential không rời BE; prod bị từ chối | be/apps/api/src/sapp/sapp.controller.ts:3948-3989, be/libs/modules/src/lib/sapp/sap-log.common.service.ts:286-331 |
| A-17 | Sub-tool | Thêm một option vào property dạng danh sách của HubSpot dev | E-17 | Giữ nguyên các option cũ, thêm option mới cuối danh sách; option đã có → added=false | be/libs/modules/src/lib/hubspot/common.service.ts:715-800 |
| A-18 | Sub-tool | Đọc/ghi dữ liệu SAPP Ops (danh mục, môn, cơ sở, khoá, lớp, lịch, giáo viên, học viên, user, sản phẩm, đơn, giao dịch, resync SAP) theo môi trường | E-18 | BE đăng nhập Ops thay người dùng, trả dữ liệu Ops; lỗi Ops kèm thông điệp gốc | be/libs/modules/src/lib/sapp/sapp-ops.common.service.ts:65-126, :286-887 |
| A-19 | Sub-tool | Kiểm tra kết nối Ops | E-19 | Trả { ok: true } — không bao giờ trả token | be/libs/modules/src/lib/sapp/sapp-ops.common.service.ts:280-296 |
| A-20 | Sub-tool (26878, 26297) | Hỏi môi trường có chạy SQL được không; chạy một câu SQL đã lập danh mục theo id + tham số | E-20, E-21 | configured=false là câu trả lời bình thường; chạy xong trả câu lệnh (không kèm giá trị), số dòng, thời gian | be/apps/api/src/sapp/sapp-ops.controller.ts:82-108, be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:106-195 |
| A-21 | Hệ thống | Tự đăng nhập SAPP Ops và giữ token | E-22 | Token lưu Redis theo môi trường; gặp 401 → xoá token, đăng nhập lại, thử lại đúng 1 lần | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:87-181 |
4. Dữ liệu ​
Registry tool FE (nhóm hiển thị ↔ slug ↔ code)
Nhóm sidebar (registry.ts) | Slug → TOOL_CODES.code | Bằng chứng |
|---|---|---|
| SAPP Common Hubspot Tools | hs-clone-prod-to-dev→sapp.001 · hs-snapshot-property→sapp.002 · hs-get-property→sapp.003 · hs-pipeline→sapp.004 | fe/src/ui/pages/works/sapp/tools/registry.ts:43-51, fe/src/data/constants/tool-codes.ts:32-35 |
| SAPP 20603 - EContract | econtract→sapp.005 · econtract-timeline→sapp.012 · econtract-error-stats→sapp.013 | registry.ts:53-67, tool-codes.ts:36, :43-44 |
| SAPP 24395 - Tự động ghi nhận doanh thu | sapp-24395→sapp.006 · sapp-24395-products→sapp.007 | registry.ts:70-84, tool-codes.ts:37-38 |
| SAPP 23954 - Ticket Owner | sapp-23954→sapp.008 · sapp-23954-snapshot→sapp.009 | registry.ts:86-96, tool-codes.ts:39-40 |
| SAPP 26878 - Doanh thu thực hiện (Ops → HubSpot → SAP) | sapp-26878→sapp.010 | registry.ts:98-103, tool-codes.ts:41 |
| SAPP 26297 - Chuyển nhượng học viên | sapp-26297→sapp.011 | registry.ts:105-110, tool-codes.ts:42 |
(Đường dẫn rút gọn registry.ts = fe/src/ui/pages/works/sapp/tools/registry.ts; tool-codes.ts = fe/src/data/constants/tool-codes.ts.)
Bảng / kho dữ liệu
| Entity / bảng | Field | Type | Bắt buộc | Mặc định / enum | Bằng chứng |
|---|---|---|---|---|---|
tools | code | varchar(100) | Có, unique | <family>.NNN, vd sapp.001 | be/libs/database/src/lib/entities/tool/tool.entity.ts:13-17 |
tools | name | varchar(255) | Có | — | tool.entity.ts:19-20 |
tools | isEnabled | boolean | Có | true | tool.entity.ts:22-23 |
tools | isVisible | boolean | Có | true | tool.entity.ts:25-26 |
tools | secretType | varchar(50) | Có | none · fixed_value · year_of_date | tool.entity.ts:28-29, fe/src/data/enums/tool.enum.ts:1-5 |
tools | secretValue | text | Không | null; lưu dạng rõ | tool.entity.ts:31-32 |
tools | groupId | uuid → tool_groups | Không | xoá nhóm → SET NULL | tool.entity.ts:34-39 |
tool_groups | code / name / isEnabled / isVisible / description | varchar / varchar / bool / bool / text | code, name bắt buộc | code unique; enabled/visible true | be/libs/database/src/lib/entities/tool/tool-group.entity.ts:5-24 |
tools (seed) | 13 dòng sapp.001–sapp.013 | — | — | Seed chỉ có code + name (+ nhóm sapp cho 011–013) → mặc định bật, hiện, không khoá | be/libs/database/migrations/1783700000000-create-tools.ts:6-15, :33, be/libs/database/migrations/1786300000000-seed-tool-sapp-26297.ts:14-19, 1786400000000-seed-tool-sapp-20603-econtract-timeline.ts:20 |
Shape public tool (PublicToolDto) | code, name, isEnabled, isVisible, secretType, requiresSecret, group | — | — | *giá trị hiệu lực = nhóm AND tool; không có id, secretValue | be/libs/modules/src/lib/tool/service.ts:105-123 |
env_systems | key (unique) / value | varchar(255) / text | key bắt buộc | Mật khẩu/secret lưu dạng rõ trong value | be/libs/database/src/lib/entities/env/env-system.entity.ts:4-12 |
env_systems — HubSpot | SAPP_{PROD,DEV}_HUBSPOT_{API_URL,ACCESS_TOKEN,CLIENT_SERCET} | — | Chỉ ACCESS_TOKEN được đọc | staging dùng lại bộ PROD | be/libs/constants/src/lib/env-system/env-system.constants.ts:6-11, be/libs/constants/src/lib/hubspot/hubspot.constants.ts:10-32, be/libs/modules/src/lib/hubspot/common.service.ts:47-58 |
env_systems — Ops (auto-login) | SAPP_OPS_{API_URL,USERNAME,PASSWORD}_{PROD,STAGING,DEV} | — | Đủ 3 key/env | — | env-system.constants.ts:19-27, be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:17-36 |
env_systems — Ops (cũ, một bộ) | SAPP_BASE_API_URL, SAPP_API_TOKEN | — | Cả 2 | Token xoay tay, không theo env | env-system.constants.ts:17-18, be/libs/constants/src/lib/sapp/sapp.constants.ts:22-25, be/libs/modules/src/lib/sapp/common.service.ts:278-302 |
env_systems — Ops DB (SQL runner) | SAPP_OPS_DB_{HOST,PORT,NAME,USERNAME,PASSWORD}_{DEV,STAGING} | — | Trừ PORT | PORT mặc định 5432; không có bộ PROD | env-system.constants.ts:28-37, be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:281-307 |
env_systems — SAP service | SAPP_SAP_{API_URL,CLIENT_ID,HMAC_SECRET}_{PROD,STAGING,DEV} | — | Đủ 3 key/env (manual-scan chỉ cần URL) | staging không dùng lại prod | env-system.constants.ts:47-55, be/libs/modules/src/lib/sapp/sap-log.common.service.ts:79-113, :340-355 |
| Redis | sapp:ops:token:{prod|staging|dev} → { token, expiresAt } | JSON | — | TTL xem R-26 | be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:66-67, be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:27-31, :171-176 |
| localStorage (trình duyệt) | mk:works:sapp:last-tool · mk:works:sapp:sidebar-collapsed · mk:works:sapp:theme-dark · mk:works:sapp:nav-groups-closed | string / "1"/"0" / JSON mảng id nhóm | — | Không đọc được storage → dùng mặc định, không lỗi | fe/src/ui/components/works/shared/last-tool.ts:10, fe/src/ui/pages/works/sapp/tools/shell.tsx:51-53, fe/src/ui/components/works/shared/use-persisted-flag.ts:15-46 |
| sessionStorage | mk:tool-unlocked:<code> = "1" | string | — | Mất khi đóng tab/phiên | fe/src/ui/components/works/shared/tool-gate.tsx:12, :111, :199 |
5. Rule & validation tìm thấy ​
| ID | Rule (ngôn ngữ nghiệp vụ) | Loại | Áp dụng ở | Bằng chứng | Nghi là bug? |
|---|---|---|---|---|---|
| R-01 | Mỗi tool có mã vĩnh viễn dạng sapp.NNN (3 chữ số, tăng dần), gắn với slug route; không bao giờ dùng lại hay đánh số lại. FE chỉ giữ mã + tên, mọi trạng thái do BE quyết | điều kiện | A-02, A-10 | fe/src/data/constants/tool-codes.ts:4-20, fe/CLAUDE.md:3-22 | Không |
| R-02 | Mã tool là duy nhất; tạo/sửa trùng mã bị từ chối; gán vào nhóm không tồn tại bị từ chối | validation | A-10 | be/libs/modules/src/lib/tool/service.ts:35-44, :162-174 | Không |
| R-03 | Trạng thái hiệu lực của tool = trạng thái nhóm và trạng thái tool; tool không thuộc nhóm coi như nhóm bật/hiện | công thức | A-02, A-07 | be/libs/modules/src/lib/tool/service.ts:105-113 | Không |
| R-04 | 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) | điều kiện | A-02 | be/libs/modules/src/lib/tool/common.service.ts:113-119 | Không |
| R-05 | "Đóng khi không chắc" (fail-closed): tool không có trong danh sách public = đóng; tool có trong registry nhưng chưa có dòng trong bảng tools cũng đóng | điều kiện | A-04, A-07 | fe/src/ui/components/works/shared/tool-availability.ts:9-28, fe/src/ui/components/works/shared/tool-gate.tsx:144-156 | Không |
| R-06 | Không đọc được danh sách trạng thái (mạng, timeout, 4xx/5xx) → mọi tool đóng và hiển thị lý do; không chọn tool đích | điều kiện | A-02, A-03, A-07 | fe/src/ui/components/works/shared/use-tools-state.ts:41-76, fe/src/ui/components/works/shared/tool-gate.tsx:130-142, fe/src/ui/pages/works/sapp/tools/index-redirect.tsx:39-47 | Không |
| R-07 | Tool chỉ được mở khi hiện và bật | điều kiện | A-04, A-07 | fe/src/ui/components/works/shared/tool-availability.ts:26-28 | Không |
| R-08 | Chọn tool đích: ưu tiên tool dùng gần nhất nếu còn mở, rồi tool mở đầu tiên theo thứ tự registry; không bao giờ đưa vào tool đóng | điều kiện | A-03 | fe/src/ui/components/works/shared/tool-availability.ts:41-54 | Không |
| R-09 | Sidebar: tool đóng không phải link, gắn nhãn "Off"; nhóm không còn tool hiện bị ẩn; nhóm chứa tool đang mở không thu được | điều kiện | A-04, A-05 | fe/src/ui/pages/works/sapp/tools/shell.tsx:267-277, :290, :334-372 | Không |
| R-10 | Sidebar tự thu thành icon khi màn rộng < 1280 px (nếu viewer chưa chọn); giao diện theo cài đặt hệ điều hành nếu chưa chọn | giới hạn | A-06 | fe/src/ui/pages/works/sapp/tools/shell.tsx:59, :94-105 | Không |
| R-11 | 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 ngày nhập = giá trị khoá); ngày không đọc được → lỗi TOOL_SECRET_INVALID | validation | A-08 | be/libs/modules/src/lib/tool/service.ts:235-260 | Không |
| R-12 | Kiểm tra mã bị từ chối khi nhóm tắt (GROUP_DISABLED) hoặc tool tắt (TOOL_DISABLED) — kiểm trước khi so mã | trạng thái | A-08 | be/libs/modules/src/lib/tool/service.ts:222-233 | Không |
| R-13 | Kiểm tra mã và đọc trạng thái theo mã không xét tool có đang ẩn không — tool ẩn vẫn đọc được trạng thái và vẫn kiểm tra mã được | điều kiện | E-08, E-09 | be/libs/modules/src/lib/tool/service.ts:125-134, :214-221, be/libs/modules/src/lib/tool/common.service.ts:161-167 | ⚠️ Observed |
| R-14 | Mở khoá chỉ lưu ở trình duyệt (sessionStorage) theo mã tool, hết khi đóng phiên; FE không gửi bằng chứng mở khoá lên API | trạng thái | A-08 | fe/src/ui/components/works/shared/tool-gate.tsx:109-113, :197-200 | ⚠️ Observed |
| R-15 | Khoá/tắt tool chỉ chặn ở giao diện: không API /sapp/* nào kiểm tra trạng thái tool hay mã bí mật (comment BE tự nhận "UX gate, not an authorization boundary") | điều kiện | A-07, A-13…A-20 | be/apps/api/src/tool/tool-public.controller.ts:74-77; Grep ToolService|ToolCommonService|verifySecret trong be/apps/api/src/sapp, be/libs/modules/src/lib/sapp = 0 kết quả | ⚠️ Observed |
| R-16 | Kiểm tra mã bí mật public không giới hạn tần suất, không cần đăng nhập (khoá "năm của ngày" chỉ có vài trăm giá trị khả dĩ) | giới hạn | A-08 | be/apps/api/src/tool/tool-public.controller.ts:79-97; Grep Throttl trong be/apps/api/src, be/libs = 0 kết quả; shared/api-docs/tools.md:192-194 | ⚠️ Observed |
| R-17 | Thông báo lỗi mở khoá theo mã: tool tắt / nhóm tắt / tool không còn / sai định dạng / lỗi cấu hình máy chủ (mã lỗi dạng đăng nhập) / mặc định | validation | A-08 | fe/src/ui/components/works/shared/tool-gate.tsx:49-67 | Không |
| R-18 | Mọi route /api/v1/sapp/* (259 route: 128 + 103 + 28) đánh dấu @Public() — không cần đăng nhập, không permission, không system API key; interceptor toàn cục bỏ qua xác thực khi có cờ public | quyền | E-13…E-21 và mọi route sub-tool | be/apps/api/src/sapp/sapp.controller.ts:157-174, be/apps/api/src/sapp/sapp-ops.controller.ts:73, :635, be/apps/api/src/sapp/sapp-26297.controller.ts:43, :79, be/apps/api/src/interceptors/grpc-auth.interceptor.ts:28-35, be/apps/api/src/app/app.module.ts:97 | ⚠️ Observed |
| R-19 | Môi trường được chọn bằng đoạn cố định trong đường dẫn (prod/staging/dev), mỗi môi trường là một route riêng — không có tham số môi trường tự do; route không khai báo cho env nào thì env đó không gọi được | điều kiện | E-13…E-21 | be/apps/api/src/sapp/sapp-ops.controller.ts:61-66, be/libs/constants/src/lib/hubspot/hubspot.enum.ts:1-5 | Không |
| R-20 | Chọn môi trường staging cho HubSpot thực chất dùng token portal prod (không có portal staging) — mọi thao tác HubSpot "staging" chạm dữ liệu prod | điều kiện | Mọi sub-tool gọi HubSpot với staging | be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26 | ⚠️ Observed |
| R-21 | Thêm option property HubSpot: chỉ portal dev; value bắt buộc (bỏ khoảng trắng), label mặc định = value; property phải là dạng danh sách; option đã có thì không thêm (trả added=false); gửi lại toàn bộ danh sách cũ + option mới ở cuối | validation | A-17 | be/apps/api/src/sapp/sapp.controller.ts:821-840, be/libs/modules/src/lib/hubspot/common.service.ts:722-789 | Không |
| R-22 | Ops passthrough mở đủ thao tác ghi trên prod (tạo môn/cơ sở/khoá/lớp/lịch/giáo viên/user/sản phẩm/đơn/giao dịch, sửa lớp/phòng/lịch, huỷ và xoá lịch, chuyển học viên, xác nhận giao dịch, resync SAP) — không kèm điều kiện chặn prod nào ở tầng dùng chung | quyền | A-18 | be/apps/api/src/sapp/sapp-ops.controller.ts:739, :799, :958, :1063, :1156, :1261, :1366, :1417, :1477, :1497, :1591, :1651, :1667, :1861, :1912, :1963, :2074, :2179, :2230, :2290, :2350 | ⚠️ Observed |
| R-23 | Ops passthrough không tự kiểm tra rule nghiệp vụ của Ops (ngày học tương lai, giá > 0, định dạng giờ…) — để Ops quyết; lỗi Ops trả về kèm câu thông báo gốc; Ops trả success=false với HTTP 200 cũng coi là lỗi | validation | A-18 | be/libs/modules/src/lib/sapp/sapp-ops.common.service.ts:73-77, :94-126 | Không |
| R-24 | Số trang/kích thước trang không phải số nguyên dương thì bị bỏ qua (dùng mặc định) thay vì gửi sang Ops | validation | A-18 | be/apps/api/src/sapp/sapp-ops.controller.ts:48-59 | Không |
| R-25 | Auto-login Ops: URL + user + mật khẩu đọc theo môi trường từ env_systems; thiếu một trong ba → lỗi 13030 SAPP_OPS_AUTH_NOT_CONFIGURED | validation | A-21 | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:58-84 | Không |
| R-26 | Token Ops giữ tới (hạn JWT − 60 s); token không có hạn → 30 phút; tối đa 24 h; nếu hạn còn lại < 30 s thì vẫn giữ 30 phút | công thức | A-21 | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:189-202, be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:77-84 | ⚠️ Observed |
| R-27 | Chỉ HTTP 401 mới kích hoạt đăng nhập lại + thử lại đúng 1 lần; 403 không thử lại | điều kiện | A-21 | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:121-134, be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:86-92 | Không |
| R-28 | Nhiều yêu cầu cùng lúc chỉ tạo một lượt đăng nhập mỗi môi trường (trong một tiến trình) | giới hạn | A-21 | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:43-49, :98-105 | Không |
| R-29 | Đăng nhập Ops lỗi → 13031; đăng nhập được nhưng không thấy token → 13032; token được dò theo danh sách trường ưu tiên, có act, cố ý loại rft (refresh token) | validation | A-21 | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:154-169, be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:43-63 | Không |
| R-30 | Tồn tại song song hai cách xác thực Ops: bộ cũ SAPP_BASE_API_URL + SAPP_API_TOKEN (một bộ cho mọi môi trường, phải xoay tay khi hết hạn) và bộ auto-login theo môi trường | trạng thái | Sub-tool dùng SappCommonService (vd 24395 products) vs Ops passthrough | be/libs/modules/src/lib/sapp/common.service.ts:278-302, be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:33-38 | Không |
| R-31 | SAP log: thiếu URL / client id / HMAC secret của môi trường → lỗi 13037 và log nêu tên key thiếu | validation | A-13, A-14, A-16 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:79-113 | Không |
| R-32 | Tra vết SAP cần ít nhất một khoá lọc trong 5 khoá (deal_id, event_id, entry_id, class_code, transaction_id); nhiều khoá thì AND; tra theo deal_id trả cả dòng phase 1 (hoá đơn, thanh toán) | validation | A-13 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:132-144, :156-164, be/libs/constants/src/lib/sapp/sap-log.constants.ts:79-89 | Không |
| R-33 | limit 1–200, áp cho từng bảng; FE mặc định 50, offset 0 | giới hạn | A-13, A-14 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:146-154, be/libs/constants/src/lib/sapp/sap-log.constants.ts:72-77, fe/src/ui/components/works/sapp/sap-log-trace.tsx:317-321 | Không |
| R-34 | Khoá lọc rỗng bị bỏ trước khi ký và gửi (chuỗi rỗng không coi là điều kiện lọc) | validation | A-13, A-14 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:357-369 | Không |
| R-35 | Kích hoạt quét thủ công và dựng callback ký sẵn bị từ chối trên prod (lỗi SAP_SCAN_NOT_ALLOWED_ON_PROD), và không có route prod | điều kiện | A-15, A-16 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:228-236, :290-296; route chỉ dev/staging be/apps/api/src/sapp/sapp.controller.ts:3991-4047 | Không |
| R-36 | Quét thủ công: triggered=false nghĩa là tính năng đang tắt (công tắc SAP_REVENUE_RECOGNITION_ENABLED), trả như kết quả bình thường; 403 và 429 có mã lỗi riêng; triggered=true chỉ là đã vào hàng đợi | trạng thái | A-15 | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:215-271 | Không |
| R-37 | Callback SAP ký sẵn: mặc định status=SUCCEEDED, role=POSITIVE; chỉ gửi trường tester nhập; kết quả dùng 1 lần trong ~300 s. Route public → bất kỳ ai gọi được cũng dựng được callback hợp lệ trên dev/staging | điều kiện | A-16 | be/apps/api/src/sapp/sapp.controller.ts:3964-3983, :4017-4047, be/libs/constants/src/lib/sapp/sap-log.constants.ts:54-64 | ⚠️ Observed |
| R-38 | SQL runner chỉ chạy câu lệnh có trong danh mục theo id; không nhận SQL do người gọi gửi; giá trị được bind qua driver | validation | A-20 | be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:62-73, :116-122, :52-60 | Không |
| R-39 | SQL runner không thể chạy trên prod: không có bộ key prod và không có route prod | điều kiện | A-20 | be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:272-307, be/apps/api/src/sapp/sapp-ops.controller.ts:2404-2442 | Không |
| R-40 | SQL: tham số thiếu/rỗng → dừng (13056), không bind NULL; placeholder còn sót sau khi thay → lỗi | validation | A-20 | be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:132-163 | Không |
| R-41 | SQL: một mục nhiều câu chạy trong một transaction; timeout 15 s/câu; SELECT tối đa 200 dòng | giới hạn | A-20 | be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:25-38, :165-174, be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:309-313 | Không |
| R-42 | SQL: lỗi DB trả nguyên thông điệp của Postgres (tên cột, ràng buộc) cho người gọi qua route public | điều kiện | A-20 | be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:181-193 | ⚠️ Observed |
| R-43 | SQL: id câu lệnh trùng giữa các danh mục tool → dịch vụ từ chối khởi động | validation | A-20 | be/libs/constants/src/lib/sapp/sapp-ops-sql.constants.ts:7-32 | Không |
| R-44 | FE phân loại trạng thái dòng log SAP theo từ khoá, ưu tiên: lỗi (FAIL, ERROR, REJECT, TIMEOUT, CANCEL, INVALID) → đang xử lý (NOT_SYNCED, PENDING, RETRY…) → thành công (SUCCESS, SYNCED, SENT…) → không rõ | công thức | A-13 | fe/src/ui/components/works/sapp/sap-log-summary.tsx:160-200 | Không |
| R-45 | Danh sách public nhận trường sắp xếp (sortBy) dạng chuỗi tự do và ghép thẳng vào câu ORDER BY | validation | E-07 | be/libs/modules/src/lib/tool/common.service.ts:109, :128, be/libs/interface/src/lib/dto/base/request.dto.ts:19-23 | ⚠️ Observed |
| R-46 | Component SecretGate (khoá bằng ngày, năm phải là 2003, kiểm tra hoàn toàn ở trình duyệt) có trong code nhưng không tool nào dùng | điều kiện | — | fe/src/ui/components/works/sapp/secret-gate.tsx:14-47, :73-74; Grep SecretGate trong fe/ chỉ ra chính file đó | ⚠️ Observed |
| R-47 | Mật khẩu/secret hệ ngoài (Ops, Ops DB, SAP HMAC, HubSpot token) và secretValue tool lưu dạng rõ; API admin trả lại secretValue | trạng thái | A-10, A-12 | be/libs/database/src/lib/entities/env/env-system.entity.ts:10-11, be/libs/database/src/lib/entities/tool/tool.entity.ts:31-32, be/libs/modules/src/lib/tool/common.service.ts:6-20 | ⚠️ Observed |
| R-48 | Tool mới seed qua migration mặc định bật + hiện + không khoá | trạng thái | A-10 | be/libs/database/migrations/1783700000000-create-tools.ts:33, :41, be/libs/database/migrations/1786300000000-seed-tool-sapp-26297.ts:14-19 | Không |
Trạng thái & chuyển trạng thái của một tool khi viewer mở (FE, ToolGate):
text
[ĐANG TẢI] --(đọc danh sách lỗi)--> [KHÔNG KIỂM TRA ĐƯỢC] (R-06)
[ĐANG TẢI] --(code không có trong danh sách / isVisible=false)--> [CHƯA MỞ] (R-05)
[ĐANG TẢI] --(isEnabled=false)--> [ĐÃ BỊ TẮT]
[ĐANG TẢI] --(secretType ≠ none và phiên chưa mở khoá)--> [ĐANG KHOÁ]
[ĐANG KHOÁ] --(verify valid=true)--> [MỞ] (nhớ trong sessionStorage đến hết phiên)
[ĐANG TẢI] --(visible & enabled & (none hoặc đã mở khoá))--> [MỞ]Trạng thái token Ops mỗi môi trường (BE, SappAuthCommonService):
text
[CHƯA CÓ TOKEN] --(gọi lần đầu → login ok)--> [TOKEN TRONG REDIS]
[TOKEN TRONG REDIS] --(hết expiresAt)--> [CHƯA CÓ TOKEN]
[TOKEN TRONG REDIS] --(Ops trả 401)--> xoá token → login lại → thử lại 1 lần6. Quyền, tích hợp, thông báo, job ​
| Loại | Chi tiết | Bằng chứng |
|---|---|---|
| Quyền — workspace FE | /works/sapp/* không có tường đăng nhập; FE chỉ đọc route public để quyết định hiện/ẩn/khoá | fe/src/ui/components/works/shared/use-tools-state.ts:25-38, fe/src/data/models/tool.interface.ts:38-54 |
| Quyền — tool public | /tools/public, /tools/public/code/:code, /tools/public/code/:code/verify: @Public() | be/apps/api/src/tool/tool-public.controller.ts:29-30, :47-48, :79-80 |
| Quyền — tool admin | /tools* yêu cầu đăng nhập + quyền tools (read/create/update/delete) | be/apps/api/src/tool/tool.controller.ts:35-38, :50-53, :67-70, :100-102, :117-119, :135-137 |
| Quyền — nhóm tool | /tool-groups* yêu cầu quyền tool_groups | be/apps/api/src/tool-group/tool-group.controller.ts:32-34, :49-51, :66-68 |
| Quyền — env_systems | /env-systems* yêu cầu quyền env_systems (read/create/update/delete) | be/apps/api/src/env-system/env-system.controller.ts:32-34, :48-50, :63-65, :80-82, :98-100 |
| Quyền — SAPP | Toàn bộ 259 route /api/v1/sapp/* @Public(), gồm route ghi trên prod (R-18, R-22). SystemApiKeyGuard có sẵn nhưng chỉ dùng ở app-version / erd-version / resource | be/apps/api/src/sapp/sapp.controller.ts:174, be/apps/api/src/sapp/sapp-ops.controller.ts:635, be/apps/api/src/sapp/sapp-26297.controller.ts:79, be/apps/api/src/guards/system-api-key.guard.ts:10-25 |
| Tích hợp ngoài — HubSpot CRM API | Token theo môi trường (prod, dev; staging = prod) đọc từ env_systems lúc gọi; thiếu → 12001 HUBSPOT_ENV_NOT_CONFIGURED | be/libs/modules/src/lib/hubspot/common.service.ts:47-58, be/libs/constants/src/lib/hubspot/hubspot.constants.ts:10-32 |
| Tích hợp ngoài — SAPP Ops REST API | Đăng nhập POST {baseUrl}/api/v1/auth/login, bearer token cache Redis; timeout login 30 s; request Ops thường timeout 10 phút | be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:38-41, :69-74, be/libs/constants/src/lib/sapp/sapp.constants.ts:38 |
| Tích hợp ngoài — SAP service | Trace/scan-runs ký HMAC (secret chỉ ở BE), timeout 30 s; manual-scan GET không xác thực; sign-callback gửi client id + secret trong body tới signer | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:56-68, :238-242, :298-315, be/libs/constants/src/lib/sapp/sap-log.constants.ts:42-70 |
| Tích hợp ngoài — Postgres SAPP Ops | Kết nối trực tiếp dev/staging cho SQL runner | be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:83-104, :166-174 |
| Hạ tầng — Redis | Token Ops sapp:ops:token:{env} | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:109-111, :136-144, :176 |
| Wiring | SappCommonModule cung cấp 6 service dùng chung (Auth, Common, SapLog, Ops, OpsSql, 26297); SappModule gắn 3 controller | be/libs/modules/src/lib/sapp/module.ts:11-30, be/apps/api/src/sapp/sapp.module.ts:7-11 |
| APP (Flutter) | Không có màn SAPP; chỉ màn quản trị tool/nhóm tool (Grep -i sapp trong app/lib = 3 dòng, đều là gợi ý/ghi chú mã tool) | app/lib/models/tool.dart:3, app/lib/screens/tool_form_screen.dart:168, app/lib/screens/tool_group_form_screen.dart:153 |
| Thông báo (mail / push / MQTT / Discord) | Không thấy — Grep mqtt|mailService|discord|telegram|@Cron trong be/apps/api/src/sapp/*.ts, be/libs/modules/src/lib/sapp/*.ts = 0 kết quả | (kết quả Grep) |
| Job / cron | Không có job phía mind_keep; cron quét doanh thu tuần nằm ở SAP service (ngoài hệ thống) | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:215-217; Grep sapp trong be/apps/schedule/src = 0 kết quả |
7. Drift — tài liệu nói khác code ​
| ID | Tài liệu (file + section) | Tài liệu nói | Code đang làm | Bằng chứng |
|---|---|---|---|---|
| DR-01 | shared/api-docs/sapp.md:12 §Overview | HubSpot "across two portals (prod / dev)" | Ba môi trường; staging dùng lại credential portal prod | be/libs/constants/src/lib/hubspot/hubspot.constants.ts:14-31 |
| DR-02 | shared/api-docs/sapp.md:14 §Overview | "the three routes below are currently marked @Public() … (temporary)" | Toàn bộ 259 route SAPP đều @Public(), kể cả route ghi prod | be/apps/api/src/sapp/sapp.controller.ts:174, be/apps/api/src/sapp/sapp-ops.controller.ts:635, be/apps/api/src/sapp/sapp-26297.controller.ts:79 |
| DR-03 | shared/api-docs/sapp.md:1128-1131 §SAPP Ops authentication | Token dò theo access_token/accessToken/token/id_token/idToken/jwt; "chưa kiểm với API thật" | Danh sách có thêm act — và comment code nói đây là trường đang thực sự dùng (data.tokens.act) | be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:43-63 |
| DR-04 | shared/api-docs/sapp.md:1096-1098 §SAPP Ops authentication | Cache token tới exp − 60 s; 30 phút nếu token opaque; tối đa 24 h | Thêm nhánh không ghi trong doc: hạn còn < 30 s → vẫn cache 30 phút | be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:195-200 |
| DR-05 | shared/api-docs/sapp.md:2474 §SAPP Ops passthrough; be/.agents/maps/modules/tool.md §3 ("~20 thao tác Ops") | "Twenty read/write operations" | 33 thao tác mỗi môi trường (35 ở dev/staging tính cả 2 route SQL) | Đếm route @(Get|Post|Put|Delete)('<env>/sapp-ops/…') trong be/apps/api/src/sapp/sapp-ops.controller.ts:634-2442 |
| DR-06 | shared/api-docs/sapp.md:2241 §SAP log trace | "Two read-only endpoints" | Section còn có manual-scan (kích hoạt quét) và sign-callback (dựng callback ký) — không chỉ đọc | be/apps/api/src/sapp/sapp.controller.ts:3991-4047 |
| DR-07 | shared/api-docs/tools.md:24-25 §Overview | Route /tools/public/* "only expose effectively visible tools" | GET /tools/public/code/:code và verify trả/kiểm cả tool đang ẩn | be/libs/modules/src/lib/tool/service.ts:125-134, :214-221 |
| DR-08 | shared/api-docs/tools.md:29-32; comment fe/src/data/models/tool.interface.ts:8-12 | "The public by-code route (GET /tools/code/:code)" | GET /tools/code/:code yêu cầu quyền tools:read; route public là /tools/public/code/:code | be/apps/api/src/tool/tool.controller.ts:50-53 |
| DR-09 | shared/api-docs/tools.md:11 §Overview | Registry ở mind_keep_cms_ui/src/data/constants/tool-codes.ts | Đường dẫn thực tế fe/src/data/constants/tool-codes.ts | fe/src/data/constants/tool-codes.ts:1-57 |
| DR-10 | shared/api-docs/tool-groups.md:30-35 | Nhóm sapp có sapp.* (10) tool | Registry có 13 mã sapp.*; migration seed thêm sapp.011–013 | fe/src/data/constants/tool-codes.ts:32-44, be/libs/database/migrations/1786300000000-seed-tool-sapp-26297.ts:14-19 |
8. Câu hỏi cho BA (code không trả lời được) ​
| ID | Câu hỏi | Vì sao cần | Chặn bước sau? |
|---|---|---|---|
| Q-01 | Toàn bộ API /api/v1/sapp/* (259 route) không cần đăng nhập, kể cả ghi dữ liệu thật trên prod (Ops: tạo user/lớp/đơn/giao dịch, xoá lịch, confirm giao dịch, resync SAP — R-22; econtract retry prod). Đây là cố ý (công cụ nội bộ, chấp nhận rủi ro) hay bug/nợ bảo mật? Ai được phép dùng? (R-18, R-22, DR-02) | Quyết định ghi thành BR ("tool mở cho mọi người có link") hay Open Issue bảo mật; ảnh hưởng mọi FS nhóm | Có |
| Q-02 | Chọn "staging" cho HubSpot thực chất ghi vào portal prod (R-20). Người dùng tool có biết điều này không; các thao tác ghi HubSpot "staging" của sub-tool (tạo contact/deal/ticket) có được phép chạm dữ liệu prod? | Viết đúng rule môi trường trong FS mọi nhóm dùng HubSpot | Có |
| Q-03 | Trên DB prod hiện tại tool nào đang bị tắt/ẩn/khoá và loại khoá gì? Code seed mặc định "không khoá" (R-48) nên không suy ra được | Mô tả quyền truy cập thực tế từng tool trong FS | Có |
| Q-04 | Đối tượng sử dụng /works/sapp là ai (dev/QA nội bộ, BA, đội SAPP)? Không có đăng nhập nên hệ thống không phân biệt vai trò | Viết Actor/role trong FS | Có |
| Q-05 | Khoá tool chỉ là UX gate: API không kiểm trạng thái tool (R-15), mở khoá chỉ ở sessionStorage (R-14), verify không giới hạn tần suất (R-16). Đây là mức bảo vệ được chấp nhận hay cần coi là rủi ro? | Ghi BR "khoá tool" đúng bản chất | Không |
| Q-06 | Tool đang ẩn vẫn đọc được trạng thái và kiểm tra mã qua route public (R-13, DR-07) — cố ý hay bug? | Quyết định BR hay OQ | Không |
| Q-07 | sortBy của danh sách public ghép thẳng vào ORDER BY (R-45) — cố ý hay bug? | Rủi ro kỹ thuật cần ghi OQ | Không |
| Q-08 | Nhánh cache token 30 phút khi hạn còn < 30 s (R-26) — cố ý hay bug? (có thể giữ token đã chết, được cứu bởi retry 401) | Ghi rule token đúng | Không |
| Q-09 | Hai cơ chế xác thực Ops cùng tồn tại (R-30). Sub-tool nào còn dùng SAPP_API_TOKEN xoay tay; có kế hoạch bỏ không? Ai chịu trách nhiệm xoay token? | Mô tả vận hành/điều kiện tiên quyết trong FS | Không |
| Q-10 | Route dựng callback SAP ký sẵn trên dev/staging là public (R-37) — chấp nhận việc ai cũng giả được callback SAP trên staging? | Rủi ro, ghi OQ | Không |
| Q-11 | SQL runner trả nguyên thông báo lỗi Postgres qua route public (R-42) — cố ý (để tester sửa công thức) hay cần che bớt? | Quyết định BR hay OQ | Không |
| Q-12 | SecretGate (khoá cứng năm 2003, chỉ ở trình duyệt) không được dùng (R-46) — di sản cần xoá hay còn kế hoạch dùng? | Tránh mô tả nhầm như tính năng đang chạy | Không |
| Q-13 | Secret hệ ngoài và secretValue lưu dạng rõ trong DB (R-47) — đã được chấp nhận? | Ghi ràng buộc bảo mật/NFR | Không |
| Q-14 | Việc #39FE/#41BE còn mở: đã xác nhận mọi mã sapp.001–sapp.013 có dòng trong tools dưới nhóm bật+hiện trên prod chưa? (fail-closed → thiếu dòng = tool đóng, R-05) | Điều kiện tiên quyết khi phát hành tool | Không |
| Q-15 | Tên chuẩn của tool là tên trong TOOL_CODES/DB hay nhãn sidebar? Có chỗ khác nhau, vd sapp.010 "SAPP 26878: Create deal instance" vs nhãn "Test data theo luồng" (fe/src/data/constants/tool-codes.ts:41, fe/src/ui/pages/works/sapp/tools/registry.ts:101) | Thống nhất tên trong FS | Không |
| Q-16 | Mục đích nghiệp vụ của cách nhóm tool theo số ticket SAPP (20603, 24395, …) và ai quyết định thêm/bỏ tool khỏi workspace? | Viết phần tổng quan/BRD | Không |
9. Nhật ký nguồn đã đọc ​
| File / section | Mục đích |
|---|---|
ba/_workflow/templates/feature-inventory/Template.md | Khung §1–§9 |
ba/system-profile.md §3 | Công thức truy vết |
ba/projects/2026-SAPP-Works-tools/project-context.md | Phạm vi dự án, nhóm tài liệu |
ba/projects/2026-SAPP-Works-tools/working/ai-drafts/feature-inventory-hubspot-20260930.md (đầu file) | Thống nhất định dạng với inventory nhóm khác |
fe/CLAUDE.md (§Tool codes, §DatePicker) | Luật TOOL_CODES |
fe/app/works/sapp/page.tsx, fe/app/works/sapp/tools/page.tsx, fe/app/works/sapp/tools/layout.tsx | Route hub, index, layout |
fe/src/ui/pages/works/sapp/tools/registry.ts, index-redirect.tsx, shell.tsx | Nhóm tool, chọn tool đích, sidebar, lưu trạng thái trình duyệt |
fe/src/ui/components/works/shared/{tool-availability.ts, tool-gate.tsx, use-tools-state.ts, tools-state-context.tsx, last-tool.ts, use-persisted-flag.ts} | Cơ chế đóng/mở, khoá, ghi nhớ |
fe/src/data/constants/tool-codes.ts | Registry mã tool |
fe/src/data/models/tool.interface.ts, fe/src/data/enums/tool.enum.ts | Shape public, loại khoá |
fe/src/data/services/cms/(tools)/get-public.service.ts, verify-secret.service.ts | Route FE gọi |
fe/src/ui/components/works/sapp/secret-gate.tsx + Grep SecretGate | Component khoá cũ, xác nhận không dùng |
fe/src/ui/components/works/sapp/sap-log-trace.tsx (301-360), sap-log-summary.tsx (160-238) + Grep importer | Tra vết SAP phía FE, luật màu trạng thái |
fe/src/ui/components/works/sapp/ (Grep ^export trong shared.tsx, utils.ts, select.tsx, checkbox.tsx, date-picker.tsx, hubspot-property-field.tsx; property-tool.tsx:25-30) | Liệt kê component dùng chung |
fe/src/data/constants/api.ts (178-341) | URL SAPP phía FE, kiểu env |
fe/src/data/services/sapp/sap-log.service.ts (1-40) + ls fe/src/data/services/sapp | Service FE dùng chung |
fe/app/cms/(tools)/tools/page.tsx | Màn admin tool web |
be/apps/api/src/tool/tool-public.controller.ts, tool.controller.ts (20-70 + Grep), tool.module.ts (Grep) | API tool public/admin |
be/apps/api/src/tool-group/tool-group.controller.ts (Grep) | Quyền nhóm tool |
be/libs/modules/src/lib/tool/service.ts, common.service.ts | Rule hiệu lực, verify, danh sách public |
be/libs/database/src/lib/entities/tool/tool.entity.ts, tool-group.entity.ts | Bảng tools, tool_groups |
be/libs/interface/src/lib/dto/tool/tool.dto.ts (Grep + 175-190), be/libs/interface/src/lib/dto/base/request.dto.ts | DTO lọc/verify, phân trang |
be/libs/database/migrations/1783700000000-create-tools.ts (Grep), 1786300000000-seed-tool-sapp-26297.ts, Grep seed 012/013 | Seed tool |
be/apps/api/src/decorators/public.decorator.ts, be/apps/api/src/guards/system-api-key.guard.ts + Grep usage | Cơ chế public / API key |
be/apps/api/src/interceptors/grpc-auth.interceptor.ts (20-45), be/apps/api/src/app/app.module.ts (Grep), be/apps/api/src/main.ts (15-52) | Xác thực toàn cục, versioning, CORS |
be/apps/api/src/sapp/sapp.module.ts, sapp.controller.ts (150-200, 815-847, 3930-4050 + Grep route), sapp-ops.controller.ts (1-200 + Grep route), sapp-26297.controller.ts (40-78 + Grep route) | Quyền, route theo env, đếm route |
be/libs/modules/src/lib/sapp/module.ts | Wiring service |
be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts | Auto-login Ops |
be/libs/modules/src/lib/sapp/sap-log.common.service.ts | SAP log trace |
be/libs/modules/src/lib/sapp/sapp-ops.common.service.ts (Grep outline, 79-135, 280-300) | Ops passthrough plumbing |
be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts | SQL runner |
be/libs/modules/src/lib/sapp/common.service.ts (Grep outline, 255-313) | Phần credential Ops dùng chung (bộ cũ) |
be/libs/modules/src/lib/hubspot/common.service.ts (20-60, 715-800) | Token HubSpot, thêm option |
be/libs/modules/src/lib/env-system/env-system-map.common.service.ts, be/apps/api/src/env-system/env-system.controller.ts (Grep), be/libs/database/src/lib/entities/env/env-system.entity.ts | env_systems |
be/libs/constants/src/lib/{env-system/env-system.constants.ts, hubspot/hubspot.constants.ts, hubspot/hubspot.enum.ts, sapp/sapp-ops.constants.ts, sapp/sap-log.constants.ts, sapp/sapp.constants.ts, sapp/sapp-26878-sql.constants.ts (270-315), sapp/sapp-ops-sql.constants.ts} | Key, TTL, giới hạn, timeout |
be/libs/interface/src/lib/dto/sapp/sap-log.dto.ts (Grep) | DTO SAP log |
Grep Throttl, ToolService|verifySecret (sapp), mqtt|mail|discord|telegram|@Cron (sapp), sapp (be/apps/schedule/src) | Xác nhận không có throttle / kiểm tra tool / thông báo / job |
app/lib Grep -i sapp; app/lib/services/tool_service.dart, tool_group_service.dart, app/lib/screens/tool_admin_list_screen.dart (Grep) | Xác nhận APP không có màn SAPP |
shared/api-docs/sapp.md §Overview (1-32), §SAPP Ops authentication (1084-1133), §SAP log trace (2239-2275, 2345-2350), §add option (2427-2445), §SAPP Ops passthrough (2472-2520), §SQL runner (2674-2722) | Đối chiếu doc → Drift |
shared/api-docs/tools.md (8-33, 64-73, 134-200 + Grep) | Đối chiếu doc tool |
shared/api-docs/tool-groups.md (30-40), shared/api-docs/env-system.md (1-30 Grep) | Đối chiếu doc nhóm tool, env_systems |
shared/integration/README.md dòng #39FE, #40BE, #41BE (Grep sapp|works|tool) | Lịch sử fail-closed, verify public, việc còn mở |
shared/runbooks/sapp/README.md (đầu file) | Bối cảnh vận hành SAPP |
be/.agents/maps/modules/tool.md (6-125) | Bản đồ module tool/SAPP — đối chiếu |