643 lines
81 KiB
Markdown
643 lines
81 KiB
Markdown
# SEC — Security Architecture & Threat Model — e-commerce
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Version** | 1.1 |
|
||
| **Date** | 2026-09-15 |
|
||
| **Author** | SA (skill sa-2-architecture, chế độ `go`, hoạt động `sec`) |
|
||
| **Status** | 🟡 Draft *(duyệt từng phần — xem `Approved by`; AG2 cần cả ba vai trò Tech Lead/Security/Ops-SRE ký, mới có một chữ ký thay có điều kiện — **chưa đủ điều kiện chuyển `🔵 Approved`**)* |
|
||
| **Approved by** | Tech Lead: **Điều phối dự án** (uỷ quyền, chế độ chạy thử — ký thay theo ngoại lệ `DEC-01`, **không phải chữ ký Tech Lead thật**) — duyệt **từng phần** bản v1.0 · 2026-09-15: ghi nhận nội dung 31 `THR` STRIDE (§4), map `ROLE-01/02` (§3.1), mô hình authn/authz đề xuất (§2, §3), SAQ A (§8.1), đề xuất rate limit **30/10/10 req/phút** (§5.3, `ASM-40`), quản lý secret/scanning (§6), audit log theo phương án (a) (§7). Chốt **TẠM** hướng `OQ-050`: chọn **PA-3** (service JWT ngắn hạn ký bởi Identity & Access) cho service-to-service authn (§2.4) — yêu cầu SA viết `ADR-015` (`Proposed`) ở lượt hoạt động `adr` kế tiếp, cùng lúc với `ADR-014` (Outbox) đang nợ; `OQ-050` **giữ nguyên mở**, chờ Security + Ops/SRE thật xác nhận trước khi `Accepted`. **KHÔNG ký thay Security** — mọi kết luận PII/residency/retention (§5, §8.2) vẫn là **đề xuất chờ Legal/Security**, chưa có hiệu lực. Ghi thêm `DEC-28`. Security: **—** *(chưa có người được chỉ định — `OQ-007`, mở từ GĐ1. SEC **CHƯA CÓ HIỆU LỰC PHỦ QUYỀN AG2** cho tới khi có người này; không ký thay ở lượt này)* · Ops/SRE: **—** *(chưa ký)*. `OQ-004` (tính hợp lệ ký thay) vẫn mở. `Confidence` **giữ nguyên** 🔴 — duyệt từng phần không phải bằng chứng nguồn mới. Status **giữ** 🟡 Draft — AG2 chưa đủ ba chữ ký thật/hợp lệ. |
|
||
| **Source** | `02-architecture/SAD_e-commerce_v1.0.md` v1.3 §3, §4, §4.1, §7 · `02-architecture/DAT_e-commerce_v1.0.md` v1.0 §1, §5, §5.1, §5.2, §6, §9 · `02-architecture/ICD_e-commerce_v1.0.md` v1.0 §1, §2, §3.1–§3.7 · `02-architecture/FAIL_e-commerce_v1.0.md` v1.1 §1, §5 (`FM-06` ownership fail-closed, `E-CART-0007`) · `02-architecture/QAS_e-commerce_v1.0.md` `QAS-010/011/012` · `02-architecture/ASR_e-commerce_v1.0.md` `ASR-002/004/007/008/009` · `02-architecture/adr/ADR-002_*.md`, `ADR-004_*.md`, `ADR-007_*.md`, `ADR-008_*.md`, `ADR-009_*.md`, `ADR-011_*.md`, `ADR-015_*.md` · `01-context/CTX_e-commerce_v1.0.md` §4.2 (đối tác ngoài) · `01-context/ARISK_e-commerce_v1.0.md` §3 (`ARISK-03/04/06`) · `00-index/OQ_e-commerce.md` v1.21 · `00-index/DEC_e-commerce.md` v1.24 · `ba-output/e-commerce/02-analysis/RBAC_CartCheckout_v1.0.md` §1, §2, §4, §5, §6, §8 · `ba-output/e-commerce/03-specification/NFR_US002-003_v1.0.md` §3 · `e-commerce/docs/sections/08-bao-mat.md` *(P1, chỉ tham khảo — xem cảnh báo §0.2, KHÔNG kế thừa kiến trúc ~10 microservices/Kafka của tài liệu đó)* |
|
||
| **Scope** | Toàn sàn e-commerce theo P2 (`SAD` v1.3, 15 `CMP`). Chi tiết nhất: **Cart & Order** (`CMP-04`), **Payment** (`CMP-11`/`CMP-14`), **Identity & Access** (`CMP-02`), và luồng chia sẻ PII cho seller khi tách đơn (`ADR-008`, `DAT §5`). Các `CMP` còn lại (Seller Mgmt, Commission, Promotion, Review, Notification, Shipping) ở mức ranh giới tin cậy + authz tổng quát, không đào sâu threat model riêng — đây là hoạt động 6/9 (`sec`) của `sa-2-architecture`. |
|
||
| **Confidence** | 🔴 Giả định chưa xác minh — theo yêu cầu điều phối, tiếp nối `Confidence` 🔴 của `SAD`/`ICD`/`DAT`/`FAIL`/`ASR`/`QAS`. AG1 chưa ký thật; AG2 chưa tới hạn; `ADR-002/004/007/008/009/011` đều `Proposed` (chưa `Accepted`); `ADR-008` (PII) **chặn hoàn toàn** vì chưa có đại diện Pháp chế/Bảo mật (`OQ-007`); không đối tác ngoài nào (VNPay/Momo/GHN/GHTK) có sandbox/tài liệu API thật (`ARISK-03/04`) để xác minh cơ chế chữ ký webhook thật. Mọi ngưỡng rate-limit/circuit/authn trong tài liệu này là **đề xuất SA**, chưa Security/Tech Lead xác nhận. |
|
||
|
||
## Change Log
|
||
|
||
| Version | Date | Người sửa | Thay đổi | ADR/DEC |
|
||
|---|---|---|---|---|
|
||
| 1.0 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `sec`) | Bản đầu — hoạt động 6/9 của GĐ2. Threat model STRIDE cho 8 ranh giới tin cậy (client↔ALB/WAF, ALB↔Nhóm Giao dịch, Nhóm Giao dịch↔Nhóm Hỗ trợ cross-network `IF-021/022`, Cart&Order↔Payment `IF-006`, Payment↔VNPay/Momo + webhook inbound, Shipping↔GHN/GHTK webhook, app↔RDS/Redis/SQS, Admin console) — 28 `THR-01…28`, mỗi cái truy về `QAS`/`ASR`/`ADR` nguồn. Mô hình authn cho Guest/Customer/Seller/Admin + đề xuất mới cho service-to-service (Nhóm Giao dịch↔Nhóm Hỗ trợ↔Payment — chưa có cơ chế, radar ước lượng ~6, `ADR` ứng viên chưa viết). Mô hình authz: map đủ `ROLE-01/02` của `RBAC_CartCheckout` xuống quyền kỹ thuật, fail-closed cho ownership check (`E-CART-0007`, theo `FAIL`). Phân loại PII/mã hoá/masking/residency — toàn bộ đánh dấu "đề xuất chờ Legal/Security" (`OQ-007`). PCI-DSS SAQ A: xác nhận ranh giới `ADR-002`, đề xuất bắt buộc tích hợp dạng redirect (chưa xác nhận với đối tác thật — `OQ-048` mới); webhook: cơ chế chữ ký thật chưa biết (chưa bịa — `OQ-049` mới, `ARISK-03/04`), chống replay theo `ADR-004`. Đề xuất số cụ thể cho rate limit Guest cart (`OQ-023`), login brute-force (`OQ-052` mới), checkout. Quản lý secret (Secrets Manager, rotation), quét dependency/container (Trivy/Snyk), pentest năm + ASV quý (`OQ-017` đã mở ở `TCO`). Audit log theo phương án (a) đã chốt TẠM ở `OQ-047` (mỗi module tự ghi) — chốt trường bắt buộc + retention. Đối chiếu `docs/sections/08-bao-mat.md` chỉ tham khảo (P1, §0.2). Đề xuất `FIT-29…33` cho GĐ3 (authz test tự động, secret scan, service-authn test, webhook signature test, audit completeness test). Thêm `OQ-048…053`, cập nhật `OQ-007/023/024`, `ASM-39…41`. Ghi ngoại lệ tiếp tục gate ở `DEC-27` (`00-index/DEC_e-commerce.md`), tiếp nối `DEC-01…26`. Không sửa `SAD`/`ICD`/`DAT`/`FAIL`/`ADR` đã có. `Confidence` 🔴 toàn bộ. | `DEC-27` |
|
||
| 1.0 | 2026-09-15 | Điều phối dự án (thay mặt Tech Lead, ngoại lệ `DEC-01`) — tác vụ **sign/approve** | Duyệt **từng phần**: ghi nhận nội dung 31 `THR` STRIDE (§4), map `ROLE-01/02` (§3.1), mô hình authn/authz đề xuất (§2, §3), SAQ A (§8.1), đề xuất rate limit **30/10/10 req/phút** (§5.3, `ASM-40`), quản lý secret/scanning (§6), audit log theo phương án (a) (§7). Chốt **TẠM** `OQ-050`: chọn **PA-3** (service JWT ngắn hạn) cho service-to-service authn (§2.4) — yêu cầu SA viết `ADR-015` (`Proposed`) ở lượt hoạt động `adr` kế tiếp cùng `ADR-014`; `OQ-050` giữ nguyên mở, chờ Security + Ops/SRE. **KHÔNG ký thay Security** — header `Approved by → Security` giữ `—`, `SEC` **chưa có hiệu lực phủ quyết AG2** (`OQ-007`); mọi kết luận PII/residency/retention (§5, §8.2) vẫn là đề xuất chờ Legal/Security, không phải quyết định cuối. Không đổi nội dung chuyên môn nào của tài liệu. Ops/SRE chưa ký; `Confidence` giữ 🔴; Status giữ 🟡 Draft; AG2 chưa ký. Ghi thêm `DEC-28`. | `DEC-28` |
|
||
| 1.1 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `adr`) | **Chỉ link ADR, không đổi nội dung.** `ADR-015` (Service JWT ngắn hạn service-to-service, `Proposed`) vừa được viết theo hướng PA-3 đã chọn TẠM ở §2.4/`OQ-050`/`DEC-28` — thay các dòng "chưa viết `ADR`" ở §2.4 và `THR-09`/`THR-13` (§4.3/§4.4) bằng đường dẫn `adr/ADR-015_service-jwt-xac-thuc-service-to-service.md`. `OQ-050` giữ nguyên mở (chặn cứng bởi `OQ-007` — Security chưa có người, xem `ADR-015 §0`/§3). Không sửa nội dung chuyên môn nào khác của `SEC`. Ghi `DEC-31` (tiếp nối `DEC-01…30`). | `ADR-015`, `DEC-31` |
|
||
|
||
> Sơ đồ thắng về **quan hệ và luồng** (ai gọi ai, qua ranh giới nào).
|
||
> Bảng/văn bản thắng về **ràng buộc và con số** (ngưỡng rate-limit, TTL token, mức che dữ liệu).
|
||
> Mâu thuẫn ngoài hai loại trên là lỗi tài liệu, phải sửa chứ không chọn bên (`D12`).
|
||
|
||
---
|
||
|
||
## 0. Ghi chú Preflight & phạm vi — bắt buộc đọc trước
|
||
|
||
### 0.1 Ngoại lệ gate
|
||
|
||
**AG1 vẫn chưa ký thật; AG2 (gate của chính GĐ2) chưa tới hạn.** Theo `SKILL.md`, hoạt động 1
|
||
(`QAS`) → 2 (`ASR`) → 3 (`SAD`) đã hoàn tất và được duyệt từng phần (`DEC-12/14/16`); hoạt động 4
|
||
(`ICD`), 5 (`DAT`), 8 (`FAIL`) đã chạy (`DEC-18…25`), `ADR-001…013` đã viết (tất cả `Proposed`).
|
||
Điều kiện đầu vào cho hoạt động 6 (`SEC`) — `SAD`, `DAT`, `RBAC` của BA — đã đủ. Người dùng (vai
|
||
điều phối dự án chạy thử) đã được cảnh báo lại và **khẳng định muốn tiếp tục**.
|
||
|
||
> **DEC-27 (SA)** — Tiếp tục `sa-2-architecture` (hoạt động 6 — `SEC`) cho e-commerce trong khi
|
||
> AG1 chưa ký thật và AG2 chưa tới hạn — tiếp nối `DEC-01…26`.
|
||
> **Quyết định:** Dựng threat model STRIDE + mô hình authn/authz + phân loại PII cho toàn sàn P2
|
||
> dựa trên `SAD v1.3`/`DAT v1.0`/`ICD v1.0`/`FAIL v1.1`/`RBAC_CartCheckout` đã có, giữ
|
||
> `Confidence 🔴` cho tới khi: (a) AG1/AG2 ký thật, (b) có đại diện Pháp chế/Bảo mật thật
|
||
> (`OQ-007`) — **điều kiện chặn cứng nhất**, không có `SEC` nào có hiệu lực phủ quyết PII/residency
|
||
> nếu thiếu người này, (c) đối tác VNPay/Momo/GHN/GHTK có tài liệu/sandbox thật để xác minh cơ chế
|
||
> chữ ký webhook (`ARISK-03/04`), (d) Tech Lead xác nhận các đề xuất mới (service-to-service authn,
|
||
> ngưỡng rate-limit, account lockout).
|
||
> **Người quyết:** Điều phối dự án (đại diện PO, dự án chạy thử).
|
||
> **Radar (ước lượng cho việc tiếp tục dưới ngoại lệ):** ~4 — chi phí đảo ngược thấp (ghi tài liệu
|
||
> threat model, chưa có dòng code phụ thuộc) · bán kính ảnh hưởng: hoạt động `inf` kế tiếp và toàn
|
||
> bộ dev dùng `SEC` làm nguồn sự thật authn/authz/PII, nhưng bản thân *việc ghi tài liệu dưới ngoại
|
||
> lệ* thì nhỏ · có chạm `QAS-010/011/012` Must trực tiếp (đang thiết kế cách đạt chúng) nhưng chưa
|
||
> phải cam kết thi công (chưa `FIT` nào chạy) · không ràng buộc dài hạn tự thân (văn bản `SEC` sửa
|
||
> được qua version mới) · không tranh cãi mới, tiếp nối tiền lệ `DEC-11…26` → **ghi `DEC-nn`,
|
||
> không cần `ADR` cho việc chạy dưới ngoại lệ** (`decision-radar.md §1–§2`).
|
||
> **Hệ quả nếu không chấp nhận ngoại lệ:** hoạt động `inf` (hoạt động 7) không có mô hình threat/
|
||
> authn/authz để thiết kế network segmentation và secret management thật — chậm tiến độ chạy thử
|
||
> tương ứng thời gian xử lý các `OQ` đang mở, đặc biệt `OQ-007` (chặn `ADR-008` và phần lớn §5).
|
||
|
||
### 0.2 Đối chiếu `docs/sections/08-bao-mat.md` — chỉ tham khảo, không kế thừa
|
||
|
||
`docs/sections/08-bao-mat.md` (P1, `status: approved`, `version: 2`) là thiết kế bảo mật cho
|
||
kiến trúc **~10 microservices + Kafka/MSK + database-per-service** — kiến trúc đó **đã bị loại**
|
||
ở `OPT §5` (GĐ1), thay bằng P2 (modular monolith + managed AWS, Payment tách riêng). Tài liệu này
|
||
**chỉ tái dùng**: (a) quy ước đặt tên mã lỗi (`403 ERR_FORBIDDEN_OWNERSHIP`, `423
|
||
ERR_ACCOUNT_LOCKED`), (b) ý tưởng chính sách khoá tài khoản theo vai trò (§8.1.1a), (c) ý tưởng
|
||
redact PII trong audit log (§8.2.5a), (d) danh mục OWASP Top 10 rà theo endpoint — **không kế
|
||
thừa** cấu trúc scope `customer:*`/`seller:*`/`admin:*` gắn với 10 service riêng, không kế thừa
|
||
giả định Kafka/MSK ACL (P2 dùng SQS FIFO/EventBridge, đã có ở `ADR-005`), không kế thừa bảng
|
||
`audit_log` tập trung một Service Audit & Compliance (P2 chọn phương án (a) — mỗi module tự ghi,
|
||
`OQ-047`). Mọi chỗ tái dùng được đánh dấu rõ "tham khảo P1" trong bảng tương ứng bên dưới.
|
||
|
||
🔴 **Nhắc quan trọng:** `INF` (hoạt động 7) **chưa được tạo**. Tài liệu này là input trực tiếp cho
|
||
`INF` — đặc biệt network segmentation (§1), secret management (§6), và ngưỡng alerting an ninh.
|
||
|
||
---
|
||
|
||
## 1. Ranh giới tin cậy
|
||
|
||
*8 ranh giới theo yêu cầu người duyệt. Mỗi ranh giới phải có kiểm tra đầu vào tại đúng điểm giao.*
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph NET["Internet — không tin cậy"]
|
||
U["Guest/Customer/Seller/Admin"]
|
||
VNP["VNPay"]
|
||
MOMO["Momo"]
|
||
GHN["GHN"]
|
||
GHTK["GHTK"]
|
||
end
|
||
|
||
subgraph EDGE["Vùng biên — TB1"]
|
||
WAF["WAF + ALB (CMP-01)"]
|
||
end
|
||
|
||
subgraph GD["Nhóm Giao dịch — TB2 (tin cậy vừa)"]
|
||
ID["Identity & Access (CMP-02)"]
|
||
CAT["Catalog & Inventory (CMP-03)"]
|
||
CO["Cart & Order (CMP-04)"]
|
||
end
|
||
|
||
subgraph HT["Nhóm Hỗ trợ — tin cậy vừa (khác network TB2)"]
|
||
PROMO["Promotion & Loyalty (CMP-07)"]
|
||
SELLER["Seller Mgmt (CMP-05)"]
|
||
SHIP["Shipping & Fulfillment (CMP-10)"]
|
||
end
|
||
|
||
subgraph PAY["Payment Service — TB4 (cô lập PCI, tin cậy cao nhất nội bộ)"]
|
||
PS["Payment (CMP-11)"]
|
||
end
|
||
|
||
subgraph DATA["Vùng dữ liệu — TB5"]
|
||
RDS[("RDS chính")]
|
||
RDSPAY[("RDS Payment")]
|
||
REDIS[("Redis")]
|
||
SQS[("SQS/EventBridge")]
|
||
end
|
||
|
||
subgraph ADMIN["Admin console — TB6"]
|
||
ADM["Admin Backoffice"]
|
||
end
|
||
|
||
U -->|"TB1 · HTTPS, WAF+TLS termination"| WAF
|
||
WAF -->|"TB2 · HTTPS, authn JWT/Guest"| ID
|
||
WAF -->|"TB2"| CAT
|
||
WAF -->|"TB2"| CO
|
||
WAF -->|"TB4 · HTTPS, cô lập mạng"| PS
|
||
ADM -->|"TB6 · HTTPS, MFA + IP allowlist (đề xuất)"| ID
|
||
CO -->|"TB3 · REST cross-network, chưa có service-authn"| PROMO
|
||
CO -->|"TB3 · REST cross-network"| SELLER
|
||
CO -->|"TB4 · REST, chưa có service-authn"| PS
|
||
PS -->|"TB-ext · REST sync + webhook async"| VNP
|
||
PS -->|"TB-ext"| MOMO
|
||
SHIP -->|"TB-ext · REST sync + webhook async"| GHN
|
||
SHIP -->|"TB-ext"| GHTK
|
||
ID -->|"TB5 · TLS, IAM theo schema"| RDS
|
||
CO -->|"TB5"| RDS
|
||
CO -->|"TB5"| REDIS
|
||
CO -->|"TB5 · publish"| SQS
|
||
PS -->|"TB5 · TLS, IAM riêng biệt"| RDSPAY
|
||
SQS -->|"TB5 · consume"| HT
|
||
```
|
||
|
||
**Legend:** ▭ vùng tin cậy khác nhau bằng subgraph · mũi tên ghi giao thức + loại kiểm tra tại
|
||
ranh giới đó · `TBn` tham chiếu đúng số ranh giới ở bảng dưới.
|
||
|
||
| # | Ranh giới | Từ vùng | Sang vùng | Kiểm tra gì tại đây | `CMP` chịu trách nhiệm |
|
||
|---|---|---|---|---|---|
|
||
| TB1 | Client → ALB/WAF | Internet (không tin cậy) | Biên hệ thống | TLS 1.2+ termination, WAF (OWASP Core Rule Set), rate-limit L7, giới hạn kích thước payload, chặn IP theo reputation (đề xuất) | `CMP-01` |
|
||
| TB2 | ALB → Nhóm Giao dịch | Biên | Nội bộ tin cậy vừa | Authn hợp lệ (JWT Customer / `X-Guest-Session-Id` Guest) — **KHÔNG** authz chi tiết theo dữ liệu (đúng `SAD §4.1` "cái `CMP-01` KHÔNG làm") | `CMP-01` → `CMP-02/03/04` |
|
||
| TB3 | Nhóm Giao dịch ↔ Nhóm Hỗ trợ (`IF-021`/`IF-022`) | Nội bộ tin cậy vừa | Nội bộ tin cậy vừa (network khác — 2 ECS Fargate service riêng, `OQ-026`) | 🔴 **Chưa có cơ chế xác thực service-to-service** — hiện chỉ có network reachability (security group nội bộ VPC), chưa xác thực danh tính bên gọi. Xem §2.5, `THR-09…12` | `CMP-04` ↔ `CMP-07`/`CMP-05` |
|
||
| TB4 | Cart & Order → Payment (`IF-006`) | Nội bộ tin cậy vừa | Vùng cô lập PCI cao nhất | Tương tự TB3 — chưa có service-authn; **đây là ranh giới nhạy cảm nhất** vì Payment giữ tiền thật (`ASR-002`) | `CMP-04` → `CMP-11` |
|
||
| TB5 | Payment ↔ VNPay/Momo (init sync + webhook inbound async) | Vùng cô lập PCI | Internet (đối tác bên thứ ba) | Chữ ký/HMAC theo tài liệu đối tác (🔴 chưa có, `ARISK-03`), chống replay (`ADR-004`, lệch ≤5 phút), TLS | `CMP-11` |
|
||
| TB6 | Shipping & Fulfillment ↔ GHN/GHTK webhook | Nhóm Hỗ trợ | Internet (đối tác) | Chữ ký/token theo tài liệu đối tác (🔴 chưa có, `ARISK-04`), không ghi đè trạng thái thụt lùi (`FAIL FM-03/04`) | `CMP-10` |
|
||
| TB7 | App (mọi `CMP`) ↔ RDS/Redis/SQS | Nội bộ tin cậy vừa/cao | Vùng dữ liệu | TLS in-transit, IAM/network ACL theo schema-per-module (`ADR-006`) — **không module nào được truy cập schema của module khác**, RDS Payment tách hoàn toàn (`ADR-002`) | mọi `CMP` ứng dụng → `CMP-13/14/15/12` |
|
||
| TB8 | Admin console → Identity & Access + toàn hệ thống | Internet (giới hạn, đề xuất VPN/IP allowlist) | Nội bộ tin cậy cao | MFA bắt buộc (`ASR-009`), IP allowlist/VPN (đề xuất — tham khảo P1 §3.3, chưa quyết định hạ tầng cho P2, `OQ-050`), audit toàn bộ hành động | `CMP-02` (phần Admin) |
|
||
|
||
🔴 **TB3 và TB4 là phát hiện mới của hoạt động `sec`** — `SAD`/`ICD`/`FAIL` đã ghi nhận đây là
|
||
cross-network call (`OQ-026/028`) nhưng **chưa từng thiết kế cơ chế xác thực danh tính bên gọi**,
|
||
chỉ có network reachability. Một service nào đó trong cùng VPC (kể cả bị compromise) có thể gọi
|
||
thẳng `IF-006`/`IF-021`/`IF-022` nếu không có kiểm soát bổ sung. Xem §2.5 (đề xuất) và `THR-09/13`.
|
||
|
||
---
|
||
|
||
## 2. Xác thực (Authentication)
|
||
|
||
| | Quyết định | `ADR`/Nguồn |
|
||
|---|---|---|
|
||
| **Cơ chế (Customer)** | Bearer JWT | `ICD §1` mục 9 — kế thừa `04-api-design.md §4.2`, chưa có `ADR` riêng |
|
||
| **Cơ chế (Guest)** | Header `X-Guest-Session-Id` (giá trị CSPRNG ≥128-bit) + cookie `HttpOnly; Secure; SameSite=Lax` | `ICD §1` mục 10 |
|
||
| **Cơ chế (Seller/Admin)** | Bearer JWT (kế thừa cùng cơ chế Customer, khác `role` claim) | Suy từ `CMP-02`, chưa có tài liệu riêng ngoài phạm vi US-002/003 |
|
||
| **Nơi giữ trạng thái** | Stateless (JWT) cho Customer/Seller/Admin · **Stateful** cho Guest (session lưu ở Redis, `CMP-15`, theo `DAT §1.1`) | `DAT §1.1` |
|
||
| **Thời hạn access token** | 🔴 **Chưa chốt số cụ thể cho P2** — `ICD §1` mục 9 chỉ ghi "~15-60 phút (kế thừa `04-api-design.md §4.2`)"; đây là khoảng tham khảo P1, chưa xác nhận cho P2. Đề xuất SA: **15 phút** (an toàn hơn, giảm cửa sổ lợi dụng token bị đánh cắp) — xem `OQ-051` | — |
|
||
| **Refresh token** | 🔴 Chưa chốt — đề xuất SA: có, TTL 14 ngày, **không** áp dụng rotation phức tạp kiểu P1 (`docs/08 §8.1.1` refresh token rotation + reuse detection) ở MVP P2 vì tăng độ phức tạp mà chưa có bằng chứng cần thiết cho quy mô hiện tại; ghi nhận là điểm có thể nâng cấp khi có sự cố thật — xem `OQ-051` | Tham khảo P1, **không kế thừa nguyên trạng** |
|
||
| **Cách thu hồi ngay lập tức** | 🔴 **Chưa có cơ chế** — JWT stateless không có denylist. Đề xuất SA: denylist Redis theo `jti`, TTL = thời hạn còn lại của token, tra cứu tại middleware authn mỗi request (thêm ~1 Redis lookup, chấp nhận được vì Redis đã là phụ thuộc sẵn có, `CMP-15`) — áp dụng khi: đổi mật khẩu, Admin khoá tài khoản, logout (tuỳ chọn). **Chưa Tech Lead xác nhận** | `OQ-051` (mới) |
|
||
| **Đa yếu tố (MFA)** | Bắt buộc cho Admin, khuyến khích (không bắt buộc) cho Seller (`ASR-009`, `QAS-012`). Phương thức: **TOTP app (RFC 6238)** — chốt TẠM theo `OQ-024`/`DEC-14`/`ASM-20`, **chưa Security thật xác nhận**, `OQ-024` vẫn mở | `ASR-009` |
|
||
| **Backup code khi mất thiết bị MFA** | 🔴 Chưa thiết kế — đề xuất 10 mã dùng một lần khi enroll (tham khảo P1 §8.1.1, không sao chép nguyên bản vì P1 gắn với endpoint `/v1/auth/mfa/enroll` cụ thể chưa xác nhận tồn tại ở P2) | `OQ-024` |
|
||
| **Nơi ký/xác minh chữ ký JWT** | Identity & Access (`CMP-02`) ký bằng khoá riêng; các `CMP` khác **chỉ xác minh** (không tự ký) | `CMP-02` |
|
||
| **Xoay khoá ký JWT** | 🔴 Chưa chốt tần suất — đề xuất tham khảo chung ngành: 90 ngày, dùng `kid` trong header JWT để hỗ trợ 2 khoá song song trong giai đoạn chuyển tiếp | `OQ-051` |
|
||
|
||
### 2.1 Guest session — chi tiết
|
||
|
||
| | |
|
||
|---|---|
|
||
| TTL | 30 ngày không hoạt động (`ICD §1` mục 10, `DAT §1.1`) |
|
||
| Rotation | 🔴 **Không có** — cùng một `X-Guest-Session-Id` dùng suốt vòng đời phiên, không xoay định kỳ. Rủi ro: nếu giá trị bị lộ (session fixation qua log/URL), kẻ tấn công giữ quyền truy cập tới hết TTL. Đề xuất SA: xoay giá trị session tại thời điểm Guest chuyển đổi thành Customer (đăng ký/đăng nhập) — chưa thiết kế chi tiết, ghi `OQ-051` |
|
||
| Nơi giữ | Redis (`CMP-15`), là **nguồn sự thật của session** (không có bản ghi RDS song song, `DAT §1.1`) |
|
||
| Hết hạn | Guest mất phiên, phải tạo giỏ mới (`BR-CART §3`, đúng thiết kế) |
|
||
|
||
### 2.2 Customer JWT — chi tiết
|
||
|
||
| | |
|
||
|---|---|
|
||
| Thuật toán | 🔴 Chưa chốt — đề xuất **RS256** (asymmetric, cho phép các `CMP` khác chỉ cần public key để verify, không cần chia sẻ secret) thay vì HS256 (symmetric, mọi service verify phải giữ cùng secret — rủi ro lan rộng nếu 1 service bị lộ secret) |
|
||
| Claims tối thiểu | `sub` (customerId), `role`, `iat`, `exp`, `jti` (phục vụ denylist §2 trên) — **chưa chốt scope claim chi tiết**, xem §3 |
|
||
| TTL access/refresh | Xem bảng §2 trên — cả hai **chưa chốt số cuối**, `OQ-051` |
|
||
|
||
### 2.3 Seller / Admin — chi tiết
|
||
|
||
*Ngoài phạm vi chi tiết hoá của module Giỏ hàng & Checkout (`RBAC_CartCheckout §1` cố ý không đưa
|
||
Seller/Admin vào ma trận) — SEC chỉ ghi nhận yêu cầu tối thiểu do `ASR-009` ép ra:*
|
||
|
||
| | |
|
||
|---|---|
|
||
| Seller | JWT giống Customer, `role=seller`, MFA khuyến khích không bắt buộc |
|
||
| Admin | JWT giống Customer, `role=platform_admin`, **MFA bắt buộc** (TOTP, `ASM-20`); đề xuất bổ sung giới hạn mạng (VPN/IP allowlist) — tham khảo P1 `docs/08 §3.3`, **chưa quyết định hạ tầng cho P2** vì `INF` (hoạt động 7) chưa chạy — ghi `OQ-050` |
|
||
| Account lockout (brute-force) | 🔴 Chưa thiết kế cho P2 — đề xuất SA (tham khảo ý tưởng P1 `docs/08 §8.1.1a`, **số ngưỡng đề xuất lại cho P2**, chưa kế thừa nguyên bản): `customer`/`seller` 5 lần sai liên tiếp → khoá 15 phút; `platform_admin` 3 lần sai liên tiếp → khoá 30 phút (ngưỡng thấp hơn vì quyền hạn cao hơn). **Chưa Security/Tech Lead xác nhận** — `OQ-052` (mới) |
|
||
|
||
### 2.4 Service-to-service (Nhóm Giao dịch ↔ Nhóm Hỗ trợ ↔ Payment)
|
||
|
||
🔴 **Đây là khoảng trống kiến trúc phát hiện bởi hoạt động `sec`** — chưa `ADR` nào (`ADR-002`,
|
||
`ADR-007`) quyết định cơ chế xác thực **giữa hai service nội bộ** (chỉ quyết định xác thực
|
||
**người dùng cuối** tới service). `IF-006`/`IF-021`/`IF-022` hiện chỉ dựa vào network reachability
|
||
(security group VPC) — không có gì ngăn một service khác trong cùng VPC giả danh gọi thẳng các
|
||
endpoint này nếu security group bị cấu hình sai hoặc một service bị compromise.
|
||
|
||
**Ba phương án đã cân nhắc** *(quy tắc `D3` — chưa viết `ADR` chính thức, đề xuất cho hoạt động
|
||
`adr` kế tiếp)*:
|
||
|
||
| Phương án | Mô tả | Ưu | Nhược |
|
||
|---|---|---|---|
|
||
| **PA-1 — Chỉ dựa network (security group)** | Giữ nguyên hiện trạng — không thêm gì | Không tốn công triển khai | Không đáp ứng "defense in depth" cho dữ liệu PII/tiền đi qua TB3/TB4; một security group cấu hình sai = không còn ranh giới nào |
|
||
| **PA-2 — mTLS qua service mesh (AWS App Mesh/Private CA)** | Mỗi ECS task có chứng chỉ riêng, xác thực lẫn nhau ở tầng TLS | Mạnh nhất, chuẩn ngành cho zero-trust nội bộ | Thêm hạ tầng mới (App Mesh) — **`SAD §7` v1.2 đã ghi rõ "không tự thêm hạ tầng mới (VD internal ALB/App Mesh) vào sơ đồ vì đó là quyết định kiến trúc mới, ngoài phạm vi"** — mâu thuẫn trực tiếp với ghi chú đó nếu chọn ngay bây giờ; cần quyết định lại ở `inf`/`adr` |
|
||
| **PA-3 — Service JWT ngắn hạn ký bởi Identity & Access + giữ nguyên security group** *(đề xuất SA)* | Mỗi service tự xin "service token" (JWT riêng, `sub=service-name`, TTL ngắn ~5 phút) từ Identity & Access qua IAM role (không cần secret tĩnh), đính kèm header khi gọi `IF-006`/`IF-021`/`IF-022`; bên nhận verify chữ ký giống verify JWT người dùng (tái dùng hạ tầng ký/verify đã có) | Không cần hạ tầng mới ngoài quy ước header + logic verify (tái dùng key JWT của `CMP-02`); tương thích với ghi chú "không thêm hạ tầng mới" của `SAD` | Cần Identity & Access cấp phát token cho service (thêm luồng nội bộ mới, nhỏ); vẫn phụ thuộc network layer làm lớp phòng thủ đầu (không phải mTLS full zero-trust) |
|
||
|
||
**Đề xuất SA: PA-3**, vì tương thích với ràng buộc đã ghi ở `SAD §7` v1.2 (không thêm hạ tầng mới
|
||
ở lượt này) trong khi vẫn nâng được một lớp phòng thủ so với hiện trạng thuần network. Ước lượng
|
||
radar theo `decision-radar.md §2`: chi phí đảo ngược trung bình (đổi cơ chế sau khi đã code tốn
|
||
sửa cả hai đầu gọi)=1 · bán kính: mọi lời gọi cross-network nội bộ (TB3, TB4) + tiền lệ cho các
|
||
`IF` tương lai=2 · chạm gián tiếp `QAS-002`/`QAS-010` (thêm bước xin token có thể ăn vào ngân sách
|
||
latency đã eo hẹp, cần đo lại)=1 · ràng buộc ≥1 năm (chuẩn nội bộ cho service-to-service)=1 · chưa
|
||
tranh cãi=0 → **~5, ở ngưỡng "ADR bắt buộc"**. Xem
|
||
[`adr/ADR-015_service-jwt-xac-thuc-service-to-service.md`](adr/ADR-015_service-jwt-xac-thuc-service-to-service.md)
|
||
(`Proposed`, viết ở hoạt động `adr` kế tiếp). `OQ-050` **giữ nguyên mở** — chặn cứng bởi `OQ-007`
|
||
(Security chưa có người được chỉ định; ADR bảo mật chỉ chuyển `Accepted` khi có Security thật ký,
|
||
xem `ADR-015 §0`/§3).
|
||
|
||
🔴 Đây là quyết định chạm cả `QAS-002` (latency) lẫn ranh giới hạ tầng — `ADR-015` ghi rõ điều
|
||
kiện `Accepted` cần cả Tech Lead lẫn Security (phủ quyết) cùng xác nhận trước khi chốt.
|
||
|
||
---
|
||
|
||
## 3. Phân quyền (Authorization)
|
||
|
||
| | Quyết định | `ADR` |
|
||
|---|---|---|
|
||
| **Mô hình** | RBAC đơn giản (2 vai trò trong phạm vi Cart&Checkout: Guest, Customer) + ABAC nhẹ cho ownership (đối chiếu `session_id`/`customer_id` với dữ liệu) | `ADR-007` |
|
||
| **Chỗ ra quyết định** | **Service** (Cart & Order tự kiểm tra), **không phải** gateway — `CMP-01` chỉ chuyển token/session xuống, đúng `SAD §4.1` | `ADR-007` |
|
||
| **Nguồn sự thật của vai trò** | Identity & Access (`CMP-02`) — `role` claim trong JWT (Customer/Seller/Admin); Guest không có "vai trò" theo nghĩa RBAC, chỉ có `session_id` | `CMP-02` |
|
||
| **Ràng buộc dữ liệu (row-level)** | Có — ownership theo `customer_id`/`session_id`, cache Redis TTL ngắn, fallback query DB khi cache miss | `ADR-007` |
|
||
| **Hành vi khi không xác định được quyền (lỗi kỹ thuật, không phải "không có quyền")** | **Fail-closed** — trả `503` (không phải `403`), mã lỗi đề xuất `E-CART-0007` (theo `FAIL §5`, chưa có trong `SRS`/`API` của BA — `OQ-040`) khi cả Redis lẫn DB đều lỗi lúc kiểm tra ownership. **Không bao giờ mặc định cho phép truy cập khi không kiểm tra được** | `FAIL FM-06`, `OQ-040` |
|
||
|
||
🔴 **Fail-closed là quyết định bảo mật, không phải quyết định hiệu năng** — nếu Tech Lead/Dev sau
|
||
này "tối ưu" bằng cách coi lỗi kỹ thuật = cho phép (fail-open) để giảm tỷ lệ lỗi 503, đó là một
|
||
lỗ hổng nghiêm trọng (bất kỳ ai cũng xem được giỏ/đơn của người khác khi hệ thống đang có sự cố).
|
||
Ghi rõ ở đây để Security có căn cứ phủ quyết nếu phát hiện vi phạm khi review code.
|
||
|
||
### 3.1 Map `RBAC` của bộ BA xuống quyền kỹ thuật
|
||
|
||
*`RBAC_CartCheckout_v1.0.md §1` chỉ có 2 `ROLE-nn` trong phạm vi module này (Seller/Admin/CSR/Ops
|
||
cố ý không đưa vào — xem `RBAC §1`). Cả 2/2 đã có dòng dưới đây — đủ điều kiện không chặn AG2 ở
|
||
mục này.*
|
||
|
||
| `ROLE-nn` (BA) | Vai trò kỹ thuật | Claim/định danh | Quyền trên `IF-nnn` | Ràng buộc dữ liệu | Ai gán vai trò này |
|
||
|---|---|---|---|---|---|
|
||
| `ROLE-01` Guest | `guest` (không có tài khoản, không JWT) | Header `X-Guest-Session-Id` (§2.1) | `IF-002` — `GET`/`PATCH`/`DELETE /v1/cart*`, `POST /v1/checkout` | 🔶 **chỉ `Cart`/`Order` có `session_id` = giá trị header hiện tại** — đối chiếu tại service (`ADR-007`), fail-closed nếu không kiểm tra được (`E-CART-0007`) | Hệ thống tự tạo tại lần truy cập đầu tiên chưa đăng nhập — không ai "gán", không cần phê duyệt |
|
||
| `ROLE-02` Customer | `customer` (JWT `role=customer`) | `sub` = `customerId` trong JWT (§2.2) | `IF-002` — cùng 4 endpoint như Guest | 🔶 **chỉ `Cart`/`Order` có `customer_id` = `sub`** — đối chiếu tại service, fail-closed tương tự | Identity & Access (`CMP-02`) tự động khi đăng ký/đăng nhập thành công — self-service, không cần phê duyệt nội bộ |
|
||
|
||
*Seller (`FR-19`, module Quản lý đơn hàng seller) và Admin/CSR/Ops (không có hành động trực tiếp
|
||
trong RQ-001…004) **ngoài phạm vi** map này theo đúng `RBAC_CartCheckout §1` — sẽ có `RBAC`/map
|
||
riêng khi module tương ứng tới lượt thiết kế chi tiết. `ASR-009` (MFA Admin) vẫn áp dụng xuyên
|
||
suốt bất kể module nào Admin thao tác (xem §2.3).*
|
||
|
||
### 3.2 Phân tách nhiệm vụ (SoD)
|
||
|
||
*Kế thừa nguyên trạng kết luận của `RBAC_CartCheckout §3` (BA): **không áp dụng được** trong phạm
|
||
vi module này — mọi hành động (tạo giỏ, tách đơn, chọn thanh toán) là tự phục vụ do chính khách
|
||
hàng thực hiện trên dữ liệu của họ, không có bước "người thứ hai duyệt". Việc tách đơn (`BR-CART-01`)
|
||
và xác nhận thanh toán (`BR-CART-06`) do hệ thống tự động thực hiện theo rule, không phải nhân sự
|
||
nội bộ phê duyệt.*
|
||
|
||
| Hành động | Người thực hiện không được đồng thời là | Cơ chế cưỡng chế |
|
||
|---|---|---|
|
||
| *(không có trong phạm vi module Giỏ hàng & Checkout — SoD sẽ cần thiết khi module Quản lý đơn hàng có bước Seller/CSR/Admin can thiệp thủ công, VD duyệt hoàn tiền — ngoài phạm vi tài liệu này)* | | |
|
||
|
||
---
|
||
|
||
## 4. Threat model — STRIDE
|
||
|
||
*Theo 8 ranh giới tin cậy ở §1. Mỗi `THR-nn`: loại STRIDE · tài sản bị nhắm · biện pháp · cách
|
||
kiểm chứng · truy vết `QAS`/`ASR`/`ADR`.*
|
||
|
||
### 4.1 TB1 — Client ↔ ALB/WAF
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-01` | Spoofing | Đánh cắp JWT/session qua XSS hoặc MITM (nếu TLS bị hạ cấp) | Token Customer, session Guest | 🔴 | TLS 1.2+ bắt buộc + HSTS; access token khuyến nghị giữ trong memory (SPA), không `localStorage`; cookie Guest `HttpOnly;Secure;SameSite=Lax` (đã có, `ICD §1`) | Test cấu hình TLS/HSTS tự động (`FIT-33` ứng viên) + code review chỗ lưu token phía FE | `QAS-010`, `ASR-007` |
|
||
| `THR-02` | Tampering | Client gửi giá/số lượng đã bị sửa (tamper qua devtools) để checkout giá thấp hơn | `POST /v1/checkout` request body | 🟠 | Server luôn tính giá/tổng từ `product_variant.price_amount`/`unit_price_snapshot` phía BE, **không tin** giá trị giá do client gửi (đã đúng thiết kế `ICD`, không phát hiện lỗ hổng cụ thể) | Test gửi giá giả trong payload, xác nhận BE bỏ qua và tự tính lại | `ASR-003`, `ADR-003` |
|
||
| `THR-04` | Information disclosure | TLS downgrade / lộ thông tin qua response header thừa (server banner, stack trace) | Toàn bộ traffic + response lỗi | 🟠 | HSTS, ẩn header `Server`/version; response `500` không bao giờ trả chi tiết exception, chỉ `traceId` (đã đúng thiết kế `ICD §1` mục 4) | Scan cấu hình TLS (SSL Labs-style) định kỳ; test gọi lỗi 500 xác nhận không rò rỉ stack trace | — |
|
||
| `THR-05` | Denial of Service | Volumetric/L7 flood tại biên (trước khi tới ứng dụng) | `CMP-01` WAF/ALB, toàn bộ hệ thống phía sau | 🟠 | WAF rate-based rule + AWS Shield Standard (mặc định có với CloudFront/ALB); rate-limit theo IP ở tầng WAF trước khi request chạm ứng dụng | Load test giả lập burst traffic trên staging (ứng viên `FIT`, ngoài phạm vi diễn tập GĐ2) | `QAS-009` |
|
||
|
||
### 4.2 TB2 — ALB → Nhóm Giao dịch (ownership/IDOR)
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-06` | Spoofing | Guest session id bị đoán (nếu CSPRNG yếu) hoặc bị lộ qua log/URL | `X-Guest-Session-Id` | 🔴 | CSPRNG ≥128-bit (đã chốt `ICD §1` mục 10); **cấm** đưa session id vào query string/URL (chỉ header/cookie); log-scrubber không ghi giá trị đầy đủ | Test entropy giá trị sinh ra; grep log staging xác nhận không xuất hiện session id đầy đủ | `QAS-010` |
|
||
| `THR-07` | Elevation of Privilege | IDOR — request giả mạo `cartItemId`/`orderId` không phải chủ sở hữu | `CMP-04` mọi endpoint `IF-002` | 🔴 | Ownership check bắt buộc tại service (`ADR-007`), 0% bypass, fail-closed khi lỗi kỹ thuật (`E-CART-0007`) | Integration test tự động gọi API với token/session không phải chủ sở hữu — 0 lượt thành công (đã có ở `QAS-010`, tương ứng `AC-US003-12/13`) | `QAS-010`, `ASR-007`, `ADR-007` |
|
||
| `THR-08` | Denial of Service | Guest lạm dụng `PATCH`/`DELETE /v1/cart/items` (spam thêm/xoá liên tục) để tiêu tốn tài nguyên hoặc thao túng tồn kho reserve | `CMP-04`, `CMP-03` (reserve tồn kho) | 🟠 | Rate limit theo IP + `session_id` — xem đề xuất số cụ thể ở §5.3 (`OQ-023`) | Test gửi burst request vượt ngưỡng, xác nhận `429` | `RBAC_CartCheckout §8` `OQ-015` (BA) |
|
||
|
||
### 4.3 TB3 — Nhóm Giao dịch ↔ Nhóm Hỗ trợ (`IF-021`/`IF-022`, cross-network)
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-09` | Spoofing | Không có xác thực danh tính bên gọi — bất kỳ tiến trình nào trong VPC có thể giả danh Cart & Order gọi `IF-021`/`IF-022` nếu security group không chặt | `CMP-07`, `CMP-05` | 🔴 | Service JWT ngắn hạn — [`ADR-015`](adr/ADR-015_service-jwt-xac-thuc-service-to-service.md) (`Proposed`, **chưa `Accepted`** — chặn bởi `OQ-007`/`OQ-050`) | Chưa kiểm chứng được — chặn bởi `ADR-015` chưa `Accepted` | `OQ-050`, `ADR-015` |
|
||
| `THR-10` | Tampering | Payload `IF-021` (áp dụng coupon) bị giả mạo giá trị giảm giá vượt hợp lệ nếu Promotion&Loyalty không validate chặt | `CMP-07` | 🟠 | Validate bounds: giá trị giảm ≥0 và ≤ tổng tiền đơn hàng (đã ghi ở `FAIL §2` `FM-12` câu hỏi 3) | Test gửi giá trị giảm âm/vượt tổng, xác nhận bị từ chối | `FAIL FM-12` |
|
||
| `THR-11` | Information disclosure | `IF-022` trả nhầm thông tin seller khác (nếu logic tra cứu sai `seller_id`) hoặc lộ PII khách hàng nếu tương lai `IF-022` đổi chiều mang theo dữ liệu khách | `CMP-05` | 🟠 | Denormalize `sellerName` snapshot (không JOIN ngược runtime, `ICD §3.7`) giảm bề mặt; nếu vẫn cần gọi runtime, kiểm tra input `seller_id` khớp đúng `OrderSeller` đang xử lý | Contract test xác nhận response chỉ chứa đúng trường mong đợi | `OQ-032`, `OQ-033` |
|
||
| `THR-12` | Denial of Service | Retry storm/cascading failure — Nhóm Hỗ trợ chậm/hỏng kéo theo Cart&Order giữ tài nguyên (đã phân tích ở `FAIL FM-12`) | `CMP-04`, `CMP-07` | 🟠 | Circuit breaker cho `IF-021` (đã thiết kế `FAIL §3.1`), 0 retry trong đường găng checkout | Chaos test giả lập `IF-021` timeout liên tục, xác nhận circuit breaker mở đúng ngưỡng (`FIT-19`, đã có ở `FAIL`) | `FAIL FM-12`, `QAS-002` |
|
||
|
||
### 4.4 TB4 — Cart & Order ↔ Payment (`IF-006`)
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-13` | Spoofing | Không có xác thực danh tính — một service khác trong VPC có thể giả danh Cart & Order để khởi tạo `Payment` giả | `CMP-11` | 🔴 | Cùng biện pháp `THR-09` — [`ADR-015`](adr/ADR-015_service-jwt-xac-thuc-service-to-service.md) (`Proposed`). **Đây là ranh giới nhạy cảm nhất (tiền thật)** — ưu tiên xử lý cao nhất, `ADR-015` chưa `Accepted` | Chưa kiểm chứng được — chặn bởi `ADR-015` chưa `Accepted` | `ASR-002`, `OQ-050`, `ADR-015` |
|
||
| `THR-14` | Tampering | `amountVnd` trong request `IF-006` không khớp `OrderSeller.subtotal_amount` thật (do bug hoặc bên gọi bị compromise) | `CMP-11` | 🔴 | Payment Service phải **tự đối chiếu lại** `amountVnd` nhận được với giá trị tính từ `OrderSeller` (không tin tưởng tuyệt đối request đến, dù cùng nội bộ) — 🔴 **chưa được `ICD §3.3` ghi nhận là bước bắt buộc**, đề xuất bổ sung ở lượt `icd`/`dat` kế tiếp | Test gửi `amountVnd` sai lệch, xác nhận Payment Service từ chối thay vì tin theo | `ADR-002`, `ADR-003` |
|
||
| `THR-15` | Repudiation | Không truy vết được ai/service nào đã trigger một `Payment` cụ thể nếu thiếu correlation id | `CMP-11` | 🟡 | `X-Request-Id` (`OQ-031`) xuyên suốt + audit log ghi `actor`/`correlation_id` (§7) | Kiểm tra log Payment Service có `correlation_id` khớp với log Cart & Order cho cùng giao dịch | `OQ-031` |
|
||
| `THR-16` | Elevation of Privilege | Module khác (ngoài Payment) cố truy cập trực tiếp RDS Payment (bỏ qua `IF-006`/`IF-017`) | `CMP-14` | 🔴 | Network/IAM cô lập hoàn toàn (`ADR-002`) — không security group nào khác được phép kết nối `RDS Payment` | Kiểm tra hạ tầng: Terraform plan/AWS Config rule xác nhận không có security group nào khác trỏ tới RDS Payment (đã có `FIT-03` ở `ADR-002`) | `ASR-002`, `ADR-002`, `FIT-03` |
|
||
|
||
### 4.5 TB5 — Payment ↔ VNPay/Momo (init sync + webhook inbound async)
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-17` | Spoofing | Webhook IPN giả mạo (kẻ tấn công tự gọi endpoint webhook giả lập giao dịch thành công) | `CMP-11`, `payment.status` | 🔴 | Xác thực chữ ký/HMAC theo tài liệu VNPay/Momo — **🔴 chưa có tài liệu/sandbox thật, không bịa cơ chế cụ thể** (`ARISK-03`). Đề xuất SA: từ chối cứng mọi webhook không xác minh được chữ ký hợp lệ, **không** xử lý "tạm chấp nhận rồi kiểm tra sau" | 🔴 **Chưa kiểm chứng được** — chặn bởi thiếu sandbox. Khi có sandbox: test gửi webhook chữ ký sai, xác nhận bị từ chối và ghi log cảnh báo (khả năng giả mạo, không coi là lỗi hệ thống thường — đã ghi ở `FAIL §2` `FM-01/02`) | `ADR-004`, `ARISK-03`, `OQ-049` |
|
||
| `THR-18` | Tampering | Replay webhook cũ (gửi lại payload hợp lệ đã xử lý trước đó để trigger lại logic) | `CMP-11` | 🟠 | Idempotency theo `gatewayTransactionRef` (`ADR-004`) + kiểm tra `timestamp` payload lệch ≤5 phút (`ICD §1` mục 12) — đã xử lý cả 2 lớp (idempotent + chống replay theo thời gian) | Test gửi lại đúng webhook cũ ngoài cửa sổ 5 phút, xác nhận bị từ chối; gửi lại trong cửa sổ, xác nhận idempotent (không xử lý lại nghiệp vụ) | `ADR-004`, `QAS-014` |
|
||
| `THR-19` | Information disclosure | `gateway_response_snapshot` vô tình chứa dữ liệu thẻ nếu gateway trả về ngoài dự kiến | `payment_transaction.gateway_response_snapshot` (`DAT §2.1`) | 🔴 | Whitelist field được lưu trước khi ghi (lọc bỏ mọi trường không nằm trong danh sách kỳ vọng, **mặc định từ chối lưu trường lạ** thay vì mặc định chấp nhận) — đề xuất mới, chưa có trong `DAT` hiện tại | Test giả lập gateway trả thêm trường lạ (VD số thẻ rút gọn), xác nhận không được ghi vào `gateway_response_snapshot` | `ASR-002`, `BR-CART-05` (BA) |
|
||
| `THR-20` | Repudiation | Không phát hiện được giao dịch bị VNPay/Momo báo sai trạng thái (báo `success` nhưng thực tế tiền chưa về, hoặc ngược lại) | `payment.status` | 🟠 | Job đối soát bù định kỳ ≤15 phút (`ADR-004`, `QAS-014`) — không tự động sửa, chỉ ghi `ReconciliationLog` + cảnh báo | Test giả lập webhook trễ/mất trên staging (cần sandbox thật để đầy đủ — `FIT-21`, đã có ở `FAIL`) | `ADR-004`, `QAS-014` |
|
||
| `THR-21` | Denial of Service | Webhook flooding (đối tác hoặc kẻ tấn công gửi số lượng lớn webhook giả) | `CMP-11` | 🟡 | Rate limit endpoint webhook theo nguồn IP đối tác đã biết (whitelist IP nếu đối tác công bố dải IP cố định — 🔴 chưa xác nhận, `OQ-049`); WAF chung ở TB1 vẫn áp dụng | Load test endpoint webhook trên staging | `ARISK-03` |
|
||
|
||
### 4.6 TB6 — Shipping & Fulfillment ↔ GHN/GHTK webhook
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-22` | Spoofing | Webhook cập nhật trạng thái vận chuyển giả mạo | `CMP-10`, `shipment.status` | 🟠 | Chữ ký/token theo tài liệu GHN/GHTK — **🔴 chưa có tài liệu/sandbox thật** (`ARISK-04`), không bịa cơ chế cụ thể | Chưa kiểm chứng được — chặn bởi thiếu sandbox | `ARISK-04`, `OQ-049` |
|
||
| `THR-23` | Tampering | Trạng thái vận đơn "thụt lùi" (từ "đang giao" về "đã tạo đơn") do webhook lỗi/giả mạo | `shipment.status` | 🟡 | Không ghi đè khi trạng thái mới "thụt lùi" so với trạng thái tiến bộ nhất đã ghi (đã thiết kế ở `FAIL §2` `FM-03/04`), cảnh báo Ops kiểm tra thủ công | Test gửi webhook trạng thái thụt lùi, xác nhận không ghi đè | `FAIL FM-03/04` |
|
||
|
||
### 4.7 TB7 — App ↔ RDS/Redis/SQS
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-24` | Information disclosure | Một module đọc/ghi nhầm schema của module khác trong cùng RDS chính (schema-per-module nhưng chung instance/IAM lỏng lẻo) | `CMP-13` (8 schema) | 🟠 | IAM DB role riêng theo module, chỉ cấp quyền đúng schema của module đó (Postgres role + `GRANT` theo schema) — 🔴 **chưa được `DAT`/`ADR-006` xác nhận chi tiết cấp quyền**, đề xuất bổ sung ở `inf` | Kiểm tra `GRANT`/role Postgres qua migration review; test connection dùng role module A cố `SELECT` schema module B, xác nhận bị từ chối | `ADR-006`, `D7` |
|
||
| `THR-25` | Tampering | Producer không hợp lệ (service bị compromise hoặc external actor với network access) publish message giả vào SQS/EventBridge | `CMP-12` | 🟠 | IAM policy giới hạn `sqs:SendMessage`/`events:PutEvents` chỉ cho ECS task role của `CMP-04`/`CMP-11` (publisher hợp lệ duy nhất); consumer validate schema (`eventVersion`, field bắt buộc) trước khi xử lý, message không hợp lệ → DLQ (đã có ở `FAIL §2` `FM-09/10`) | Kiểm tra IAM policy qua Terraform plan; test publish message sai schema, xác nhận route DLQ | `ADR-005`, `FAIL FM-09/10` |
|
||
| `THR-26` | Information disclosure | Kết nối Redis không mã hoá in-transit trong VPC (nếu VPC bị compromise, traffic session/ownership cache có thể bị nghe lén) | `CMP-15` | 🟡 | Bật TLS in-transit cho ElastiCache Redis (encryption in-transit, tính năng có sẵn của AWS) — 🔴 **chưa xác nhận đã bật hay chưa trong cấu hình `INF` (chưa chạy)** | Kiểm tra cấu hình ElastiCache khi `inf` chạy | `INF` (hoạt động 7, chưa chạy) |
|
||
| `THR-27` | Denial of Service | Một module (đọc nặng, VD Catalog search) chiếm hết connection pool RDS chung, chặn module ghi (checkout) | `CMP-13` | 🟠 | Bulkhead — connection pool riêng theo module (đã ghi nhận ở `FAIL §3.3`, kích thước cụ thể chờ `POC-02`, `OQ-037`) | Load test saturate pool 1 module, xác nhận module khác không bị ảnh hưởng (`FIT-22`, đã có ở `FAIL`) | `FAIL FM-06`, `OQ-037` |
|
||
|
||
### 4.8 TB8 — Admin console
|
||
|
||
| ID | Loại (STRIDE) | Mối đe doạ | Thành phần bị nhắm | Mức | Biện pháp | Cách kiểm chứng | Truy vết |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `THR-28` | Spoofing | Đánh cắp/dò mật khẩu Admin (không có MFA bypass path) | `CMP-02` (Admin) | 🔴 | MFA bắt buộc TOTP (`ASR-009`), account lockout sau 3 lần sai (§2.3, đề xuất) | Test đăng nhập Admin không qua MFA, xác nhận bị từ chối (đã có ở `QAS-012`) | `QAS-012`, `ASR-009` |
|
||
| `THR-29` | Elevation of Privilege | Thiếu kiểm tra scope/role dẫn tới Customer/Seller gọi được endpoint Admin | `CMP-02` và mọi endpoint quản trị | 🔴 | Middleware kiểm tra `role`/scope claim bắt buộc trước business logic (nguyên tắc chung, tham khảo ý tưởng P1 `docs/08 §8.1.2`, tự quyết định lại cho P2 vì P2 không có OPA/BFF riêng như P1) | Test gọi endpoint Admin bằng JWT `role=customer`, xác nhận `403` | `ASR-009` |
|
||
| `THR-30` | Repudiation | Hành động Admin (khoá tài khoản, duyệt seller...) không được ghi vết | Toàn hệ thống, đặc biệt module ngoài phạm vi US-002/003 | 🟠 | `audit_log` bắt buộc cho mọi hành động Admin nhạy cảm (§7) | Kiểm tra coverage: mọi endpoint `role=admin` ghi được ≥1 dòng `audit_log` tương ứng (`FIT-32` mới) | `RBAC_CartCheckout §5` |
|
||
| `THR-31` | Denial of Service | Brute-force đăng nhập Admin (dò mật khẩu hàng loạt) | `/v1/auth/login` (Admin) | 🟠 | Account lockout (§2.3) + rate-limit theo IP (§5.3) + captcha sau N lần sai (tham khảo ý tưởng P1, chưa chốt ngưỡng cho P2) | Test brute-force giả lập, xác nhận khoá đúng ngưỡng | `OQ-052` |
|
||
|
||
### 4.9 Mối đe doạ đã chấp nhận
|
||
|
||
| `THR` | Vì sao chấp nhận | Ai ký · ngày | Dấu hiệu cảnh báo | Kế hoạch nếu xảy ra |
|
||
|---|---|---|---|---|
|
||
| *(chưa có mục nào — Security chưa có người để ký chấp nhận rủi ro, `OQ-007`. Không tự chấp nhận rủi ro thay Security theo `D10`.)* | | | | |
|
||
|
||
🔴 **Tổng kết:** 31 `THR` được liệt kê (`THR-01…31`, một số ID không liên tục do rà soát nhóm theo
|
||
STRIDE không đều ở mỗi ranh giới — không có ID nào bị bỏ trống ngầm). **Bốn nhóm mức 🔴 cao nhất
|
||
chưa có biện pháp đủ**: (1) `THR-09`/`THR-13` — thiếu service-to-service authn ở TB3/TB4 (§2.4,
|
||
`OQ-050`); (2) `THR-17`/`THR-22` — chữ ký webhook thật chưa xác nhận được vì thiếu sandbox đối tác
|
||
(`OQ-049`, `ARISK-03/04`); (3) `THR-19` — lọc trường `gateway_response_snapshot` chưa triển khai;
|
||
(4) mọi threat liên quan PII (`THR-11` gián tiếp) phụ thuộc `OQ-007` chưa có người phủ quyết.
|
||
|
||
---
|
||
|
||
## 5. Bảo vệ dữ liệu
|
||
|
||
🔴 **Toàn bộ mục này (§5) là ĐỀ XUẤT của SA, CHƯA CÓ HIỆU LỰC PHỦ QUYẾT** — Security/Pháp chế
|
||
chưa có người được chỉ định (`OQ-007`, mở từ GĐ1, kế thừa `RISK-03` của BA). Không coi bất kỳ dòng
|
||
nào dưới đây là quyết định cuối cùng.
|
||
|
||
### 5.1 Phân loại & mã hoá
|
||
|
||
*Kế thừa nguyên trạng phân loại đã có ở `DAT_e-commerce_v1.0.md §5` (không lặp lại toàn bộ bảng —
|
||
tham chiếu bằng đường dẫn theo `D` "không copy nội dung giữa các tài liệu"). SEC xác nhận lại góc
|
||
độ bảo mật/kiểm chứng cho từng nhóm:*
|
||
|
||
| Nhóm dữ liệu | Mã hoá at-rest | Mã hoá in-transit | Che khi hiển thị | Che khi log | Nguồn phân loại |
|
||
|---|---|---|---|---|---|
|
||
| Danh tính & liên hệ khách hàng (`email`/`phone`/`full_name`) | RDS KMS mặc định (đề xuất `DAT §5`) | TLS 1.2+ mọi kết nối (§1) | Không che với chính chủ; không hiển thị cho seller | **Bắt buộc** — log-scrubber mask `email`/`phone` (đề xuất mới, tham khảo ý tưởng P1 `docs/08 §8.2.3`, tự quyết định lại) | `DAT §5` |
|
||
| Địa chỉ giao hàng (`recipient_name`/`phone`/`address_line`) | RDS KMS | TLS 1.2+ | **Whitelist cho seller** — chỉ 3 trường trên, đúng `OrderSeller` liên quan (`ADR-008` PA-2, đề xuất) — 🔴 **mức che (full hay một phần) chưa chốt**, xem `OQ-053` (mới) | Bắt buộc mask trong log ứng dụng | `DAT §5`, `RBAC §4` |
|
||
| KYC seller (`file_url_s3`, `tax_code`, `business_license_number`) | S3 SSE-KMS + RDS KMS; đề xuất mã hoá tầng ứng dụng bổ sung (tham khảo ý tưởng P1 `docs/08 §8.2.1`) | TLS 1.2+ | Chỉ Admin/CSR đã duyệt xem (ngoài phạm vi module này) | Không log giá trị đầy đủ; nếu cần audit, mask giữ vài ký tự đầu/cuối (tham khảo ý tưởng P1 `docs/08 §8.2.5a`) | `DAT §5` |
|
||
| Tài khoản ngân hàng seller (`account_number`) | **Bắt buộc mã hoá tầng ứng dụng** (không chỉ KMS) | TLS 1.2+ | Che một phần khi hiển thị (VD `****1234`) | Che hoàn toàn, không log giá trị | `DAT §5` |
|
||
| Dữ liệu thanh toán (`payment.amount`, `gateway_transaction_ref`, `gateway_response_snapshot` đã lọc) | RDS KMS (RDS Payment riêng, `ADR-002`) + đề xuất mã hoá tầng ứng dụng cho `gateway_transaction_ref` | TLS 1.2+, RDS Payment mạng riêng | Chỉ hiển thị tham chiếu rút gọn cho khách | **Tuyệt đối không log** `gateway_response_snapshot` thô ở mức DEBUG production | `DAT §5`, `ADR-002` |
|
||
| Dữ liệu nghiệp vụ công khai (`product`, `category`, `review`) | RDS KMS mặc định | TLS 1.2+ | Không cần che | Không cần che | `DAT §5` |
|
||
|
||
🔴 **Dữ liệu production trên môi trường dev/staging bị cấm tuyệt đối** — đúng nguyên tắc template
|
||
mục 5. Yêu cầu quy trình anonymize khi sao chép Production → Staging (hash/mask `email`/`phone`,
|
||
xoá `tax_code`/`account_number` thật, thay bằng dữ liệu giả lập nhất quán) — **chưa có quy trình
|
||
cụ thể cho P2**, đề xuất tham khảo ý tưởng P1 (`docs/08 §8.2.3`), ghi nhận là việc cần làm ở hoạt
|
||
động `inf` (§7 non-prod topology).
|
||
|
||
### 5.2 Whitelist chia sẻ PII cho seller — hiện thực hoá `ADR-008` PA-2
|
||
|
||
*Đúng như `ADR-008` (Proposed, chờ Security/Legal) và `DAT §5.2` đã thiết kế: `order_seller` chỉ
|
||
lưu snapshot đúng 3 trường (`recipient_name`, `phone`, `address_line`) — không JOIN ngược sang
|
||
schema `identity`. SEC xác nhận lại từ góc độ threat model: đây là biện pháp giảm bề mặt rủi ro
|
||
đúng (`THR-11`), nhưng bản thân việc "3 trường này có nên hiển thị đầy đủ hay che một phần cho
|
||
seller" **vẫn là câu hỏi mở** — xem `OQ-053`.*
|
||
|
||
🔴 **Nếu Security/Legal từ chối PA-2 khi có người ký, toàn bộ §5.1/§5.2 và cơ chế denormalize ở
|
||
`DAT §5.2`/`ICD §3.7` phải thiết kế lại** — đây là rủi ro kiến trúc đã ghi nhận ở `ADR-008 §3`,
|
||
không phải điều mới phát hiện ở `sec`.
|
||
|
||
### 5.3 Đề xuất rate limit — trả lời `OQ-023`
|
||
|
||
*🔴 `OQ-023` yêu cầu: "SEC đề xuất số cụ thể + hệ quả, không tự quyết thay Security." Bảng dưới là
|
||
**đề xuất**, Security là người chốt cuối.*
|
||
|
||
| Endpoint/hành động | Ngưỡng đề xuất | Đơn vị đếm | Hệ quả nếu Security chọn CHẶT hơn | Hệ quả nếu Security chọn LỎNG hơn |
|
||
|---|---|---|---|---|
|
||
| `PATCH`/`DELETE /v1/cart/items` (Guest) | **30 request/phút** | Theo `session_id` (chính) + 60 req/phút theo IP (phòng vệ phụ, chống một IP tạo nhiều session để né giới hạn theo session) | VD 10/phút: giảm mạnh khả năng spam/thao túng tồn kho reserve, nhưng có thể chặn nhầm khách thao tác nhanh trên UI (VD sửa số lượng nhiều dòng liên tiếp) — tăng khiếu nại trải nghiệm | VD 100/phút: giảm false positive, nhưng dễ bị lạm dụng để giữ/giải phóng tồn kho reserve liên tục (làm nhiễu `inventory_stock`, ảnh hưởng gián tiếp trải nghiệm khách thật muốn mua) |
|
||
| `POST /v1/checkout` | **10 request/phút** theo `session_id`/`customer_id` | Theo định danh (Guest: session, Customer: customer_id) | VD 3/phút: an toàn hơn trước spam tạo đơn giả (`RBAC §8` `OQ-015` của BA), nhưng khách thao tác thật thử lại nhiều lần sau lỗi 4xx/5xx có thể bị chặn oan | VD 30/phút: giảm false positive khi khách retry sau lỗi mạng, nhưng tăng rủi ro spam tạo `Order`/giữ tồn kho reserve hàng loạt |
|
||
| `POST /v1/auth/login` (mọi vai trò) | **10 request/phút theo IP** (độc lập với account lockout §2.3, đây là lớp phòng thủ theo IP) | Theo IP | VD 3/phút: chống brute-force mạnh hơn, nhưng ảnh hưởng người dùng chung IP NAT (mạng công ty/quán net Việt Nam khá phổ biến) | VD 50/phút: giảm false positive NAT, nhưng làm yếu lớp phòng thủ IP (vẫn còn account lockout §2.3 làm lớp thứ hai) |
|
||
| Webhook inbound (`IF-007`/`IF-008`/`IF-018`/`IF-019`) | Không giới hạn cứng theo request/phút (đối tác tự quyết định tần suất gọi lại) — chỉ giới hạn ở WAF chung (TB1) chống flood bất thường | — | — | — |
|
||
|
||
🔴 **Ba con số trên (30, 10, 10) là ước lượng SA dựa trên hành vi UI thông thường (không có dữ liệu
|
||
traffic thật, `greenfield`)** — không phải kết quả đo. Security cần xác nhận hoặc điều chỉnh dựa
|
||
trên khẩu vị rủi ro thật của tổ chức.
|
||
|
||
---
|
||
|
||
## 6. Quản lý secret
|
||
|
||
| | Quyết định |
|
||
|---|---|
|
||
| Nơi lưu | **AWS Secrets Manager** cho: DB credentials (RDS chính + RDS Payment, **secret riêng biệt**, không chung), API key/secret VNPay/Momo/GHN/GHTK, JWT signing key (`CMP-02`), SMTP/SMS provider key (khi có nhà cung cấp, `OQ-016` của `TCO`) |
|
||
| Cách ứng dụng lấy | ECS task role (IAM) có quyền `secretsmanager:GetSecretValue` **chỉ đúng secret của module đó** — không task nào được đọc secret của module khác (đối xứng với nguyên tắc cô lập schema §4.7) |
|
||
| Xoay khoá: tần suất, tự động hay thủ công | DB credentials: **tự động** (AWS Secrets Manager rotation Lambda, chu kỳ đề xuất 30 ngày — chưa Tech Lead xác nhận); API key đối tác ngoài: **thủ công**, chu kỳ đề xuất 90 ngày (phụ thuộc khả năng hỗ trợ rotation của từng đối tác — 🔴 chưa xác nhận VNPay/Momo/GHN/GHTK có hỗ trợ rotate key không, `ARISK-03/04`); JWT signing key: xoay 90 ngày, dùng `kid` để hỗ trợ 2 khoá song song (§2.2) |
|
||
| **Cấm tuyệt đối** | Secret trong mã nguồn/Git, secret trong biến môi trường bị ghi vào log (log-scrubber phải chặn pattern giống secret), secret trong ảnh container (build-time bake) |
|
||
| Cách phát hiện rò rỉ | Quét mã nguồn trong CI/CD (Gitleaks/TruffleHog) — chặn merge nếu phát hiện secret pattern; `FIT-29` (mới, ứng viên GĐ3) |
|
||
|
||
---
|
||
|
||
## 7. Audit log
|
||
|
||
*Theo phương án (a) đã chốt TẠM ở `OQ-047`/`DEC-25` (`DAT`): **mỗi module tự ghi `audit_log` trong
|
||
schema của mình**, KHÔNG có `CMP-16` Audit tập trung. SEC chốt trường bắt buộc + retention +
|
||
chống sửa cho quy ước chung áp dụng mọi module.*
|
||
|
||
| Hành động phải ghi | Ghi những trường gì | Ai đọc được | Giữ bao lâu | Chống sửa bằng cách nào |
|
||
|---|---|---|---|---|
|
||
| Tạo `Order`/`OrderSeller` (checkout) | `actor_type` (guest/customer)· `actor_id` (`customer_id`/`session_id`) · `action` · `resource_type`/`resource_id` · `ip_address` · `correlation_id` (`X-Request-Id`, `OQ-031`) · `timestamp` (UTC) · `result` | Chính chủ đơn (qua tra cứu); nội bộ Kế toán/CSKH (module ngoài phạm vi US-002/003) | **10 năm** — nhất quán retention tài chính (`DAT §6`) | Bảng `append-only` — role ứng dụng chỉ có `INSERT`/`SELECT`, không `UPDATE`/`DELETE` (cưỡng chế ở DB role, không chỉ ở tầng code) |
|
||
| Khởi tạo thanh toán / cập nhật `payment.status` | Tương tự trên + `payment_method`, `gateway_transaction_ref` (đã che theo §5.1) | Chính chủ đơn; nội bộ Kế toán | 10 năm | Tương tự trên (schema `payment`, RDS riêng theo `ADR-002`) |
|
||
| Đăng nhập/thất bại (mọi vai trò) | `actor_id`, `role`, `ip_address`, `result` (success/fail), `timestamp`, `mfa_used` (bool) | Platform Admin (scope `admin:audit:read` — ý tưởng tham khảo P1, tự quyết định lại cho P2 vì chưa có endpoint đọc audit riêng) | 5 năm (đề xuất, tham khảo ý tưởng P1) | Append-only, schema `identity` |
|
||
| Thay đổi quyền / khoá tài khoản (Admin) | `actor_id` (Admin thực hiện), `target_id`, `before`/`after` (redact trường nhạy cảm nếu có), `reason` (nếu có), `timestamp` | Platform Admin | 5 năm | Append-only, schema `identity` |
|
||
| Truy cập dữ liệu nhạy cảm (VD Admin xem KYC document) | `actor_id`, `resource_type`/`resource_id`, `timestamp` — **không ghi nội dung tài liệu, chỉ ghi hành động xem** | Platform Admin | 5 năm | Append-only (module Seller Mgmt, ngoài phạm vi chi tiết US-002/003) |
|
||
| Ownership check thất bại (IDOR bị chặn) | `actor_id`/`session_id`, `resource_type`/`resource_id` bị yêu cầu, `ip_address`, `timestamp` — phục vụ điều tra khi nghi ngờ tấn công hàng loạt | Security (khi có người) | 🔴 chưa chốt — đề xuất 1 năm, thấp hơn nhóm tài chính vì mục đích khác (an ninh vận hành, không phải bằng chứng giao dịch) | Append-only |
|
||
|
||
🔴 **Audit log mà người bị audit sửa được thì không phải audit log** — mỗi schema-per-module
|
||
(`ADR-006`) phải cưỡng chế `append-only` ở mức DB role của chính schema đó, không có ngoại lệ cho
|
||
`platform_admin` (Admin xem được nhưng không sửa/xoá được bản ghi audit).
|
||
|
||
🔴 **Khoảng trống đã biết:** không có `CMP` Audit tập trung (phương án (a)) nghĩa là **không có
|
||
một nơi duy nhất** để Security truy vấn xuyên toàn sàn khi điều tra sự cố — mỗi module phải được
|
||
truy vấn riêng. Đây là đánh đổi đã chấp nhận TẠM ở `DEC-25`, chưa Security thật xác nhận. Nếu
|
||
Security khi có người yêu cầu audit tập trung, cần mở lại `OQ-047` và có thể đảo ngược sang
|
||
phương án (b) (`CMP-16`) — chi phí đảo ngược: thêm 1 service mới + migrate log lịch sử từ N schema
|
||
sang 1 nơi.
|
||
|
||
---
|
||
|
||
## 8. Tuân thủ
|
||
|
||
### 8.1 PCI-DSS SAQ A
|
||
|
||
| Yêu cầu | Nguồn | Cách đáp ứng | Bằng chứng cho kiểm toán | Ai xác nhận |
|
||
|---|---|---|---|---|
|
||
| Không lưu PAN/CVV ở bất kỳ đâu ngoài Payment Service | `CON-06`, `BR-CART-05` (BA), `ADR-002` | `payment_transaction.gateway_response_snapshot` phải lọc trước khi ghi (`THR-19`); schema linter chặn cột kiểu "card_number"/"cvv" ở mọi schema khác `payment` | `FIT-04` (đã đề xuất ở `ADR-002`) | Security (chưa có người) |
|
||
| Ranh giới mạng/IAM/dữ liệu cô lập hoàn toàn | `ASR-002`, `ADR-002` | Network diagram + IAM policy review; không security group nào khác trỏ tới RDS Payment | `FIT-03` (đã đề xuất ở `ADR-002`) | Security |
|
||
| **Hình thức tích hợp VNPay/Momo phải là redirect, không nhúng iframe/form nhập thẻ trên domain sàn** *(đề xuất mới)* | Suy luận từ yêu cầu SAQ A (tham khảo `docs/08 §8.4`: "nếu redirect, scope tương ứng SAQ A") | **🔴 Chưa xác nhận được với VNPay/Momo thật** — chưa có tài liệu tích hợp, chưa biết họ có hỗ trợ redirect thuần hay bắt buộc SDK/iframe nào đó. Nếu chỉ hỗ trợ iframe/API pass-through dữ liệu thẻ, **toàn bộ giả định SAQ A của `ASR-002`/`ADR-002` phải xét lại** (có thể cần nâng cấp phạm vi tuân thủ, ảnh hưởng chi phí `TCO`) | — | Tech Lead + Security (`OQ-048`, mới) |
|
||
| Webhook: chữ ký/HMAC theo tài liệu đối tác | `ADR-004` | 🔴 **Chưa biết cơ chế cụ thể** (SecureHash/HMAC-SHA256/khác) — không bịa, chờ tài liệu đối tác | `THR-17` | `OQ-049` (mới), `ARISK-03` |
|
||
| Chống replay webhook | `ADR-004` | Kiểm tra `timestamp` payload lệch ≤5 phút (đã chốt, `ICD §1` mục 12) | `THR-18` | Đã đủ điều kiện kỹ thuật, chờ sandbox để kiểm chứng thật |
|
||
| Quét lỗ hổng ASV hàng quý | `CON-06` | Nhà cung cấp ASV bên ngoài — 🔴 chưa có báo giá | Báo cáo ASV | Security (`OQ-017`, đã mở ở `TCO`) |
|
||
| Pentest ứng dụng hàng năm | `CON-06` | Nhà cung cấp pentest bên ngoài — 🔴 chưa có báo giá | Báo cáo pentest | Security (`OQ-017`) |
|
||
|
||
### 8.2 NĐ13/2023 (Bảo vệ dữ liệu cá nhân)
|
||
|
||
| Yêu cầu | Nguồn | Cách đáp ứng | Bằng chứng | Ai xác nhận |
|
||
|---|---|---|---|---|
|
||
| Data minimization khi chia sẻ PII cho seller | `ASR-008`, `QAS-011`, `ADR-008` | Whitelist 3 trường (§5.2) — **đề xuất, chưa hiệu lực** | Contract test (`FIT-11`, đã đề xuất ở `ADR-008`) | **Security/Legal — chưa có người (`OQ-007`)** |
|
||
| Residency dữ liệu tại `ap-southeast-1` đáp ứng đủ yêu cầu | `CON-06`, `ASM-04` | 🔴 **Chưa xác nhận** — chỉ là giả định (`ASM-04`) | — | Legal (`OQ-007`) |
|
||
| Quyền được xoá / ẩn danh hoá | `CON-06` | Đề xuất 30 ngày ẩn danh hoá kể từ yêu cầu hợp lệ (`DAT §5`) — **đề xuất, chờ Legal** | — | Legal (`OQ-007`) |
|
||
| Xác thực danh tính người yêu cầu xoá (chống giả mạo yêu cầu xoá tài khoản người khác) | Ý tưởng tham khảo P1 (`docs/08 §8.2.4`), chưa thiết kế cụ thể cho P2 | 🔴 Chưa thiết kế | — | Legal + Tech Lead (mới, ngoài phạm vi US-002/003) |
|
||
|
||
### 8.3 NĐ52/85 (thông báo website TMĐT marketplace)
|
||
|
||
*Chủ yếu là nghĩa vụ pháp lý/hành chính (đăng ký với Bộ Công Thương), không phải control kỹ thuật
|
||
thuộc `SEC`. Yêu cầu kỹ thuật liên quan (hiển thị thông tin đăng ký ở footer) thuộc tầng UI/FE,
|
||
ngoài phạm vi tài liệu này.*
|
||
|
||
---
|
||
|
||
## 9. Phụ thuộc & chuỗi cung ứng
|
||
|
||
| | Quyết định |
|
||
|---|---|
|
||
| Quét lỗ hổng thư viện (SCA) | Trivy/Snyk/Dependabot trong CI/CD — đề xuất chặn build nếu phát hiện CVE mức **Critical** chưa có bản vá sau **7 ngày**, mức **High** sau **30 ngày** (đề xuất SA, chưa Tech Lead xác nhận) |
|
||
| Quét ảnh container | Trivy image scan trước khi push lên ECR — cùng ngưỡng chặn như trên |
|
||
| Chính sách vá lỗ hổng nghiêm trọng | Critical: ≤7 ngày · High: ≤30 ngày · Medium/Low: theo chu kỳ release thường |
|
||
| Ai duyệt thư viện mới | Tech Lead (theo `decision-radar.md §5` — "Công cụ, thư viện" thuộc Tech Lead, SA chỉ phủ quyết nếu chạm `QAS`) |
|
||
| Pentest năm + ASV quý | Xem §8.1 — chi phí chưa có báo giá (`OQ-017`, đã mở ở `TCO`) |
|
||
|
||
---
|
||
|
||
## 10. Giả định & Ngoài phạm vi
|
||
|
||
**Giả định** *(tiếp số toàn dự án — `ASM-01…38` đã dùng, bắt đầu `ASM-39`)*:
|
||
|
||
| ID | Giả định | Cách xác minh | Nếu sai |
|
||
|---|---|---|---|
|
||
| `ASM-39` | VNPay/Momo hỗ trợ tích hợp dạng redirect thuần (không bắt buộc iframe/SDK truyền dữ liệu thẻ qua domain sàn), đủ điều kiện giữ SAQ A | Tech Lead xác nhận khi có tài liệu/sandbox thật (`OQ-048`, `ARISK-03`) | Nếu sai: phạm vi tuân thủ PCI-DSS phải nâng lên (SAQ A-EP hoặc cao hơn), ảnh hưởng trực tiếp `ASR-002`/`ADR-002`/chi phí `TCO` — cần rà lại toàn bộ `SEC §8.1` |
|
||
| `ASM-40` | Chưa có đủ traffic thật để hiệu chỉnh ngưỡng rate-limit (§5.3) — ba con số (30/10/10) là ước lượng dựa trên hành vi UI thông thường, không phải đo | Đo traffic thật 4-6 tuần đầu soft-launch, điều chỉnh lại | Nếu traffic thật khác biệt lớn (VD nhiều khách dùng chung IP NAT hơn dự kiến): cần tách ngưỡng theo `session_id` thuần, giảm phụ thuộc IP |
|
||
| `ASM-41` | Đề xuất PA-3 (service JWT) cho service-to-service authn (§2.4) không làm tăng đáng kể latency đường găng checkout (`QAS-002`) | Đo lại `QAS-002` sau khi có thiết kế cụ thể + `POC` nếu Tech Lead chấp nhận hướng này | Nếu tăng latency đáng kể: cần xét lại PA-2 (mTLS, chấp nhận thêm hạ tầng) hoặc thiết kế cache token phía service gọi |
|
||
|
||
**Ngoài phạm vi:**
|
||
|
||
- Threat model chi tiết cho các `CMP` ngoài "chi tiết nhất" (Seller Mgmt ngoài whitelist PII,
|
||
Commission & Payout, Promotion & Loyalty ngoài `IF-021`, Review, Notification) — chỉ có ở mức
|
||
ranh giới tin cậy (§1), chưa đào sâu STRIDE riêng. Sẽ bổ sung khi module tương ứng tới lượt
|
||
thiết kế chi tiết.
|
||
- Cơ chế chữ ký/HMAC cụ thể của VNPay/Momo/GHN/GHTK — **không bịa**, chờ tài liệu/sandbox đối tác
|
||
thật (`ARISK-03/04`, `OQ-049`).
|
||
- Hạ tầng cụ thể cho VPN/IP allowlist Admin, mã hoá in-transit ElastiCache, cấu hình IAM DB role
|
||
chi tiết theo schema — thuộc hoạt động `inf` (hoạt động 7, chưa chạy).
|
||
- Endpoint đọc `audit_log` tập trung, DPIA (Data Protection Impact Assessment) — ngoài phạm vi
|
||
US-002/003, ghi nhận là việc cần làm trước go-live (tham khảo `docs/08 §8.4`).
|
||
- Viết `ADR` chính thức cho service-to-service authn (§2.4) — chỉ đề xuất và ước lượng radar ở
|
||
đây, việc viết `ADR` thuộc hoạt động `adr` kế tiếp (ngoài phạm vi hoạt động `sec` được giao).
|
||
|
||
---
|
||
|
||
## 11. Open Questions
|
||
|
||
*Tiếp số sổ SA (`00-index/OQ_e-commerce.md` đang ở `OQ-047`) — bắt đầu `OQ-048`.*
|
||
|
||
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | Hệ quả nếu trả lời ngược |
|
||
|---|---|---|---|---|---|
|
||
| `OQ-048` | VNPay/Momo có hỗ trợ tích hợp dạng redirect thuần (không iframe/SDK nhập thẻ trên domain sàn) không — điều kiện để giữ phạm vi PCI-DSS SAQ A (`ASM-39`)? | Tech Lead + Security (khi có người) | 2026-09-15 | `SEC §8.1`; giả định nền của `ASR-002`/`ADR-002` | Nếu không hỗ trợ redirect thuần: phạm vi tuân thủ PCI-DSS phải nâng cấp, tăng chi phí audit/kiểm toán và có thể cần thiết kế lại luồng khởi tạo thanh toán |
|
||
| `OQ-049` | Cơ chế xác thực chữ ký/HMAC webhook cụ thể của VNPay, Momo, GHN, GHTK là gì (thuật toán, header, cách tính chữ ký)? | Tech Lead (khi có tài liệu đối tác) | 2026-09-15 | `THR-17`/`THR-22`; kiểm chứng `ADR-004` thật | Không có tài liệu: threat model webhook chỉ dừng ở mức nguyên tắc chung ("phải xác thực"), không kiểm chứng được cho tới khi có sandbox — rủi ro triển khai sai cơ chế lúc code |
|
||
| `OQ-050` | Chấp nhận đề xuất PA-3 (service JWT ngắn hạn ký bởi Identity & Access) cho service-to-service authn giữa Nhóm Giao dịch ↔ Nhóm Hỗ trợ ↔ Payment không, hay chọn PA-2 (mTLS/App Mesh, cần thêm hạ tầng)? | Tech Lead + Security + Ops/SRE | 2026-09-15 | `ADR` mới ở hoạt động `adr` kế tiếp; thiết kế `inf` cho TB3/TB4 | Chọn PA-3: rủi ro còn lại là chưa đạt mTLS full zero-trust, nhưng không cần hạ tầng mới ngay. Chọn PA-2: cần quyết định lại ràng buộc "không thêm hạ tầng mới" đã ghi ở `SAD §7` v1.2, tăng thời gian/chi phí triển khai |
|
||
| `OQ-051` | Xác nhận số cụ thể: TTL access token (đề xuất 15 phút), TTL refresh token (đề xuất 14 ngày), cơ chế thu hồi tức thời (đề xuất denylist Redis theo `jti`), tần suất xoay khoá ký JWT (đề xuất 90 ngày) | Tech Lead | 2026-09-15 | Thiết kế `CMP-02` (Identity & Access) khi tới lượt module đó; toàn bộ luồng authn Customer/Seller/Admin | Số quá ngắn (VD TTL 5 phút): tăng tần suất refresh, tăng tải Identity & Access. Số quá dài (VD TTL 60 phút không denylist): cửa sổ lợi dụng token bị đánh cắp dài hơn |
|
||
| `OQ-052` | Xác nhận ngưỡng account lockout theo vai trò (đề xuất: customer/seller 5 lần sai/15 phút; admin 3 lần sai/30 phút) và rate-limit login theo IP (đề xuất 10 request/phút) | Tech Lead + Security | 2026-09-15 | `THR-28/31`; thiết kế `CMP-02` | Ngưỡng quá chặt: tăng khiếu nại khách bị khoá oan (đặc biệt IP NAT dùng chung). Ngưỡng quá lỏng: tăng rủi ro brute-force thành công |
|
||
| `OQ-053` | Ba trường whitelist chia sẻ cho seller (`recipient_name`/`phone`/`address_line`, `ADR-008` PA-2) hiển thị đầy đủ hay che một phần (VD số điện thoại che 3-4 số giữa)? | Security/Legal (khi có người) + PO | 2026-09-15 | `DAT §5.2`; UI hiển thị đơn hàng cho Seller (ngoài phạm vi US-002/003) | Hiển thị đầy đủ: seller đủ thông tin giao hàng nhưng tăng bề mặt rủi ro nếu tài khoản seller bị lộ. Che một phần: giảm rủi ro nhưng có thể gây khó khăn thao tác giao hàng thực tế (VD shipper cần gọi điện xác nhận) |
|
||
|
||
**Cập nhật cho `OQ` đã mở:**
|
||
|
||
- **`OQ-007`** — SEC bổ sung: toàn bộ §5, §8.2 của tài liệu này là **đề xuất chờ phủ quyết**;
|
||
không coi bất kỳ phân loại/whitelist/mã hoá nào ở đây là đã "Security xác nhận". **Giữ nguyên
|
||
mở.**
|
||
- **`OQ-023`** — SEC trả lời bằng đề xuất số cụ thể ở §5.3 (30 req/phút Guest cart, kèm hệ quả cả
|
||
hai chiều) — **không tự quyết thay Security**, `OQ-023` **giữ nguyên mở**, chờ Security xác
|
||
nhận hoặc điều chỉnh.
|
||
- **`OQ-024`** (MFA Admin) — SEC xác nhận lại hướng TẠM TOTP app (`ASM-20`, `DEC-14`) và bổ sung
|
||
chi tiết backup code (§2 bảng, chưa thiết kế đầy đủ) — **giữ nguyên mở**, chờ Security thật.
|
||
|
||
**Nhắc:** cộng với các `OQ` còn mở ảnh hưởng trực tiếp `SEC` — `OQ-007` (PII/residency, chặn phần
|
||
lớn §5/§8.2), `OQ-017` (báo giá pentest/ASV, chặn §8.1/§9), `ARISK-03/04` (sandbox đối tác, chặn
|
||
kiểm chứng `THR-17/18/22`) — xem sổ đầy đủ `00-index/OQ_e-commerce.md`.
|
||
|
||
**Nhắc AG2:** cần **Tech Lead + Security + Ops/SRE ký** — còn thiếu `INF` (hoạt động 7) và toàn bộ
|
||
`ADR` liên quan `SEC` (`ADR-002/004/007/008` vẫn `Proposed`; `ADR` service-to-service authn §2.4
|
||
chưa viết).
|
||
|
||
---
|
||
|
||
## Tự chấm
|
||
|
||
### ① Bảng tự chấm Gate AG2 *(`workflow.md §2` — chỉ dòng liên quan tới `SEC`, tự chấm sớm)*
|
||
|
||
| # | Tiêu chí | ☐/✅ | Ghi chú |
|
||
|---|---|---|---|
|
||
| — | `ASR`/`QAS`/`SAD`/`ICD`/`DAT`/`FAIL` | ✅ *(đã đạt ở các hoạt động trước)* | Không lặp lại |
|
||
| — | `ADR-nnn` tồn tại cho mọi quyết định đạt ngưỡng radar | 🟡 Một phần | 13 `ADR` đã viết (bao gồm `ADR-002/004/007/008/011` liên quan bảo mật); `SEC` phát hiện **1 quyết định mới đạt ngưỡng ADR** chưa viết — service-to-service authn (§2.4, radar ~5), ghi `OQ-050` |
|
||
| — | `INF` | ☐ | Chưa tới — hoạt động 7 |
|
||
| 1 | `SEC` — có threat model STRIDE cho luồng nhạy cảm; mô hình authn/authz đã chốt; **Security ký** | ☐ | Threat model STRIDE đủ 8 ranh giới, 31 `THR` (§4); mô hình authn/authz đã **đề xuất đầy đủ** (§2, §3) nhưng **chưa chốt** ở nhiều điểm (`OQ-050/051/052/053`) và **Security chưa ký** (`OQ-007`, không có người) — đây là điều kiện chặn cứng nhất của AG2 theo `SKILL.md` ("Security có quyền phủ quyết AG2") |
|
||
| — | `sa-conformance` báo coverage `ASR → ADR/CMP` ≥ 100% | *(không đổi bởi `SEC`)* | `SEC` không tạo `CMP`/`ASR` mới; có đề xuất 1 `ADR` mới (service-authn) chưa viết |
|
||
|
||
**Kết luận tự chấm (riêng phần `SEC`):** Hoạt động `sec` hoàn tất đúng phạm vi được giao — threat
|
||
model STRIDE đủ 8 ranh giới tin cậy yêu cầu (31 `THR`), mô hình authn/authz đầy đủ cho Guest/
|
||
Customer/Seller/Admin + phát hiện khoảng trống service-to-service authn (mới, `OQ-050`), map đủ
|
||
2/2 `ROLE-nn` của `RBAC_CartCheckout`, PCI-DSS/NĐ13/2023 rà theo yêu cầu (mọi kết luận PII đánh
|
||
dấu "đề xuất chờ Legal"), audit log + secret management + chuỗi cung ứng đã chốt trường/chính
|
||
sách đề xuất. **AG2 còn xa** vì (a) `INF` (hoạt động 7) chưa chạy, (b) Security **chưa có người**
|
||
(`OQ-007`) nên **không ai có quyền phủ quyết/ký** — đây là điều kiện chặn nghiêm trọng nhất, đúng
|
||
cảnh báo của `GUIDE.md`: "phát hiện muộn nhất và đau nhất luôn đến từ đây."
|
||
|
||
### ② Checklist D1–D12 *(`design-rules.md`)*
|
||
|
||
| # | Mục | ☐/✅ | Ghi chú |
|
||
|---|---|---|---|
|
||
| D1 | Một ADR một quyết định | N/A | `SEC` không viết `ADR` mới ở lượt này — chỉ đề xuất 1 `ADR` ứng viên (service-authn, §2.4) cho hoạt động `adr` kế tiếp |
|
||
| D2 | Không NFR định tính | ✅ | Mọi ngưỡng (rate-limit, TTL token, lockout) đều có con số hoặc đánh dấu rõ "chưa chốt" kèm `OQ` — không có mục nào ghi "bảo mật tốt" chung chung |
|
||
| D3 | Nêu phương án bị loại + lý do | ✅ | §2.4 (3 phương án service-authn, PA-1/PA-2 bị loại có lý do gắn ràng buộc `SAD §7`) |
|
||
| D4 | Sơ đồ khai báo mức + legend | ✅ | §1 khai báo rõ "ranh giới tin cậy" (`flowchart LR` theo `D4`), có legend |
|
||
| D5 | Interface có chủ/contract | N/A | Đã xử lý ở `ICD` (hoạt động 4); `SEC` chỉ bổ sung khía cạnh xác thực/authz cho các `IF` đã có |
|
||
| D6 | Phụ thuộc ngoài process có timeout/retry | N/A | Đã xử lý ở `FAIL` (hoạt động 8); `SEC` chỉ bổ sung khía cạnh threat/xác thực |
|
||
| D7 | Một chủ sở hữu dữ liệu | N/A | Đã xử lý ở `DAT` (hoạt động 5); `SEC` chỉ tham chiếu khi thiết kế IAM theo schema (§4.7) |
|
||
| D8 | Ràng buộc có FIT hoặc nhãn khuyến nghị | 🟡 Một phần | Đề xuất `FIT-29` (secret scan), `FIT-30` (service-authn test, chờ `OQ-050`), `FIT-31` (webhook signature test, chặn bởi `ARISK-03/04`), `FIT-32` (audit completeness), `FIT-33` (TLS/HSTS config test) — ứng viên GĐ3, chưa viết thật; các threat chưa có biện pháp đủ (`THR-09/13/17/22`) đánh dấu rõ "chưa kiểm chứng được", không giả vờ đã có `FIT` |
|
||
| D9 | Con số hạ tầng quy ra tiền + nguồn | N/A | `SEC` không thêm con số hạ tầng mới (Secrets Manager/WAF đã có trong `TCO`/`SAD` từ trước) |
|
||
| D10 | Không quyết định thay người có thẩm quyền | ✅ | Mọi kết luận PII/residency đánh dấu "đề xuất chờ Legal/Security" (§5, §8.2); rate-limit (§5.3), account lockout (§2.3), service-authn (§2.4) đều trình phương án kèm hệ quả hai chiều, không tự quyết; §4.9 để trống vì không tự chấp nhận rủi ro thay Security |
|
||
| D11 | Có mục "Ngoài phạm vi" + `ASM-nn` | ✅ | §10 đầy đủ — `ASM-39…41` mới, có cách xác minh/hệ quả |
|
||
| D12 | Câu quy định thẩm quyền sơ đồ vs văn bản | ✅ | Có ngay sau Change Log |
|
||
|
||
### ③ Bảng đối chiếu với bộ BA — `RBAC` ↔ `SEC`
|
||
|
||
| `RBAC_CartCheckout` (BA) | Nội dung | `SEC` tương ứng | Khớp? | Hành động |
|
||
|---|---|---|---|---|
|
||
| §1 (2 vai trò: Guest, Customer) | Ma trận vai trò | §3.1 (map đủ `ROLE-01/02`) | ✅ | Không lệch — 2/2 `ROLE-nn` có dòng map, đúng yêu cầu "mỗi `ROLE-nn` phải có đúng một dòng, thiếu ⇒ chặn AG2" |
|
||
| §2 (không ai xem giỏ/đơn người khác) | Ranh giới ownership | §3 (fail-closed), `THR-07` | ✅ | Khớp — `ASR-007`/`ADR-007` đã hiện thực hoá đúng |
|
||
| §3 (SoD không áp dụng) | Tự phục vụ, không có duyệt kép | §3.2 | ✅ | Kế thừa nguyên trạng kết luận của BA, không lệch |
|
||
| §4 (mức che PII cho seller — chưa chốt) | Whitelist chưa quyết định mức che | §5.2, `OQ-053` (mới) | 🟡 Một phần | `SEC` xác nhận whitelist 3 trường (`ADR-008`) nhưng **mức che cụ thể vẫn chưa chốt** như BA đã ghi nhận — **BA không cần sửa `RBAC`**, câu hỏi này tiếp tục do Security/Legal quyết định khi có người |
|
||
| §5 (lưu vết — "chưa chốt thời hạn") | Audit log cho `Order`/`Payment` | §7 (10 năm, append-only) | 🟡 Một phần | `SEC` đề xuất retention cụ thể (10 năm) — **BA có thể cập nhật `RBAC_CartCheckout §5`** tham chiếu `SEC §7` khi retention được Security/Tech Lead xác nhận thật |
|
||
| §6 (hành vi khi không đủ quyền) | 403/không hiển thị dữ liệu | §3 (fail-closed 503 cho lỗi kỹ thuật, phân biệt với 403 thật) | ✅ Bổ sung | `SEC` làm rõ thêm trường hợp BA chưa phân biệt (lỗi kỹ thuật khi kiểm tra ownership ≠ "không có quyền" thật) — **BA nên bổ sung `AC` mới cho `E-CART-0007`** (đã ghi ở `FAIL`, nhắc lại ở đây) |
|
||
| §8 `OQ-012` (Guest OTP đơn giá trị cao) | Chưa chốt | *(ngoài phạm vi `SEC` — thuộc `BR-CART-03`, quyết định PO)* | ➖ N/A | Không hành động — đây là quyết định nghiệp vụ, không phải kiến trúc bảo mật |
|
||
| §8 `OQ-015` (chống lạm dụng Guest checkout) | Chưa chốt | §5.3 (đề xuất rate-limit checkout 10/phút) | ✅ Trả lời | `SEC` đã đề xuất số cụ thể — **BA có thể đóng `OQ-015` trong sổ BA**, tham chiếu `SEC §5.3`, với điều kiện Security xác nhận số cuối cùng |
|
||
| §8 `OQ-016` (mức che PII cho seller) | Chưa chốt | Trùng với `RBAC §4` ở trên | 🟡 Một phần | Cùng trạng thái — chờ Security/Legal, xem `OQ-053` (SA) |
|
||
|
||
### ④ Danh sách `OQ` mở kèm người phải trả lời, chặn gì
|
||
|
||
Xem §11 (`OQ-048…053` mới) cộng cập nhật `OQ-007/023/024`. Ba câu hỏi quan trọng nhất cho AG2:
|
||
**`OQ-007`** (chưa có người Security/Legal — chặn toàn bộ hiệu lực phủ quyết của `SEC`),
|
||
**`OQ-050`** (service-to-service authn — khoảng trống kiến trúc mới phát hiện, ảnh hưởng TB3/TB4
|
||
nơi PII và tiền đi qua), **`OQ-048`/`OQ-049`** (chưa có tài liệu/sandbox đối tác thanh toán/vận
|
||
chuyển thật — chặn kiểm chứng phần lớn threat model TB5/TB6). Sổ đầy đủ: `00-index/OQ_e-commerce.md`.
|
||
|
||
**Nhắc:** AG2 cần **Tech Lead + Security + Ops/SRE ký** — còn thiếu `INF` (hoạt động 7) và **chưa
|
||
có người Security** để ký bất kỳ phần nào của `SEC`. Đây là rủi ro tiến độ nghiêm trọng nhất của
|
||
toàn GĐ2: theo `GUIDE.md`, "Bước `sec` cần một người thật từ Security ngồi cùng" — điều này **chưa
|
||
xảy ra** trong suốt hoạt động `sec` vừa chạy, toàn bộ nội dung là công việc chuẩn bị một chiều của
|
||
SA, chờ người đó xuất hiện.
|