Giao diện
Nền tảng dùng chung của cụm tool SAPP (/works/sapp/tools) - FS Overview ​
File tổng quan + index của FS. Mỗi User Story là 1 file riêng trong cùng thư mục (
US-P0X-<slug>.md). Các phần dùng chung (tổng quan, flow tổng, related features, NFR, Open Questions, References) đặt tập trung tại đây — file US chỉ tham chiếu ID, không lặp lại. As-built: tài liệu mô tả hành vi code tại commite77c47a, dựng từ inventory đã qua Gate R1 — chưa gọi thử API, chưa chạy màn nào. FS của 6 nhóm sub-tool link vào đây cho: quyền truy cập (NFR-P-01), khoá tool (NFR-P-02), môi trường (NFR-P-03, §1.6) và các dịch vụ dùng chung (US-P05…P09).
| Field | Value |
|---|---|
| Doc ID | FS-SAPP-PLATFORM |
| Mode | B – As-built |
| As-built tại commit | e77c47a |
| Last Updated | 2026-09-30 |
| Author | AI (lane ba/) |
| Reviewers | BA |
| Status | DRAFT |
| Figma Project | N/A — as-built, không có Figma |
| Related BRD | ../../brd/brd-as-built-v0.1-20260930.md |
| Related Impact Matrix | N/A — Mode B |
1. Tổng quan dự án ​
Workspace /works/sapp/tools là một khung web chung chứa 13 công cụ (sub-tool sapp.001–sapp.013) phục vụ các ticket SAPP (HubSpot, eContract 20603, 24395, 23954, 26878, 26297). FS này mô tả phần dùng chung cho mọi sub-tool: điều hướng và sidebar, cơ chế bật/tắt/ẩn/khoá tool, quản trị trạng thái tool và cấu hình hệ ngoài theo môi trường, cùng 5 dịch vụ BE mà sub-tool gọi (tra vết log SAP và quét doanh thu, dựng callback SAP, thêm option property HubSpot dev, passthrough SAPP Ops, chạy SQL danh mục trên DB Ops). Người dùng: người dùng tool (chưa xác định — OQ-P-13) và Admin CMS.
1.1 Bối cảnh ​
- Không có tường đăng nhập ở
/works/*; hệ thống không phân biệt người dùng tool (inventory §6). Việc giới hạn tool dựa trên trạng thái tool do Admin đặt và mã bí mật (NFR-P-02). - Các tool gọi nhiều hệ ngoài (HubSpot, SAPP Ops REST + DB, SAP service) trên nhiều môi trường; BE giữ credential để trình duyệt không bao giờ cầm (NFR-P-04).
- Lịch sử: cổng chặn từng "mở khi không chắc" (fail-open), đã đổi sang fail-closed (
shared/integration/README.mddòng #39FE;fe/src/ui/components/works/shared/tool-gate.tsx:78-83).
1.2 Mục tiêu ​
[Assumption] — BA chưa trả lời G-05 / OQ-P-18. Giả định làm việc: cho đội làm ticket SAPP một chỗ duy nhất để dựng dữ liệu test và tra cứu trên các hệ SAPP theo đúng môi trường, không cần cầm credential hệ ngoài. Không có KPI được xác nhận.
1.3 In Scope ​
Phạm vi đã truy vết (inventory platform §1):
- Điều hướng
/works/sapp→/works/sapp/tools, chọn tool đích, shell (sidebar, breadcrumb, giao diện, ghi nhớ) — US-P01. - Cổng chặn tool (tải trạng thái, fail-closed, ẩn / tắt / khoá, mở khoá bằng mã) — US-P02.
- Quản trị tool / nhóm tool (web
/cms/tools, app mobile, API/tools,/tool-groups) — US-P03. - Cấu hình hệ ngoài theo môi trường (
env_systems) — US-P04. - Dịch vụ dùng chung: SAP log trace + scan-runs + manual-scan (US-P05), sign-callback (US-P06), thêm option property HubSpot dev (US-P07), SAPP Ops passthrough + auto-login + ping (US-P08), Ops SQL runner + panel SQL dùng chung (US-P09).
- Quyền truy cập của toàn bộ controller
be/apps/api/src/sapp/*.controller.ts(NFR-P-01).
1.4 Out Of Scope ​
- Hành vi riêng của 13 sub-tool → 6 FS nhóm (§3).
- Logic nghiệp vụ trong dịch vụ SAPP chung của từng ticket (econtract, 23954, 24395, 26878, 26297) — chỉ ghi phần credential dùng chung.
- Nội dung danh mục SQL
SAPP_26878_SQL_STATEMENTS,s26297.*— chỉ ghi cơ chế chạy. - Bên trong hệ ngoài (HubSpot, SAP service, SAPP Ops, LMS); workspace
/works/naucode-kahrs(dùng chung cổng chặn nhưng ngoài dự án). - Chi tiết UI app mobile quản trị tool (chỉ ghi điểm vào + field chính).
1.5 Roles And Permissions ​
| Role ID | Role Name | Description | Permission Summary |
|---|---|---|---|
| R1 | Người dùng tool | Bất kỳ ai mở /works/sapp/* — Assumption (OQ về G-01): đối tượng cụ thể chưa xác nhận (OQ-P-13) | Không đăng nhập. Thấy/mở tool theo trạng thái tool (NFR-P-02); gọi được mọi API /api/v1/sapp/* (NFR-P-01) |
| R2 | Admin CMS | Tài khoản CMS đăng nhập — Fact | Quyền tools:*, tool_groups:*, env_systems:* (read/create/update/delete) — be/apps/api/src/tool/tool.controller.ts:35-137, be/apps/api/src/tool-group/tool-group.controller.ts:32-116, be/apps/api/src/env-system/env-system.controller.ts:32-100 |
1.6 Môi trường ​
Môi trường được chọn bằng đoạn cố định trong đường dẫn API (/api/v1/sapp/{prod|staging|dev}/…), mỗi môi trường là một route riêng; route không khai báo cho môi trường nào thì môi trường đó không gọi được (be/apps/api/src/sapp/sapp-ops.controller.ts:61-66, be/libs/constants/src/lib/hubspot/hubspot.enum.ts:1-5).
| Hệ ngoài | prod | staging | dev | Bằng chứng |
|---|---|---|---|---|
| HubSpot CRM | Portal prod (SAPP_PROD_HUBSPOT_*) | ⚠️ = portal prod — cố ý theo comment code: "Staging is a client-facing environment selection only — it deliberately reuses the prod portal credentials (there is no dedicated staging portal)". Mọi thao tác HubSpot "staging" chạm dữ liệu prod (OQ-P-03) | Portal dev (SAPP_DEV_HUBSPOT_*) | be/libs/constants/src/lib/hubspot/hubspot.constants.ts:14-31 |
| SAPP Ops REST (tự đăng nhập) | SAPP_OPS_*_PROD | SAPP_OPS_*_STAGING | SAPP_OPS_*_DEV | be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:17-36 |
| SAPP Ops REST (bộ cũ) | Một bộ SAPP_BASE_API_URL + SAPP_API_TOKEN cho mọi môi trường — môi trường thật phụ thuộc giá trị đang cấu hình (G-09) | be/libs/constants/src/lib/sapp/sapp.constants.ts:22-25 | ||
| Postgres SAPP Ops (SQL runner) | Không có key, không có route | SAPP_OPS_DB_*_STAGING | SAPP_OPS_DB_*_DEV | be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:272-307 |
| SAP service | SAPP_SAP_*_PROD | SAPP_SAP_*_STAGING (không dùng lại prod) | SAPP_SAP_*_DEV | be/libs/modules/src/lib/sapp/sap-log.common.service.ts:79-113 |
| Redis mind_keep (token Ops) | sapp:ops:token:prod | sapp:ops:token:staging | sapp:ops:token:dev | be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:66-67 |
Chi tiết key: US-P04.
1.7 Chốt chặn prod có thật ​
Chỉ những chỗ dưới đây thực sự không thể ghi prod ở tầng BE (Fact). Mọi chỗ khác — gồm Ops passthrough (US-P08) và HubSpot qua "staging" — đều có đường ghi prod (OQ-P-02, OQ-P-03).
| Chốt chặn | Cơ chế chặn | US | Bằng chứng |
|---|---|---|---|
| Ops SQL runner | Không có bộ key DB prod và không có route prod; chỉ chạy câu trong danh mục, không nhận SQL thô | US-P09 | be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:272-307, be/apps/api/src/sapp/sapp-ops.controller.ts:2404-2442, be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:62-73 |
| Quét doanh thu thủ công (manual-scan) | Không có route prod và dịch vụ từ chối prod (13050) | US-P05 | be/apps/api/src/sapp/sapp.controller.ts:3991-4015, be/libs/modules/src/lib/sapp/sap-log.common.service.ts:228-236 |
| Dựng callback SAP (sign-callback) | Không có route prod và dịch vụ từ chối prod (13050) | US-P06 | be/apps/api/src/sapp/sapp.controller.ts:4017-4047, be/libs/modules/src/lib/sapp/sap-log.common.service.ts:290-296 |
| Thêm option property HubSpot | Chỉ có route dev (môi trường cố định dev trong code) | US-P07 | be/apps/api/src/sapp/sapp.controller.ts:821-846, :1101 |
| (FS nhóm) Tool 26297 | Không có route prod | FS 26297 | inventory platform X-5 |
2. Luồng tổng quan của dự án ​
text
[Admin CMS] ── US-P04 cấu hình env_systems (URL/credential theo môi trường)
└── US-P03 bật/tắt, ẩn/hiện, khoá tool + nhóm
[Người dùng tool]
/works/sapp ──→ US-P01 chọn tool đích / sidebar
↓ mở tool
US-P02 cổng chặn (fail-closed → tắt / ẩn / khoá → mở khoá)
↓ tool mở
Sub-tool (FS nhóm) ──gọi──→ dịch vụ dùng chung:
├─ US-P05 SAP log / đợt quét / quét thủ công ──→ SAP service
├─ US-P06 dựng callback SAP đã ký ────────────→ SAP service
├─ US-P07 thêm option property ──────────────→ HubSpot dev
├─ US-P08 Ops passthrough (auto-login) ───────→ SAPP Ops REST
└─ US-P09 SQL danh mục ───────────────────────→ Postgres SAPP Ops (dev/staging)
⚠️ Mọi API /api/v1/sapp/* gọi được trực tiếp, không qua cổng chặn (NFR-P-01)3. Các tính năng liên quan ​
| Mã | Tính năng liên quan | Link tài liệu | Loại liên quan | Mục bị ảnh hưởng ở feature kia | Mục ảnh hưởng ở feature hiện tại | Mô tả ảnh hưởng |
|---|---|---|---|---|---|---|
| REL-01 | FS HubSpot (sapp.001–004) | 00-overview | Be Affected | US-H01…H06 | US-P01, US-P02, US-P04, NFR-P-01, NFR-P-03 | Chạy trong shell + cổng chặn; token HubSpot theo môi trường; staging = portal prod |
| REL-02 | FS 20603 eContract (sapp.005, 012, 013) | 00-overview | Be Affected | US-E01…E06 | US-P01, US-P02, US-P04, NFR-P-01 | Shell + cổng chặn; key DB econtract prod trong env_systems |
| REL-03 | FS 24395 (sapp.006, 007) | 00-overview | Be Affected | US-I01…I06 | US-P08 BR-12, NFR-P-03 | Bulk product dùng bộ xác thực Ops cũ; tab "Staging" ghi HubSpot prod |
| REL-04 | FS 23954 (sapp.008, 009) | 00-overview | Be Affected | US-T01…T05 | US-P01, US-P02, NFR-P-01, NFR-P-03 | Shell + cổng chặn; HubSpot theo môi trường |
| REL-05 | FS 26878 (sapp.010) | 00-overview | Be Affected | US-D02, US-D03, US-D17, US-D18 | US-P05, US-P06, US-P07, US-P08, US-P09 | Sub-tool duy nhất dùng SAP log / quét / callback / option / passthrough |
| REL-06 | FS 26297 (sapp.011) | 00-overview | Be Affected | US-S01, US-S02 | US-P08 (auto-login), US-P09 (panel SQL) | Dùng chung đăng nhập Ops và panel/SQL runner |
| REL-07 | Workspace /works/naucode-kahrs | — (ngoài dự án) | Be Affected | Cổng chặn của workspace đó | US-P02 | Dùng chung component cổng chặn |
| REL-08 | SAP service (hệ ngoài) | shared/api-docs/sapp.md §SAP log trace | Affects | — | US-P05, US-P06 | Cron quét tuần, bộ ký, webhook nằm ở SAP service; công tắc SAP_REVENUE_RECOGNITION_ENABLED |
| REL-09 | SAPP Ops REST API + DB (hệ ngoài) | shared/api-docs/sapp.md §SAPP Ops passthrough / §SQL runner | Affects | — | US-P08, US-P09 | Rule nghiệp vụ Ops do Ops quyết; lỗi Ops chuyển nguyên câu |
| REL-10 | HubSpot CRM API (hệ ngoài) | shared/api-docs/sapp.md §add option | Affects | — | US-P07, NFR-P-03 | HubSpot thay cả mảng option; option theo từng loại đối tượng |
4. User Story Index ​
| US ID | Tên User Story | File | Role | Priority | Status |
|---|---|---|---|---|---|
| US-P01 | Mở workspace SAPP, duyệt sidebar và mở một tool | US-P01-hub-mo-tool.md | R1 | N/A — as-built | Draft |
| US-P02 | Truy cập tool đang bật / ẩn / khoá (mở khoá bằng mã bí mật) | US-P02-khoa-tool.md | R1 | N/A — as-built | Draft |
| US-P03 | Quản trị trạng thái tool và nhóm tool | US-P03-quan-tri-trang-thai-tool.md | R2 | N/A — as-built | Draft |
| US-P04 | Cấu hình kết nối hệ ngoài theo môi trường (env_systems) | US-P04-cau-hinh-env-systems.md | R2 | N/A — as-built | Draft |
| US-P05 | Tra vết log SAP và theo dõi / kích hoạt đợt quét doanh thu | US-P05-sap-log-va-quet-doanh-thu.md | R1 (qua 26878) | N/A — as-built | Draft |
| US-P06 | Đóng vai SAP: dựng callback đã ký | US-P06-callback-sap.md | R1 (qua 26878) | N/A — as-built | Draft |
| US-P07 | Thêm option vào property danh sách của HubSpot dev | US-P07-option-property-hubspot-dev.md | R1 (qua 26878) | N/A — as-built | Draft |
| US-P08 | Đọc / ghi SAPP Ops qua passthrough (auto-login, kiểm tra kết nối) | US-P08-ops-passthrough.md | R1 (qua 26878; auto-login cả 26297) | N/A — as-built | Draft |
| US-P09 | Chạy câu SQL đã lập danh mục trên DB Ops | US-P09-ops-sql-runner.md | R1 (qua 26878, 26297) | N/A — as-built | Draft |
Status
Draft= as-built chờ Gate R2.
Truy vết hành động inventory → US: A-01, A-03…A-07, A-09 → P01 · A-02, A-08 → P02 · A-10, A-11 → P03 · A-12 → P04 · A-13…A-15 → P05 · A-16 → P06 · A-17 → P07 · A-18, A-19, A-21 → P08 · A-20 → P09 (đủ 21/21).
5. Non-functional Requirements ​
| ID | Requirement | Applies To (US/màn/API) | Acceptance Criteria |
|---|---|---|---|
| NFR-P-01 | Toàn bộ API /api/v1/sapp/* (259 route) là @Public() — không cần đăng nhập, không permission, không system API key, kể cả route ghi prod. Fact (hiện trạng tại e77c47a), ⚠️ Observed — cố ý hay bug: OQ-P-01. Đếm decorator: sapp.controller.ts 128 · sapp-ops.controller.ts 103 · sapp-26297.controller.ts 28. Interceptor xác thực toàn cục bỏ qua khi có cờ public; guard system API key có sẵn nhưng chỉ dùng ở app-version / erd-version / resource. Bằng chứng: 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, be/apps/api/src/guards/system-api-key.guard.ts:10-25. Tài liệu API nói khác (DR-P-02) | Mọi route SAPP, mọi FS nhóm (US-P05…P09 và toàn bộ route của sub-tool) | Gọi bất kỳ route /api/v1/sapp/* (kể cả prod/sapp-ops/users POST) không kèm token / API key → không bị từ chối vì xác thực (hành vi hiện tại). FS nhóm link mục này thay vì mô tả lại quyền |
| NFR-P-02 | Khoá / tắt / ẩn tool chỉ chặn ở giao diện (FE); cổng chặn fail-closed; trạng thái mở khoá nằm trong sessionStorage. (a) FE đóng tool khi không chắc: không có trong danh sách public, chưa có dòng DB, hoặc đọc trạng thái lỗi. (b) Không API /sapp/* nào kiểm trạng thái tool hay mã bí mật — comment BE tự nhận "UX gate, not an authorization boundary". (c) Mở khoá lưu mk:tool-unlocked:<code> trong sessionStorage theo phiên, FE không gửi bằng chứng lên API. (d) Route kiểm mã public, không giới hạn tần suất. (b)(c)(d) là ⚠️ Observed (OQ-P-04, OQ-P-05). Bằng chứng: fe/src/ui/components/works/shared/tool-availability.ts:9-28, fe/src/ui/components/works/shared/tool-gate.tsx:12, :109-113, :130-156, :197-200, be/apps/api/src/tool/tool-public.controller.ts:74-97; Grep ToolService|verifySecret trong be/apps/api/src/sapp, be/libs/modules/src/lib/sapp = 0 | US-P01, US-P02, US-P03; mọi sub-tool | (a) Xoá dòng tools của một mã → tool hiện "Tool chưa mở". (b) Tắt tool rồi gọi thẳng API của nó → vẫn chạy. (c) Đóng tab → phải nhập lại mã |
| NFR-P-03 | Môi trường chọn bằng đoạn cố định trong route, không có tham số môi trường tự do; staging HubSpot = portal prod (bảng §1.6). Bằng chứng: be/apps/api/src/sapp/sapp-ops.controller.ts:61-66, be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26 | Mọi dịch vụ theo môi trường; FS HubSpot, 24395, 23954, 26878 | Gọi staging/hubspot/... → dùng token SAPP_PROD_HUBSPOT_ACCESS_TOKEN; môi trường không có route → 404 |
| NFR-P-04 | Credential hệ ngoài chỉ nằm ở BE, không tới trình duyệt (Ops username/password + token, SAP HMAC secret, DB Ops, token HubSpot); BE đọc từ env_systems lúc gọi. ⚠️ Observed: giá trị lưu dạng rõ trong DB, và secretValue tool trả lại qua API admin (OQ-P-12). Bằng chứng: be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:39-134, be/libs/modules/src/lib/sapp/sap-log.common.service.ts:56-68, :286-315, be/libs/database/src/lib/entities/env/env-system.entity.ts:10-11 | US-P04…P09 | Không response nào của US-P05…P09 chứa password / secret / token Ops (ping chỉ trả { ok: true }) |
| NFR-P-05 | Timeout và giới hạn: danh sách trạng thái tool 10 s (tối đa 1000 tool); đăng nhập Ops 30 s, lời gọi Ops 10 phút; SAP service 30 s; SAP log limit 1–200 mỗi bảng; SQL 15 s/câu, SELECT ≤ 200 dòng. Bằng chứng: fe/src/ui/components/works/shared/use-tools-state.ts:51-52, be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:38-41, be/libs/constants/src/lib/sapp/sapp.constants.ts:38, be/libs/constants/src/lib/sapp/sap-log.constants.ts:42-77, be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:309-313 | US-P02, P05, P08, P09 | Vượt giới hạn → lỗi tương ứng (13041, 13057, timeout) |
| NFR-P-06 | Không có thông báo, job hay audit trail phía mind_keep cho các dịch vụ dùng chung: không mail / push / MQTT / Discord / cron; chỉ log lỗi phía server. Cron quét tuần nằm ở SAP service. Bằng chứng: Grep mqtt|mailService|discord|telegram|@Cron trong be/apps/api/src/sapp, be/libs/modules/src/lib/sapp = 0; Grep sapp trong be/apps/schedule/src = 0 | US-P03…P09 | Không có bản ghi ai đã chạy thao tác ghi nào (kể cả prod) |
| NFR-P-07 | Ghi nhớ trên trình duyệt, xuống cấp an toàn: mk:works:sapp:last-tool, …:sidebar-collapsed, …:theme-dark, …:nav-groups-closed (localStorage); đọc/ghi lỗi → dùng mặc định, không báo lỗi. Bằng chứng: 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 | US-P01 | Chặn storage trình duyệt → workspace vẫn dùng được với mặc định |
| NFR-P-08 | Token Ops giữ trong Redis theo môi trường, một lượt đăng nhập mỗi môi trường khi có yêu cầu đồng thời (trong một tiến trình); 401 → đăng nhập lại + thử lại 1 lần. Bằng chứng: be/libs/modules/src/lib/sapp/sapp-auth.common.service.ts:43-49, :87-181 | US-P08 (và FS 26297) | 5 yêu cầu đồng thời khi chưa có token → 1 lượt đăng nhập |
6. Open Questions ​
Owner mặc định: BA (ý đồ nghiệp vụ) · BE lead (hành vi code). Due: trước Gate R2. Mọi OQ đang Open.
| ID | Question | Owner | Due Date | Status | Blocks (US) |
|---|---|---|---|---|---|
| OQ-P-01 | 259 route /api/v1/sapp/* đều @Public(), kể cả route ghi prod (NFR-P-01) — cố ý hay bug? Ai được phép dùng? (inventory R-18, Q-01; G-02; DR-P-02) | BA + BE lead | Trước Gate R2 | Open | Toàn bộ US-P01…P09 + mọi FS nhóm |
| OQ-P-02 | Ops passthrough mở đủ thao tác ghi trên prod (tạo user/lớp/lịch/đơn/giao dịch, xoá/huỷ lịch, chuyển học viên, xác nhận giao dịch, resync SAP), không chốt chặn prod ở tầng dùng chung — cố ý hay bug? (inventory R-22; G-03) | BA + BE lead | Trước Gate R2 | Open | US-P08, FS 26878 |
| OQ-P-03 | Chọn "staging" HubSpot thực chất dùng portal prod — code ghi là cố ý; người dùng tool có biết không, và thao tác ghi "staging" của sub-tool có được phép chạm dữ liệu prod? Cố ý (được chấp nhận) hay bug? (inventory R-20, Q-02; G-04; DR-P-01) | BA | Trước Gate R2 | Open | US-P04, US-P07; FS HubSpot, 24395, 23954, 26878 |
| OQ-P-04 | Khoá/tắt tool chỉ chặn ở giao diện; mở khoá chỉ ở sessionStorage, FE không gửi bằng chứng lên API — mức bảo vệ này cố ý hay bug/rủi ro? (inventory R-14, R-15, Q-05) | BA | Trước Gate R2 | Open | US-P02 |
| OQ-P-05 | Route kiểm mã bí mật public, không giới hạn tần suất (khoá "năm của ngày" chỉ vài trăm giá trị) — cố ý hay bug? (inventory R-16) | BE lead | Trước Gate R2 | Open | US-P02 |
| OQ-P-06 | Tool đang ẩn vẫn đọc được trạng thái và kiểm mã qua route theo mã — cố ý hay bug? (inventory R-13, Q-06; DR-P-07) | BE lead | Trước Gate R2 | Open | US-P02, US-P03 |
| OQ-P-07 | sortBy của danh sách tool public là chuỗi tự do ghép thẳng vào câu sắp xếp — cố ý hay bug? (inventory R-45, Q-07) | BE lead | Trước Gate R2 | Open | US-P02 |
| OQ-P-08 | Token Ops còn hạn < 30 s vẫn được giữ 30 phút (có thể giữ token đã chết, được cứu bởi nhánh 401) — cố ý hay bug? (inventory R-26, Q-08; DR-P-04) | BE lead | Trước Gate R2 | Open | US-P08 |
| OQ-P-09 | Route dựng callback SAP ký sẵn trên dev/staging là public — ai cũng giả được callback SAP hợp lệ — cố ý hay bug? (inventory R-37, Q-10) | BA + BE lead | Trước Gate R2 | Open | US-P06 |
| OQ-P-10 | SQL runner trả nguyên thông báo lỗi Postgres (tên cột, ràng buộc) qua route public — cố ý (để tester sửa) hay bug? (inventory R-42, Q-11) | BE lead | Trước Gate R2 | Open | US-P09 |
| OQ-P-11 | Component khoá cũ (năm cố định 2003, kiểm ở trình duyệt) không tool nào dùng — di sản cần xoá hay còn kế hoạch dùng? Cố ý giữ hay bug (code chết)? (inventory R-46, Q-12) | FE lead | Trước Gate R2 | Open | US-P02 |
| OQ-P-12 | Secret hệ ngoài và giá trị khoá tool lưu dạng rõ; API admin trả lại giá trị khoá — cố ý (được chấp nhận) hay bug? (inventory R-47, Q-13) | BA + BE lead | Trước Gate R2 | Open | US-P03, US-P04 |
| OQ-P-13 | Ai là người dùng /works/sapp (owner / QA SAPP / Ops SAPP / BA…)? Hệ thống không phân biệt vai trò (inventory Q-04; G-01) | BA | Trước Gate R2 | Open | Role R1 ở US-P01, P02, P05…P09 |
| OQ-P-14 | Trên DB prod hiện tool nào đang tắt / ẩn / khoá, loại khoá gì? Seed mặc định "không khoá" (inventory Q-03; G-09) | BA | Trước Gate R2 | Open | US-P02, US-P03 |
| OQ-P-15 | Hai cơ chế xác thực Ops cùng tồn tại (bộ cũ SAPP_API_TOKEN xoay tay vs tự đăng nhập). Ai xoay token cũ, có kế hoạch bỏ không? (inventory R-30, Q-09) | BA + BE lead | Trước Gate R2 | Open | US-P04, US-P08; FS 24395 |
| OQ-P-16 | Đã 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 (việc #39FE/#41BE)? Thiếu dòng = tool đóng (inventory Q-14) | BE lead | Trước Gate R2 | Open | US-P01, US-P03 |
| OQ-P-17 | Tên chuẩn của tool là tên trong mã/DB hay nhãn sidebar (vd sapp.010 "SAPP 26878: Create deal instance" vs "Test data theo luồng")? (inventory Q-15) | BA | Trước Gate R2 | Open | US-P01, US-P03 |
| OQ-P-18 | Mục đích nghiệp vụ của việc nhóm tool theo số ticket, và ai quyết thêm/bỏ tool khỏi workspace? (inventory Q-16; G-05) | BA | Trước Gate R2 | Open | US-P03; §1.2 |
| OQ-P-19 | (Phát hiện khi viết FS R3, chưa có ở inventory) Mã lỗi 13058 dùng cho cả "Failed to update the SAPP Ops class schedule" và "No LMS API URL is configured…" (26297); 13059 cho cả xoá lịch Ops và "A learner LMS token is required" — cố ý hay bug? Bằng chứng: be/libs/constants/src/lib/error-codes/error-codes.constants.ts:812-820, :834-845 | BE lead | Trước Gate R2 | Open | US-P08; FS 26297 |
| OQ-P-20 | Dựng callback chạy được (201) nhưng webhook staging từ chối body bộ ký dựng (400) — FS mô tả là "đã triển khai, chưa chạy được"? (G-08; shared/external/sapp/sapp-26878/2026-09-22-mind-sign-callback-lech-dto.md:15-18) | BA | Trước Gate R2 | Open | US-P06; FS 26878 US-D17 |
| OQ-P-21 | (Phát hiện khi viết FS R3) Hộp xác nhận xoá biến môi trường nói "Services that read it fall back to their defaults", nhưng dịch vụ SAPP không có mặc định mà báo lỗi thiếu cấu hình — cố ý hay bug (câu chữ sai)? Bằng chứng: fe/src/ui/pages/cms/(env-systems)/page.tsx:189 vs be/libs/modules/src/lib/sapp/sap-log.common.service.ts:99-106 | FE lead | Trước Gate R2 | Open | US-P04 |
| OQ-P-22 | (Phát hiện khi viết FS R3) Mã lỗi dùng lẫn: sign-callback lỗi trả 13052 "Failed to trigger the manual revenue-recognition sweep"; manual-scan nhận mọi 403 từ SAP service đều trả 13050 "…cannot run against production" — cố ý hay bug? Bằng chứng: be/libs/modules/src/lib/sapp/sap-log.common.service.ts:249-254, :318-328 | BE lead | Trước Gate R2 | Open | US-P05, US-P06 |
6b. Drift: tài liệu ↔ code (Mode B/C — Mode A ghi N/A) ​
Không tự chọn bên đúng — mỗi dòng cần owner quyết. shared/api-docs/ chỉ lane be/ được sửa.
| ID | Tài liệu nói | Code đang làm (bằng chứng file:dòng) | Ảnh hưởng | Owner quyết |
|---|---|---|---|---|
| DR-P-01 | shared/api-docs/sapp.md:12 §Overview: HubSpot "across two portals (prod / dev)" (inventory DR-01) | Ba môi trường; staging dùng lại credential portal prod — be/libs/constants/src/lib/hubspot/hubspot.constants.ts:14-31 | Người đọc doc không biết "staging" ghi prod (NFR-P-03) | BE lane |
| DR-P-02 | shared/api-docs/sapp.md:14 §Overview: "the three routes below are currently marked @Public() … (temporary)" (inventory DR-02) | Toàn bộ 259 route SAPP @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 | Đánh giá rủi ro sai (NFR-P-01, OQ-P-01) | BE lane |
| DR-P-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" (inventory DR-03) | Danh sách có thêm act, comment code nói đây là trường đang dùng thật (data.tokens.act) — be/libs/constants/src/lib/sapp/sapp-ops.constants.ts:43-63 | Doc thiếu trường thực dùng | BE lane |
| DR-P-04 | shared/api-docs/sapp.md:1096-1098: cache token tới exp − 60 s; 30 phút nếu token opaque; tối đa 24 h (inventory DR-04) | Thêm nhánh: 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 | OQ-P-08 | BE lane |
| DR-P-05 | shared/api-docs/sapp.md:2474 §SAPP Ops passthrough; be/.agents/maps/modules/tool.md §3: "Twenty read/write operations" / "~20 thao tác Ops" (inventory DR-05) | 33 thao tác mỗi môi trường (35 ở dev/staging tính 2 route SQL) — be/apps/api/src/sapp/sapp-ops.controller.ts:634-2442 | Doc thiếu 13 thao tác | BE lane |
| DR-P-06 | shared/api-docs/sapp.md:2241 §SAP log trace: "Two read-only endpoints" (inventory DR-06) | Section còn 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 | Doc bỏ sót route có tác động | BE lane |
| DR-P-07 | shared/api-docs/tools.md:24-25 §Overview: route /tools/public/* "only expose effectively visible tools" (inventory DR-07) | 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 | OQ-P-06 | BE lane |
| DR-P-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)" (inventory DR-08) | 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 | Dễ gọi nhầm route cần đăng nhập (lịch sử #39FE) | BE lane (doc) · FE lane (comment) |
| DR-P-09 | shared/api-docs/tools.md:11 §Overview: registry ở mind_keep_cms_ui/src/data/constants/tool-codes.ts (inventory DR-09) | Đường dẫn thực tế fe/src/data/constants/tool-codes.ts — fe/src/data/constants/tool-codes.ts:1-57 | Đường dẫn cũ (trước monorepo) | BE lane |
| DR-P-10 | shared/api-docs/tool-groups.md:30-35: nhóm sapp có sapp.* (10) tool (inventory DR-10) | 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 | Số tool sai | BE lane |
| DR-P-11 | (Phát hiện khi viết FS R3) Câu chữ panel SQL fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:442: "route chạy SQL là route DUY NHẤT của tool này cần JWT" | Route `dev | staging/sapp-ops/sql/status | runlà@Public()như mọi route SAPP —be/apps/api/src/sapp/sapp-ops.controller.ts:2405, :2417, :2431, :2443` |
7. References ​
- BRD: ../../brd/brd-as-built-v0.1-20260930.md
- Impact Matrix: N/A — Mode B
- Solution Decision:
../../../project-decisions.md(Gate R1 Approved, R2 confirm 60 US) - Figma: N/A — as-built, không có Figma
- API Spec:
shared/api-docs/sapp.md,shared/api-docs/tools.md,shared/api-docs/tool-groups.md,shared/api-docs/env-system.md(xem Drift §6b) - Code đã đọc: chi tiết ở
working/ai-drafts/feature-inventory-platform-20260930.md§9. Đọc thêm khi viết FS (R3):fe/src/ui/pages/cms/(tools)/page.tsx,fe/src/ui/pages/cms/(env-systems)/page.tsx,fe/src/ui/components/cms/(tools)/create-form.tsx,update-form.tsx,fe/src/ui/components/cms/(env-systems)/create-form.tsx,app/lib/screens/tool_form_screen.dart,tool_group_form_screen.dart,fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx,sapp-26878-step-scan.tsx,sapp-26878-manual-scan.tsx,sapp-26878-step-option.tsx,sapp-26878-flows.ts(5985-6030),fe/src/data/services/sapp/sap-log.service.ts,sapp-ops.service.ts,be/libs/constants/src/lib/error-codes/error-codes.constants.ts,be/libs/interface/src/lib/dto/sapp/sap-log.dto.ts,be/libs/interface/src/lib/dto/hubspot/hubspot-property.dto.ts - Nguồn mục đích ("So that"):
shared/external/sapp/sapp-26878/0005-sapp-26878-phase2-us04-tra-loi-ops-mind.md,shared/external/sapp/sapp-26878/2026-09-22-mind-sign-callback-lech-dto.md - Meeting Notes / Q&A:
working/ai-drafts/gate-r1-summary-20260930.md(G-01…G-10 chưa có trả lời)
Template Conformance Check ​
Quét mục lục từng file US so với ba/_workflow/templates/fs/User-Story.md (Metadata · 1 US Statement · 2 Dependencies/DoR · 3 Business Rules có cột "Đã cover bởi (AC)" + "Nguồn code" · 4 Design: mỗi màn có UI States / Fields / Filter-Search-Sort / Actions / AC (G/W/T) / Negative AC · 5 Cross-feature AC). Section không áp dụng giữ heading + N/A — <lý do>.
| US file | Section thiếu | Trạng thái |
|---|---|---|
| US-P01-hub-mo-tool.md | (đủ) — M1 Fields/Filter N/A có lý do | ✅ |
| US-P02-khoa-tool.md | (đủ) — Filter N/A (không phải List) | ✅ |
| US-P03-quan-tri-trang-thai-tool.md | (đủ) — M3 UI States / Filter N/A (ngoài phạm vi truy vết chi tiết) | ✅ |
| US-P04-cau-hinh-env-systems.md | (đủ) | ✅ |
| US-P05-sap-log-va-quet-doanh-thu.md | (đủ) — M3 Fields N/A (chỉ có nút) | ✅ |
| US-P06-callback-sap.md | (đủ) — UI States N/A (dịch vụ, UI thuộc FS 26878) | ✅ |
| US-P07-option-property-hubspot-dev.md | (đủ) — UI States N/A (dịch vụ, UI thuộc FS 26878) | ✅ |
| US-P08-ops-passthrough.md | (đủ) — UI States N/A (dịch vụ); M2 Fields N/A | ✅ |
| US-P09-ops-sql-runner.md | (đủ) | ✅ |