save
This commit is contained in:
705
sa-output/e-commerce/02-architecture/SAD_e-commerce_v1.0.md
Normal file
705
sa-output/e-commerce/02-architecture/SAD_e-commerce_v1.0.md
Normal file
@@ -0,0 +1,705 @@
|
||||
# SAD — Solution Architecture Document — e-commerce
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Version** | 1.3 |
|
||||
| **Date** | 2026-09-15 |
|
||||
| **Author** | SA (skill sa-2-architecture, chế độ `go`, hoạt động `sad`) |
|
||||
| **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: chấp nhận C4 Context/Container/Component (Cart & Order), deployment view, bảng `CMP-01…15`, ma trận `ASR→CMP` đủ 15/15, 17 `IF-nn` ứng viên cho `ICD` *(sửa từ số đếm sai "22" ở v1.2 — xem `OQ-029`, `ICD §0.1`, Change Log v1.2)*, 12 chỗ chờ `ADR-001…012` (không `ADR` nào được viết ở lượt này). Chốt **TẠM** `OQ-026` (P2 có 2 ECS Fargate service riêng — Nhóm Giao dịch/Nhóm Hỗ trợ — để scale độc lập, `TCO §3.2` giữ nguyên tới khi hoạt động `inf` xác nhận, theo `ASM-23`) và `OQ-027` (Identity & Access thuộc Nhóm Giao dịch, theo `ASM-22`) làm hướng đi tạm cho hoạt động `icd`/`dat`/`sec`/`inf`/`fail` kế tiếp — **`OQ-026`/`OQ-027` giữ nguyên MỞ**, chờ Tech Lead/Ops thật xác nhận, không coi là đã đóng. Ký thay Tech Lead theo ngoại lệ `DEC-01` (SA) — **không phải chữ ký Tech Lead thật**. · Security: — *(chưa ký)* · Ops/SRE: — *(chưa ký)* — AG2 cần cả ba cùng ký; tài liệu này **vẫn chưa qua AG2**, còn xa vì `ICD`/`DAT`/`SEC`/`INF`/`FAIL` (hoạt động 4–8) và mọi `ADR` (hoạt động 9) chưa chạy. `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, không nâng `Confidence`. Status **giữ** 🟡 Draft — AG2 chưa đủ ba chữ ký thật/hợp lệ. Ghi thêm `DEC-16`. **Lưu ý v1.2 (2026-09-15):** §4/§6/§7 vừa được sửa lỗi nhất quán (phân loại
|
||||
`IF-021` cross-network, đếm lại `IF-nn` 22→17) theo yêu cầu người duyệt và phát hiện của `ICD`
|
||||
(`OQ-028`/`OQ-029`) — đây là sửa lỗi tài liệu, **không phải** nội dung kiến trúc mới; chữ ký nêu
|
||||
trên chỉ áp dụng cho nội dung **trước khi sửa**, §4/§6/§7 bản v1.2 **chưa được Tech Lead/Security/
|
||||
Ops ký lại**. **Lưu ý v1.3 (2026-09-15):** §6.1 (sequence checkout) và §8 (bảng ADR) vừa được sửa
|
||||
theo `ADR-013` (`Proposed`, bất đồng bộ hoá bước khởi tạo thanh toán — quyết định Lựa chọn B của
|
||||
`OQ-034`/`DEC-22`) — đây **là** nội dung kiến trúc mới (đổi luồng checkout đồng bộ→có nhánh bất
|
||||
đồng bộ), **không phải** sửa lỗi tài liệu như v1.2; chữ ký nêu trên **không** áp dụng cho §6.1/§8
|
||||
bản v1.3 — cần Tech Lead + PO **thật** xác nhận `ADR-013` trước khi coi §6.1/§8 là đã duyệt. |
|
||||
| **Source** | `02-architecture/ASR_e-commerce_v1.0.md` v1.0 (toàn bộ `ASR-001…015`, §B2, §D) · `02-architecture/QAS_e-commerce_v1.0.md` v1.0 (§A3, §A4 xung đột) · `01-context/OPT_e-commerce_v1.0.md` §1, §3 (P2), §9 · `01-context/CTX_e-commerce_v1.0.md` §2 (`DRV`), §3 (`CON`), §4.2 (đối tác ngoài) · `01-context/TCO_e-commerce_v1.0.md` §3.2 (P2, kịch bản A/B) · `01-context/ARISK_e-commerce_v1.0.md` §3, §6 (`POC-01/02`) · `02-architecture/FAIL_e-commerce_v1.0.md` v1.1 §1.2 (ngân sách timeout, phát hiện vượt `QAS-002`) · `02-architecture/adr/ADR-013_bat-dong-bo-hoa-khoi-tao-thanh-toan.md` (mới, `Proposed`) · `00-index/OQ_e-commerce.md` v1.18 (`OQ-034`, `DEC-22`) · `00-index/DEC_e-commerce.md` v1.20 (`DEC-22`, `DEC-23`) · `ba-output/e-commerce/02-analysis/PROCESS_CartCheckout_v1.0.md` (luồng B1–B9) · `ba-output/e-commerce/02-analysis/IMPACT_CartCheckout_v1.0.md` §1.5 (tích hợp) · `ba-output/e-commerce/03-specification/API_US002-003_v1.0.md` (contract đề xuất Cart) · `e-commerce/docs/sections/03-kien-truc.md` §3.1 (**chỉ tái dùng danh sách module/domain và tích hợp ngoài — KHÔNG kế thừa kiểu kiến trúc ~10 microservices, đó là P1 đã bị loại ở `OPT §5`**) · `e-commerce/docs/sections/04-api-design.md` §4.1 (danh sách endpoint tham khảo) |
|
||||
| **Scope** | Toàn sàn e-commerce theo phương án **P2** (modular monolith + managed AWS, tách riêng Payment Service — `DEC-06`/`ASR-001`, **chưa** có `ADR-001` chính thức, xem §8). Chi tiết nhất: module **Giỏ hàng & Checkout** (US-002/003, `BR-CART-01…09`, `RBAC` `ROLE-01/02`). Đây là hoạt động 3/9 của `sa-2-architecture` — **không** viết `ADR`/`ICD`/`DAT`/`SEC`/`INF`/`FAIL` ở lượt này; đánh dấu rõ chỗ chờ từng hoạt động đó. |
|
||||
| **Confidence** | 🔴 Giả định chưa xác minh — theo yêu cầu điều phối, tiếp nối `Confidence` 🔴 của `QAS`/`ASR`. AG1 chưa có chữ ký PO/Tech Lead thật (`OQ-004` mở); `POC-01`/`POC-02` chưa chạy; `ADR-001` (kiểu kiến trúc tổng thể) chưa tồn tại — tài liệu này **giả định trước** kết luận của `ADR-001` (P2) để có thể vẽ C4, đúng theo hướng đã duyệt từng phần ở `DEC-06`/`DEC-14`, nhưng bản thân quyết định đó vẫn `Proposed`, chưa `Accepted`. Mọi con số hạ tầng ở §7 kế thừa `TCO §3.2` nguyên trạng — không tự đổi khi phát hiện lệch (xem `OQ-026`). |
|
||||
|
||||
## Change Log
|
||||
|
||||
| Version | Date | Người sửa | Thay đổi | ADR |
|
||||
|---|---|---|---|---|
|
||||
| 1.0 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `sad`) | Bản đầu — hoạt động 3/9 của `sa-2-architecture`. Dựng C4 Context (4 actor + 5 hệ ngoài), C4 Container (Mermaid, legend theo `D4`), C4 Component cho container "Nhóm Giao dịch" (chi tiết Cart & Order — đúng yêu cầu "chi tiết nhất cho Giỏ hàng & Checkout"), 2 sequence diagram (Checkout, Webhook thanh toán + đối soát), deployment view AWS `ap-southeast-1` đối chiếu `TCO §3.2` (phát hiện 1 điểm lệch mức chi tiết — ghi `OQ-026`, không tự đổi số `TCO`). Bảng `CMP-01…15` (15 component, ma trận `ASR-001…015` × `CMP` đủ 15/15, không CMP mồ côi), danh sách 17 `IF-nn` ứng viên cho `ICD` (hoạt động 4) *(số gốc "22" là đếm nhầm — sửa ở v1.2, xem `OQ-029`)*, bảng thực thể dữ liệu sở hữu ứng viên cho `DAT` (hoạt động 5), bảng phụ thuộc vượt ranh giới process ứng viên cho `FAIL` (hoạt động 8). Đánh dấu 12 chỗ chờ `ADR-001…012` (không viết `ADR` nào — đúng yêu cầu điều phối). Không sửa `QAS`/`ASR` đã duyệt từng phần. Thêm `OQ-026/027`, `ASM-22/23`. Ghi `DEC-15` (tiếp nối `DEC-01…14`, ngoại lệ gate tiếp tục GĐ2 hoạt động `sad`). `Confidence` 🔴 toàn bộ. | — *(chưa viết ADR)* |
|
||||
| 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**: chấp nhận C4 Context/Container/Component, deployment view, bảng `CMP-01…15`, ma trận `ASR→CMP` đủ 15/15, 17 `IF-nn` ứng viên *(sửa từ "22" ở v1.2 — xem `OQ-029`)*, 12 chỗ chờ `ADR`. Chốt **TẠM** `OQ-026` (2 ECS Fargate service riêng theo Nhóm Giao dịch/Nhóm Hỗ trợ, `TCO §3.2` giữ nguyên tới khi `inf` xác nhận, `ASM-23`) và `OQ-027` (Identity & Access thuộc Nhóm Giao dịch, `ASM-22`) làm hướng đi tạm — cả hai **giữ nguyên mở**, chờ Tech Lead/Ops thật xác nhận. Không đổi nội dung chuyên môn. Security/Ops chưa ký; `OQ-004` mở; `Confidence` giữ 🔴; Status giữ 🟡 Draft; AG2 **chưa** ký. Ghi thêm `DEC-16`. | `DEC-16` |
|
||||
| 1.1 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `adr`) | **Chỉ cập nhật §8** (bảng "Quyết định kiến trúc đã ghi") — thay cột "*Chưa viết*" bằng đường dẫn file thật của 12 `ADR-001…012` vừa được viết (tất cả `Status: Proposed`, radar/điều kiện POC giữ nguyên không đổi so với bảng ứng viên đã duyệt từng phần ở `DEC-14`/`DEC-16`). Không sửa bất kỳ nội dung chuyên môn nào khác của `SAD` (C4, `CMP`, deployment view, `OQ`, `ASM` giữ nguyên như v1.0, đã qua duyệt từng phần `DEC-16`). Ghi thêm `DEC-17`. `Confidence` giữ 🔴 — việc link file không phải bằng chứng nguồn mới. | `DEC-17` |
|
||||
| 1.2 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `sad`) | **Sửa nhất quán theo phát hiện `ICD` (`OQ-028`/`OQ-029`), người duyệt yêu cầu 2026-09-15** — sửa lỗi tài liệu, không tạo nội dung kiến trúc mới, không đổi `CMP`. (1) `IF-021` (Cart&Order → Promotion&Loyalty): sửa mọi mô tả từ "internal call cùng process" thành **cross-network REST giữa 2 ECS Fargate service riêng** (Nhóm Giao dịch ↔ Nhóm Hỗ trợ, theo `OQ-026`/`ASM-23` và `OQ-028`/`ASM-24` đã chốt TẠM ở `ICD`) — sửa ở legend §4, thêm footnote §4.1, bảng bước §6.1, bảng phụ thuộc §6.3, bổ sung cạnh mạng còn thiếu `ECSGD`↔`ECSHT` ở §7 (đánh dấu 🔴 chờ `inf` thiết kế đường kết nối thật). Rà theo cùng nguyên tắc cho mọi `IF` khác: `IF-022` (Cart&Order ↔ Seller Management, cũng GD↔HT) trước đây không có nhãn loại — nay ghi rõ **cũng cross-network** (không phải "đổi loại", chỉ làm rõ vì trước đó chưa từng gán nhãn "internal"); `IF-005` (trong Nhóm Giao dịch) giữ **in-process** (không đổi, đúng từ trước); `IF-006` (Cart&Order→Payment) giữ **cross-network** (không đổi, đúng từ trước). Không `IF` nào khác đổi loại. (2) Đếm lại `IF-nn`: đối chiếu toàn bộ sơ đồ Context/Container/Component (§3/§4/§5) với bảng `CMP-nn` (§4.1) và bảng phụ thuộc (§6.3) — chỉ **17 ID** thực sự xuất hiện (`IF-001…009, 015…022`), không có `IF-010…014` ở bất kỳ đâu, không có mũi tên nào thiếu ID → **kết luận: con số "22" là đếm nhầm ở bản gốc, không phải bỏ sót interface**. Sửa "22"→"17" ở header (`Approved by`), Change Log v1.0/v1.0-sign, `§Tự chấm` (D5, đoạn Nhắc cuối) — nội dung chuyên môn (17 `IF-nn`, `CMP`, ma trận `ASR×CMP`) không đổi, chỉ sửa số đếm sai. Đóng `OQ-029` trong sổ `00-index/OQ_e-commerce.md` với kết luận trên. `OQ-028` **giữ nguyên mở** (SAD nay đã hết mâu thuẫn nội bộ, vẫn chờ Tech Lead thật xác nhận ranh giới mạng). Không sửa §8 (`ADR` links), không sửa `ASR`/`QAS`/`ADR`/`ICD`. Ghi ngoại lệ tiếp tục gate ở `DEC-20` (`00-index/DEC_e-commerce.md`), tiếp nối `DEC-01…19`. `Confidence` giữ 🔴; Status giữ 🟡 Draft; §4/§6/§7 v1.2 **chưa được Tech Lead/Security/Ops ký lại**. | — |
|
||||
| 1.3 | 2026-09-15 | SA (qua skill sa-2-architecture, chế độ `go`, hoạt động `adr`) | **Sửa nhất quán tối thiểu theo `ADR-013` (`Proposed`), yêu cầu người duyệt 2026-09-15** — hiện thực hoá Lựa chọn B đã chọn ở `OQ-034`/`DEC-22` (bất đồng bộ hoá bước khởi tạo thanh toán VNPay/Momo trong `POST /v1/checkout`). **Đây là nội dung kiến trúc mới, không phải sửa lỗi tài liệu như v1.2.** (1) §6.1: sequence diagram checkout chèn nhánh rẽ theo phương thức thanh toán — COD giữ nguyên luồng đồng bộ cũ; VNPay/Momo dừng đường găng đồng bộ ngay sau khi commit TX Order (bước ghi `Order`/`OrderSeller`/`OrderItem`), trả response `201` với `orderId` + `status: PENDING_PAYMENT_INIT` (chưa có `redirectUrl`), việc gọi VNPay/Momo chuyển thành bất đồng bộ qua message `PaymentInitRequested` (tái dùng message backbone `ADR-005`) — Payment Service consume, gọi gateway, publish `PaymentInitReady`/`PaymentInitFailed`; thêm chú thích tham chiếu `ADR-013` ngay dưới sơ đồ và cập nhật bảng bước kèm theo. (2) §8: thêm dòng `ADR-013` vào bảng "Quyết định kiến trúc đã ghi" (Status `Proposed`, radar 7, không bắt buộc POC vì dưới ngưỡng 8, chờ Tech Lead + PO thật xác nhận). Không sửa nội dung khác của `SAD` (C4 §3–§5, `CMP` §4.1, deployment view §7, §9, §10, §11 giữ nguyên như v1.2) — đúng phạm vi được giao. `OQ-034` cập nhật trạng thái "đã có `ADR-013`, chờ Tech Lead/PO thật xác nhận" trong sổ `00-index/OQ_e-commerce.md`. Thêm `OQ-041`, `OQ-042` (mới, từ `ADR-013`). Ghi ngoại lệ tiếp tục gate ở `DEC-23` (`00-index/DEC_e-commerce.md`), tiếp nối `DEC-01…22`. `Confidence` giữ 🔴 — chưa có bằng chứng nguồn mới (chưa đo thật, chưa Tech Lead/PO thật ký); Status giữ 🟡 Draft; §6.1/§8 bản v1.3 **chưa được Tech Lead/Security/Ops ký**. | `ADR-013` |
|
||||
|
||||
> Sơ đồ thắng về **quan hệ và luồng** (ai gọi ai, theo thứ tự nào).
|
||||
> Bảng/văn bản thắng về **ràng buộc và con số** (timeout, quyền, định dạng, giới hạn).
|
||||
> 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 phải chọn bên (`D12`).
|
||||
|
||||
---
|
||||
|
||||
## 0. Ghi chú Preflight & ngoại lệ gate — bắt buộc đọc trước
|
||||
|
||||
**AG1 vẫn chưa được ký chính thức** và **AG2 (gate của chính GĐ2) càng chưa tới hạn** — tài liệu
|
||||
này là hoạt động 3/9 của `sa-2-architecture`. Theo đúng thứ tự bắt buộc của `SKILL.md` ("1→2→3
|
||||
bắt buộc trước; 4–8 chạy song song được"): hoạt động 1 (`QAS`) và hoạt động 2 (`ASR`) đã hoàn tất
|
||||
và được duyệt từng phần (`DEC-12`, `DEC-14`) — điều kiện đầu vào cho `sad` đã đủ.
|
||||
|
||||
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**
|
||||
sang hoạt động 3 (`SAD`). Quyết định ngoại lệ này được ghi tại `DEC-15` dưới đây và tại sổ
|
||||
`00-index/DEC_e-commerce.md`.
|
||||
|
||||
> **DEC-15 (SA)** — Tiếp tục `sa-2-architecture` (hoạt động 3 — `SAD`) cho e-commerce trong khi
|
||||
> AG1 chưa có chữ ký PO/Tech Lead thật và AG2 (gate của chính GĐ2) chưa tới hạn — tiếp nối
|
||||
> `DEC-01…14`.
|
||||
> **Quyết định:** Dựng `SAD` (C4 Context/Container/Component, deployment view, bảng `CMP-nn`,
|
||||
> ma trận `ASR×CMP`) dựa trên hướng kiến trúc P2 đã duyệt từng phần (`DEC-06`/`DEC-14`), giữ
|
||||
> `Confidence 🔴` cho tới khi: (a) AG1 ký thật, (b) `ADR-001` (kiểu kiến trúc tổng thể) được viết
|
||||
> và `Accepted`, (c) `POC-01`/`POC-02` chạy xong, (d) `OQ-010` (số đội thật, ảnh hưởng ranh giới
|
||||
> nhóm triển khai `ASR-014`) được trả lời.
|
||||
> **Người quyết:** Điều phối dự án (đại diện PO, dự án chạy thử).
|
||||
> **Radar (ước lượng):** ~4 — chi phí đảo ngược thấp (bản vẽ C4 sửa lại khi `ADR-001` đổi hướng
|
||||
> không tốn nhiều so với đã code) · bán kính ảnh hưởng: hoạt động `icd`/`dat`/`sec`/`inf`/`fail`
|
||||
> kế tiếp phụ thuộc `SAD` này, nhưng bản thân *việc ghi tài liệu dưới ngoại lệ* thì nhỏ · có chạm
|
||||
> `QAS`/`ASR` Must trực tiếp (đang hiện thực hoá chúng thành component) nhưng chưa phải cam kết
|
||||
> thi công (chưa `ADR` nào `Accepted`) · không ràng buộc dài hạn tự thân (văn bản `SAD` sửa được
|
||||
> qua version mới, khác `ADR` bất biến) · không tranh cãi mới, tiếp nối tiền lệ `DEC-11…14` →
|
||||
> **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ệ:** dừng GĐ2 ở hoạt động `asr`, không có `SAD` để hoạt
|
||||
> động `icd`/`dat`/`sec`/`inf`/`fail` (hoạt động 4–8) dùng làm đầu vào — chậm tiến độ chạy thử
|
||||
> tương ứng thời gian xử lý các `OQ` đang mở, đặc biệt `OQ-010` (ảnh hưởng trực tiếp §4.1/§7).
|
||||
|
||||
**Cập nhật v1.2 (2026-09-15):** Người duyệt yêu cầu sửa lỗi nhất quán phát hiện bởi hoạt động
|
||||
`icd` (`OQ-028`/`OQ-029`) — đây là sửa lỗi tài liệu, **không phải** quyết định kiến trúc mới, không
|
||||
cần `ADR`. Người dùng (vai điều phối dự án chạy thử) đã được cảnh báo lại AG1/AG2 vẫn chưa qua và
|
||||
**khẳng định muốn tiếp tục**. Ghi ngoại lệ tiếp tục tại `DEC-20` (`00-index/DEC_e-commerce.md`),
|
||||
tiếp nối `DEC-01…19`.
|
||||
|
||||
🔴 **Nhắc quan trọng:** `ADR`, `ICD`, `DAT`, `SEC`, `INF`, `FAIL` **chưa được tạo**. Tài liệu này
|
||||
đánh dấu rõ 12 chỗ chờ `ADR-001…012` (§8) và ghi ứng viên `IF-nn` (§4.1, §6.3), thực thể dữ liệu
|
||||
sở hữu (§4.1, cho `DAT`), phụ thuộc cần `FAIL` (§6.3) — để các hoạt động kế tiếp không phải dò
|
||||
lại từ đầu, **không thay thế** các hoạt động đó.
|
||||
|
||||
---
|
||||
|
||||
## 1. Tóm tắt cho người quyết định
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Kiểu kiến trúc** | Modular monolith theo domain, chạy trên AWS managed service (ECS Fargate), **tách riêng duy nhất Payment Service** (mạng/IAM/DB riêng) — phương án **P2** của `OPT`, chưa có `ADR-001` chính thức (vẫn `Proposed`, xem §8) |
|
||||
| **Quyết định lớn nhất** | `ADR-001` — Modular Monolith P2 thay vì ~10 microservices (P1, đã loại ở `OPT §5`); radar ước lượng ~7, cần `POC-01`/`POC-02` trước khi `Accepted` |
|
||||
| **Rủi ro kiến trúc lớn nhất** | `ARISK-01`/`ARISK-02` (SQS/EventBridge và RDS gộp chưa đo throughput thật) — chặn trực tiếp `ADR-005`/`ADR-006` (radar ≥8, xem `ASR-005`/`ASR-006`) |
|
||||
| **Cái này KHÔNG làm được** | Scale-out **độc lập** Catalog/Search khỏi Cart/Checkout ngay từ ngày một (thua P1 đúng 1 bậc ở `OPT §4`); chưa dùng OpenSearch (hoãn, dùng Postgres FTS); chưa tách ranh giới ECS chi tiết theo "Nhóm giao dịch"/"Nhóm hỗ trợ" trong `TCO` (xem `OQ-026`) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Kiểu kiến trúc và lý do
|
||||
|
||||
Quyết định ở `ADR-001` (chưa viết — xem §8). Tóm tắt lý do gắn với `ASR`/`CON`:
|
||||
|
||||
| Tín hiệu trong dự án này | Nghiêng về | Kết luận |
|
||||
|---|---|---|
|
||||
| `CON-05` (số đội thi công chưa xác nhận thật, giả định tạm "team MVP chuẩn" `DEC-02`, hồ sơ thầu BE trung bình ~2,6 FTE/tháng) so với ~10 service độc lập của P1 | Modular monolith — mỗi BE ôm 3–4 service ở P1 vi phạm Conway rõ (`OPT §4` tiêu chí 5: P1=2, P2=5) | Giữ P2 — 2–3 nhóm triển khai thay vì ~10 |
|
||||
| `ASR-001`/`ASR-014` (tải lệch Catalog/Cart&Order so với nhóm hỗ trợ, cần scale nhanh hơn) | Tách logic thành ≥2 nhóm triển khai trong cùng monolith thay vì 1 khối duy nhất | 2 nhóm container logic: "Nhóm Giao dịch" và "Nhóm Hỗ trợ" (§4.1) + Payment tách biệt |
|
||||
| `CON-05`/`OQ-010` (chưa xác nhận đội thi công thật từng vận hành Kafka/MSK/OpenSearch/EKS production) | Managed service đơn giản hơn (SQS/EventBridge, ECS Fargate, RDS) thay vì tự vận hành cluster | Loại Kafka/MSK/OpenSearch cho MVP — dùng SQS FIFO + EventBridge (`ASR-005`) và Postgres FTS giai đoạn đầu |
|
||||
| `CON-06` (PCI-DSS SAQ A, không thương lượng) | Payment phải là ranh giới mạng/IAM/DB riêng bất kể chọn monolith hay microservices | Payment Service tách hoàn toàn (`ASR-002`) — quyết định này **không phụ thuộc** việc chọn P1 hay P2 |
|
||||
|
||||
🔴 **Modular monolith là mặc định hợp lý** cho ≤2 team và ranh giới nghiệp vụ chưa ổn định — ở
|
||||
đây team thi công thật **chưa được Tech Lead xác nhận** (`OQ-010` còn mở); ranh giới 2 nhóm logic
|
||||
dưới đây (`ASR-014`) dựa trên giả định team `DEC-02`, phải rà lại khi có số thật.
|
||||
|
||||
---
|
||||
|
||||
## 3. C4 — Mức 1: System Context
|
||||
|
||||
*Mức: **C4 Context**. Ai dùng hệ thống, hệ thống nói chuyện với cái gì bên ngoài. Không có chi
|
||||
tiết bên trong.*
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Guest(["○ Guest\n(chưa đăng nhập)"])
|
||||
Customer(["○ Customer"])
|
||||
Seller(["○ Seller"])
|
||||
Admin(["○ Admin\n(bắt buộc MFA — ASR-009)"])
|
||||
|
||||
subgraph SYS["▭ Sàn e-commerce — P2: Modular Monolith + managed AWS, Payment tách riêng"]
|
||||
PLATFORM["Nền tảng e-commerce\n(Identity · Catalog · Cart&Order · Seller · Commission ·\nPromotion&Loyalty · Review · Notification · Shipping · Payment)"]
|
||||
end
|
||||
|
||||
VNPay["▱ VNPay\n(cổng thanh toán)"]
|
||||
Momo["▱ Momo\n(cổng thanh toán)"]
|
||||
GHN["▱ GHN\n(vận chuyển)"]
|
||||
GHTK["▱ GHTK\n(vận chuyển, fallback GHN)"]
|
||||
EmailSMS["▱ Email/SMS Provider\n(nhà cung cấp chưa chốt — CTX §4.2)"]
|
||||
|
||||
Guest -->|"1 · HTTPS REST, sync"| PLATFORM
|
||||
Customer -->|"1 · HTTPS REST, sync"| PLATFORM
|
||||
Seller -->|"1 · HTTPS REST, sync"| PLATFORM
|
||||
Admin -->|"1 · HTTPS REST, sync"| PLATFORM
|
||||
|
||||
PLATFORM -->|"2 · REST (init) sync + Webhook IPN async"| VNPay
|
||||
PLATFORM -->|"2 · REST (init) sync + Webhook IPN async"| Momo
|
||||
PLATFORM -->|"3 · REST (tạo/tra vận đơn) sync + Webhook async"| GHN
|
||||
PLATFORM -->|"3 · REST sync + Webhook async, fallback GHN"| GHTK
|
||||
PLATFORM -->|"4 · REST/SDK qua queue, async"| EmailSMS
|
||||
```
|
||||
|
||||
**Legend:** ▭ hệ thống của ta · ▱ hệ thống ngoài · ○ người dùng · ──▶ nhãn số + giao thức + sync/async ghi trên mũi tên.
|
||||
|
||||
| Thực thể ngoài | Vai trò | Ai sở hữu | Giao thức | SLA của họ | `IF-nnn` ứng viên |
|
||||
|---|---|---|---|---|---|
|
||||
| VNPay | Cổng thanh toán online (redirect + IPN), không lưu thẻ | VNPay (bên thứ ba) | REST/HTTPS, timeout đề xuất 10s (kế thừa `CTX §4.2`, **chưa kiểm chứng sandbox thật**) | 🔴 Chưa xác nhận (`CON-04`) | `IF-007` |
|
||||
| Momo | Tương tự VNPay | Momo (bên thứ ba) | REST/HTTPS, timeout đề xuất 10s | 🔴 Chưa xác nhận (`CON-04`) | `IF-008` |
|
||||
| GHN | Tạo vận đơn, tra cứu trạng thái, webhook | GHN (bên thứ ba) | REST/HTTPS, timeout đề xuất 8s | 🔴 Chưa xác nhận (`CON-04`) | `IF-018` |
|
||||
| GHTK | Tương tự GHN, fallback chéo khi GHN lỗi (`ASR-013`) | GHTK (bên thứ ba) | REST/HTTPS, timeout đề xuất 8s | 🔴 Chưa xác nhận (`CON-04`) | `IF-019` |
|
||||
| Email/SMS Provider | Thông báo đơn hàng/giao hàng, đa ngôn ngữ | Chưa chọn (`SAD.md §3.4` tự ghi "chưa chốt"; 🔴🔴 mức chưa sẵn sàng cao nhất theo `CTX §4.2`) | REST/HTTPS hoặc SDK qua queue, timeout đề xuất 5s | Chưa có nhà cung cấp | `IF-020` |
|
||||
|
||||
*Ngoài phạm vi Context này (đã ghi ở `CTX §4.2`, không lặp lại chi tiết): Google/Facebook OAuth
|
||||
(Should, `DRV` không có — không chặn MVU vì email/password vẫn hoạt động độc lập); ngân hàng
|
||||
payout (COD/hoa hồng, luồng nội bộ tài chính, không phải điểm tích hợp giao dịch của Cart &
|
||||
Checkout). Không vẽ vào Context vì không thuộc phạm vi bắt buộc của ghi chú người duyệt.*
|
||||
|
||||
---
|
||||
|
||||
## 4. C4 — Mức 2: Container
|
||||
|
||||
*Mức: **C4 Container**. Các khối chạy được và triển khai được. Đây là sơ đồ dev dùng nhiều nhất.*
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
WebApp["Web/Mobile Client\n(Guest/Customer/Seller/Admin)"]
|
||||
|
||||
ALB["ALB / API Gateway\n(WAF gắn kèm — TCO §3.2)"]
|
||||
|
||||
subgraph MONO["Modular Monolith — ECS Fargate (P2)"]
|
||||
GD["Nhóm Giao dịch\n(Identity&Access · Catalog&Inventory ·\nCart&Order + Dispute)"]
|
||||
HT["Nhóm Hỗ trợ\n(Seller Mgmt · Commission&Payout ·\nPromotion&Loyalty · Review · Notification ·\nShipping&Fulfillment)"]
|
||||
end
|
||||
|
||||
PAY["Payment Service\n(mạng/IAM riêng — ASR-002)"]
|
||||
|
||||
BUS[("SQS FIFO (group=seller_id)\n+ EventBridge — ASR-005")]
|
||||
RDS[("RDS PostgreSQL Multi-AZ chính\nschema-per-module — ASR-006")]
|
||||
RDSPAY[("RDS PostgreSQL riêng\nchỉ Payment — ASR-002")]
|
||||
REDIS[("ElastiCache Redis\ncache/session/ownership")]
|
||||
S3CF[("S3 + CloudFront\nasset/ảnh sản phẩm/KYC")]
|
||||
|
||||
VNPay["VNPay"]
|
||||
Momo["Momo"]
|
||||
GHN["GHN"]
|
||||
GHTK["GHTK"]
|
||||
EmailSMS["Email/SMS Provider"]
|
||||
|
||||
WebApp -->|"1 · HTTPS REST, sync"| ALB
|
||||
ALB -->|"2 · REST, sync"| GD
|
||||
ALB -->|"3 · REST, sync"| HT
|
||||
ALB -->|"4 · REST, sync, cô lập mạng"| PAY
|
||||
GD -->|"5 · SQL, sync"| RDS
|
||||
HT -->|"5 · SQL, sync"| RDS
|
||||
PAY -->|"6 · SQL, sync"| RDSPAY
|
||||
GD -->|"7 · cache/session, sync"| REDIS
|
||||
GD -->|"8 · publish OrderPlaced, async"| BUS
|
||||
PAY -->|"8b · publish PaymentConfirmed, async"| BUS
|
||||
BUS -->|"9 · consume, async"| HT
|
||||
GD -->|"10 · asset, sync"| S3CF
|
||||
GD -->|"11 · REST, sync — áp dụng coupon/điểm (OQ mới BA §OQ-017)"| HT
|
||||
PAY -->|"12 · REST sync (init) + webhook async"| VNPay
|
||||
PAY -->|"12 · REST sync (init) + webhook async"| Momo
|
||||
HT -->|"13 · REST sync + webhook async"| GHN
|
||||
HT -->|"13 · REST sync + webhook async, fallback"| GHTK
|
||||
HT -->|"14 · SDK/queue, async"| EmailSMS
|
||||
```
|
||||
|
||||
**Legend:** ▭ container ta sở hữu · hình trụ = data store · nhãn số + giao thức + sync/async
|
||||
bắt buộc trên mọi mũi tên (`D4`) · mũi tên "11" (Cart&Order → Promotion&Loyalty, `IF-021`) **là
|
||||
cross-network REST** — Nhóm Giao dịch và Nhóm Hỗ trợ là **2 ECS Fargate service riêng** (theo
|
||||
`OQ-026`/`ASM-23` đã chốt TẠM), không phải cùng process.
|
||||
|
||||
🔴 **Sửa v1.2:** bản trước (v1.0/v1.1) ghi nhầm mũi tên "11" là "internal call trong cùng
|
||||
process/network boundary" — mâu thuẫn trực tiếp với `OQ-026` (2 nhóm ECS riêng) đã chốt TẠM ngay
|
||||
trong cùng tài liệu. Phát hiện bởi `ICD §0`/`OQ-028` (`ASM-24`). Timeout/fallback cụ thể **chưa
|
||||
chốt** — ứng viên `FAIL` có mức ưu tiên cao hơn vì nay là cross-network call nằm trong đường găng
|
||||
checkout (ngân sách `QAS-002` ≤3s). Không mũi tên container↔container nào còn được coi là
|
||||
"internal" trong sơ đồ này — kể cả `IF-022` (Cart&Order↔Seller Management, cũng Nhóm Giao
|
||||
dịch↔Nhóm Hỗ trợ, xem footnote §4.1).
|
||||
|
||||
### 4.1 Bảng container/component — `CMP-nn`
|
||||
|
||||
*Cột "Nhóm triển khai" theo yêu cầu người duyệt: **Nhóm giao dịch** / **Nhóm hỗ trợ** / **Payment
|
||||
(tách biệt)** / **Hạ tầng dùng chung** (không thuộc 3 nhóm compute, dùng chung bởi nhiều nhóm) —
|
||||
theo `ASR-014`.*
|
||||
|
||||
| ID | Tên | Trách nhiệm *(một câu)* | **Cái nó KHÔNG làm** | Dữ liệu sở hữu *(ứng viên `DAT`)* | Interface vào | Interface ra | Team | `ASR` ép ra | Nhóm triển khai |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| `CMP-01` | ALB / API Gateway | Định tuyến, TLS termination, WAF, biên rate-limit ngoài | Không chứa business logic; không tự quyết định authz chi tiết (chỉ chuyển token/session xuống) | Không (stateless) | `IF-001` | `IF-002`, `IF-003`, `IF-004` | Platform/DevOps | `ASR-007` (một phần — chỗ ra quyết định authz) | Hạ tầng dùng chung |
|
||||
| `CMP-02` | Identity & Access | Đăng ký/đăng nhập, phát hành JWT/session, MFA Admin (`ASR-009`) | Không quyết định ownership dữ liệu Cart/Order (chỉ cấp danh tính) | `User`/`Account`, `Session`, `MFA config` | `IF-002` | `IF-015` (Redis) | BE (nhóm giao dịch) | `ASR-007`, `ASR-009`, `ASR-010`, `ASR-011` | Nhóm Giao dịch *(`ASM-22` mới — xem §10)* |
|
||||
| `CMP-03` | Catalog & Inventory | Quản lý Product/Variant/Category, tồn kho, giữ tồn kho (reserve) lúc checkout | Không tính giá cuối cùng có khuyến mãi (phối hợp với Promotion&Loyalty) | `Product`, `ProductVariant`, `Category`, `InventoryStock` | `IF-002`, `IF-005` | `IF-016` (RDS) | BE (nhóm giao dịch) | `ASR-006`, `ASR-015` | Nhóm Giao dịch |
|
||||
| `CMP-04` | Cart & Order (+ Dispute) | Giỏ hàng đa seller, checkout, tách `Order`/`OrderSeller` theo seller (`ASR-003`), ownership check | Không xử lý thanh toán thật (chuyển Payment Service); không tính hoa hồng | `Cart`, `CartItem`, `Order`, `OrderSeller`, `OrderItem`, `Dispute` | `IF-002` | `IF-005`, `IF-006`, `IF-009`, `IF-021`, `IF-022` | BE (nhóm giao dịch, chi tiết nhất — §5) | `ASR-001`, `ASR-003`, `ASR-004` (phần cập nhật status), `ASR-007`, `ASR-008`, `ASR-010`, `ASR-011` | Nhóm Giao dịch |
|
||||
| `CMP-05` | Seller Management | Onboarding/KYC seller, quản trị seller (khoá/duyệt) | Không tính hoa hồng/payout | `Seller`, `KYC document` (S3 ref) | `IF-003` | `IF-016`, `IF-022` | BE (nhóm hỗ trợ) | `ASR-008` | Nhóm Hỗ trợ |
|
||||
| `CMP-06` | Commission & Payout | Cấu hình hoa hồng theo ngành hàng, tính hoa hồng, lịch payout, kỳ giữ tiền (hold) | Không khởi tạo giao dịch thanh toán khách hàng | `CommissionConfig`, `PayoutBatch`, `PayoutLedger` | `IF-009` | *(ngân hàng payout — ngoài phạm vi module này)* | BE (nhóm hỗ trợ) | `ASR-003` (tiêu thụ `OrderSeller`), `ASR-005` | Nhóm Hỗ trợ |
|
||||
| `CMP-07` | Promotion & Loyalty | Cấu hình coupon, tích/đổi điểm, xếp hạng thành viên; API áp dụng mã/điểm cho checkout | Không tạo `Order` | `Coupon`/`Promotion`, `LoyaltyPoint`, `MembershipTier` | `IF-009`, `IF-021` | — | BE (nhóm hỗ trợ) | `ASR-005` (consumer fan-out) | Nhóm Hỗ trợ |
|
||||
| `CMP-08` | Review | Đánh giá/nhận xét sản phẩm sau khi mua | Không xử lý đơn hàng | `Review`, `Rating` | `IF-003`, `IF-009` | — | BE (nhóm hỗ trợ) | `ASR-005` (consumer fan-out) | Nhóm Hỗ trợ |
|
||||
| `CMP-09` | Notification | Gửi email/SMS theo sự kiện, nội dung đa ngôn ngữ cho UI hệ thống (`ASR-015`) | Không tự quyết định nội dung nghiệp vụ (chỉ render template theo sự kiện) | `NotificationLog`, `Template` | `IF-009` | `IF-020` | BE (nhóm hỗ trợ) | `ASR-005`, `ASR-015` | Nhóm Hỗ trợ |
|
||||
| `CMP-10` | Shipping & Fulfillment | Điều phối đóng gói, tích hợp GHN/GHTK, cập nhật trạng thái giao hàng, fallback chéo (`ASR-013`) | Không tính phí hoa hồng | `ShippingOrder`/`Waybill`, tracking status | `IF-003`, `IF-009` | `IF-018`, `IF-019` | BE (nhóm hỗ trợ) | `ASR-013` | Nhóm Hỗ trợ |
|
||||
| `CMP-11` | Payment Service | Khởi tạo giao dịch VNPay/Momo, xử lý webhook idempotent (`ASR-004`), xử lý trạng thái COD, đối soát bù, **không lưu thẻ** | Không giữ dữ liệu Cart/Order (chỉ nhận/trả `gateway_transaction_ref` + status) | `Payment`, `PaymentTransaction`, `ReconciliationLog` | `IF-004`, `IF-006`, `IF-007` (webhook), `IF-008` (webhook) | `IF-007`, `IF-008`, `IF-009`, `IF-017` | BE riêng (Payment, cô lập) | `ASR-002`, `ASR-004`, `ASR-010`, `ASR-011`, `ASR-013` | **Payment (tách biệt)** |
|
||||
| `CMP-12` | Message Backbone (SQS FIFO + EventBridge) | Truyền sự kiện `OrderPlaced`/`PaymentConfirmed` bất đồng bộ, đảm bảo thứ tự theo `seller_id` | Không lưu trạng thái nghiệp vụ lâu dài (chỉ transit + DLQ tạm) | Không (message transit) | `IF-009` (publish) | `IF-009` (consume bởi HT) | Platform/SRE | `ASR-005` | Hạ tầng dùng chung *(publish: Nhóm Giao dịch + Payment; consume: Nhóm Hỗ trợ)* |
|
||||
| `CMP-13` | RDS chính (schema-per-module) | Lưu trữ giao dịch cho mọi module trừ Payment, chịu tải ghi/đọc gộp | Không lưu dữ liệu Payment (RDS riêng) | Schema của `Identity`/`Catalog`/`Cart&Order`/`Seller`/`Commission`/`Promotion`/`Review`/`Notification`/`Shipping` | `IF-016` | — | Ops/DBA | `ASR-006` | Hạ tầng dùng chung *(Nhóm Giao dịch + Nhóm Hỗ trợ)* |
|
||||
| `CMP-14` | RDS Payment (riêng) | Lưu trữ `Payment`/`PaymentTransaction`, tách biệt hoàn toàn | Không cho module khác truy cập trực tiếp | `Payment`, `PaymentTransaction` | `IF-017` | — | Ops/DBA | `ASR-002`, `ASR-006` | Payment (tách biệt) |
|
||||
| `CMP-15` | ElastiCache Redis | Cache session/ownership/giỏ hàng để đạt ngân sách latency (`QAS-003`/`004`) mà không tra DB mỗi request | Không là nguồn sự thật (source of truth) — chỉ cache | Không (cache, TTL) | `IF-015` | — | Ops/SRE | `ASR-007` | Nhóm Giao dịch *(chủ yếu)* |
|
||||
|
||||
🔴 **15/15 `CMP` có ít nhất một `ASR` phục vụ — không có `CMP` mồ côi.** `ASR-001` (kiểu kiến
|
||||
trúc tổng thể), `ASR-012` (AWS bắt buộc) và `ASR-014` (ranh giới nhóm triển khai) là ràng buộc
|
||||
**cấu trúc/nền** áp dụng cho toàn bộ bảng trên (không map vào một `CMP` đơn lẻ) — xem ma trận
|
||||
đầy đủ ở §4.3.
|
||||
|
||||
🔴 **Bổ sung v1.2 (rà theo `OQ-028`):** cột "Interface ra/vào" ở trên chỉ ghi ID, không ghi loại
|
||||
kết nối — để tránh mơ hồ, ghi rõ tại đây: `IF-021` (`CMP-04`→`CMP-07`) và `IF-022` (`CMP-04`↔
|
||||
`CMP-05`) đều là **cross-network REST** (Nhóm Giao dịch ↔ Nhóm Hỗ trợ, 2 ECS Fargate service
|
||||
riêng theo `OQ-026`/`ASM-23`) — không phải in-process. `IF-005` (`CMP-04`→`CMP-03`, cùng Nhóm
|
||||
Giao dịch) vẫn **in-process** (không đổi). `IF-006` (`CMP-04`→`CMP-11`) vẫn **cross-network**
|
||||
(Payment luôn tách biệt, không đổi). Không `IF` nào khác đổi loại trong lượt sửa này.
|
||||
|
||||
### 4.2 Ranh giới thay đổi
|
||||
|
||||
| Loại thay đổi hay xảy ra | Chạm những container nào | Có chấp nhận được không |
|
||||
|---|---|---|
|
||||
| Thêm kênh thanh toán mới (VD ví điện tử khác) | `CMP-11` Payment Service + `CMP-14` RDS Payment | ✅ Chấp nhận — đúng ranh giới cô lập `ASR-002`, không chạm Nhóm Giao dịch/Hỗ trợ |
|
||||
| Đổi quy tắc tính hoa hồng theo ngành hàng | `CMP-06` Commission & Payout | ✅ Chấp nhận — chỉ chạm Nhóm Hỗ trợ |
|
||||
| Thêm ngôn ngữ hiển thị mới (UI hệ thống) | `CMP-09` Notification, `CMP-03` Catalog (nội dung sản phẩm nếu PO đổi phạm vi `OQ-025`), tầng FE (ngoài `SAD`) | ✅ Chấp nhận một phần — xem `ASR-015`, `OQ-025` (vẫn mở) |
|
||||
| Đổi phí ship theo seller (VD trợ giá) | `CMP-04` Cart & Order (Nhóm Giao dịch) + `CMP-10` Shipping & Fulfillment (Nhóm Hỗ trợ) | ✅ Chạm 2 container nhưng chấp nhận được — đây là bản chất của luồng tách đơn theo seller (`ASR-003`), không phải dấu hiệu cắt sai |
|
||||
| Đổi mô hình tách đơn (VD gộp nhiều seller vào 1 đơn) | `CMP-04`, `CMP-06`, `CMP-08`, `CMP-10` (≥4 container) | ⚠️ **Không nên xảy ra thường xuyên** — đây là core domain model (`ASR-003`/`ADR-003`, radar ~6); nếu phát sinh nhu cầu đổi, đó là tín hiệu cần rà lại `ADR-003`, không phải lỗi phân rã |
|
||||
|
||||
Không có loại thay đổi thường xuyên nào chạm ≥3 container ngoài trường hợp core model đã ghi
|
||||
chú ở trên (đúng kỳ vọng của mục này — phân rã đang cắt theo domain, không theo tầng kỹ thuật).
|
||||
|
||||
### 4.3 Ma trận `ASR` × `CMP` *(đủ 15/15)*
|
||||
|
||||
| `ASR` | `CMP` phục vụ | Ghi chú |
|
||||
|---|---|---|
|
||||
| `ASR-001` | *Toàn bộ cấu trúc container ở §4* (ranh giới 3 nhóm triển khai + Payment tách riêng) | Không map vào một `CMP` đơn lẻ — là quyết định cấu trúc tổng thể, xem `ADR-001` |
|
||||
| `ASR-002` | `CMP-11`, `CMP-14` | Payment Service + RDS riêng |
|
||||
| `ASR-003` | `CMP-04`, `CMP-06` (tiêu thụ), `CMP-10` (tiêu thụ) | Mô hình `Order`/`OrderSeller` do `CMP-04` sở hữu |
|
||||
| `ASR-004` | `CMP-11` (webhook + đối soát), `CMP-04` (cập nhật `OrderSeller.status`) | |
|
||||
| `ASR-005` | `CMP-12`, `CMP-06`, `CMP-07`, `CMP-08`, `CMP-09`, `CMP-10` | Message backbone + 5 consumer fan-out (khớp `ASR-005` "≥5 consumer") |
|
||||
| `ASR-006` | `CMP-13`, `CMP-14` | |
|
||||
| `ASR-007` | `CMP-01`, `CMP-02`, `CMP-04`, `CMP-15` | Chỗ ra quyết định authz + cache — chi tiết ở hoạt động `sec` |
|
||||
| `ASR-008` | `CMP-04` (tách đơn seller data), `CMP-05` (KYC PII) | |
|
||||
| `ASR-009` | `CMP-02` | |
|
||||
| `ASR-010` | `CMP-02`, `CMP-04`, `CMP-11` | Nhóm "giao dịch cốt lõi" cho HA/DR — khớp đúng 3 `CMP` này |
|
||||
| `ASR-011` | `CMP-02`, `CMP-04`, `CMP-11` | Cùng 3 `CMP` như `ASR-010` (observability cho cùng nhóm cốt lõi) |
|
||||
| `ASR-012` | *Ràng buộc nền cho mọi `CMP`* | Mọi dịch vụ managed dùng ở §4/§7 đều là AWS — không sinh `CMP` riêng |
|
||||
| `ASR-013` | `CMP-11` (VNPay/Momo), `CMP-10` (GHN/GHTK) | |
|
||||
| `ASR-014` | *Cột "Nhóm triển khai" của toàn bộ bảng §4.1* | Xem `ADR-012`; phụ thuộc `OQ-010` (số đội thật) |
|
||||
| `ASR-015` | `CMP-03` (nội dung sản phẩm), `CMP-09` (thông báo) | Phần lớn thuộc tầng FE, ngoài phạm vi `SAD` backend |
|
||||
|
||||
---
|
||||
|
||||
## 5. C4 — Mức 3: Component *(container phức tạp nhất — Nhóm Giao dịch, chi tiết Cart & Order)*
|
||||
|
||||
*Mức: **C4 Component**. Theo yêu cầu người duyệt "chi tiết nhất cho Giỏ hàng & Checkout" — vẽ
|
||||
mức Component cho container "Nhóm Giao dịch", xoáy vào `CMP-04` Cart & Order vì đây là logic
|
||||
phức tạp nhất (tách đơn theo seller, ownership check, phối hợp Catalog/Payment/Promotion).*
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph GD["Nhóm Giao dịch — Component view"]
|
||||
API["Cart/Checkout API\n(GET/PATCH/DELETE /v1/cart*, POST /v1/checkout)"]
|
||||
OWN["Ownership Check\n(ASR-007)"]
|
||||
CARTSVC["Cart Service\n(CartItem, nhóm theo seller_id)"]
|
||||
CHECKOUT["Checkout Orchestrator\n(tách Order/OrderSeller — ASR-003)"]
|
||||
IDSVC["Identity & Access\n(CMP-02)"]
|
||||
CATSVC["Catalog & Inventory\n(CMP-03)"]
|
||||
end
|
||||
|
||||
REDIS[("Redis — session/ownership cache")]
|
||||
RDS[("RDS chính")]
|
||||
PAY["Payment Service\n(ranh giới mạng khác — CMP-11)"]
|
||||
BUS[("SQS FIFO/EventBridge")]
|
||||
PROMO["Promotion & Loyalty\n(Nhóm Hỗ trợ, CMP-07)"]
|
||||
|
||||
API --> OWN
|
||||
OWN -->|"15 · cache hit, sync"| REDIS
|
||||
OWN -->|"nếu cache miss, sync"| IDSVC
|
||||
API --> CARTSVC
|
||||
CARTSVC -->|"16 · SQL, sync"| RDS
|
||||
CARTSVC -->|"5 · kiểm tra/giữ tồn kho, sync"| CATSVC
|
||||
API --> CHECKOUT
|
||||
CHECKOUT -->|"16 · SQL, sync (ghi Order/OrderSeller/OrderItem)"| RDS
|
||||
CHECKOUT -->|"21 · REST, sync — áp dụng coupon/điểm"| PROMO
|
||||
CHECKOUT -->|"6 · REST, sync — khởi tạo thanh toán"| PAY
|
||||
CHECKOUT -->|"9 · publish OrderPlaced, async"| BUS
|
||||
```
|
||||
|
||||
**Legend:** số trên mũi tên tham chiếu đúng `IF-nnn` ứng viên ở §4.1/§6.3 (không tạo số mới ở
|
||||
mức Component — dùng lại `IF-005`, `IF-006`, `IF-009`, `IF-015`, `IF-016`, `IF-021`).
|
||||
|
||||
🔴 **Sửa v1.2:** mũi tên "21" (`CHECKOUT`→`PROMO`, `IF-021`) là **cross-network REST** — `PROMO`
|
||||
thuộc Nhóm Hỗ trợ, đã vẽ ngoài subgraph `GD` từ trước (đúng), chỉ chú thích lại cho khớp legend §4
|
||||
đã sửa; không đổi hình vẽ.
|
||||
|
||||
---
|
||||
|
||||
## 6. Luồng chính
|
||||
|
||||
*Sequence diagram cho 2 luồng quan trọng nhất của Giỏ hàng & Checkout, theo `PROCESS_CartCheckout_v1.0.md` B1–B9.*
|
||||
|
||||
### 6.1 Checkout (tạo Order/OrderSeller đồng bộ; khởi tạo thanh toán online bất đồng bộ — `ADR-013`)
|
||||
|
||||
🔴 **Sửa v1.3 (`ADR-013`, `Proposed`):** nhánh VNPay/Momo trước đây gọi Payment Service **đồng bộ**
|
||||
trong cùng transaction (v1.0–v1.2) — `FAIL §1.2` phát hiện luồng đó vượt ngân sách `QAS-002`
|
||||
(3.220ms > 3.000ms). Từ v1.3, TX **commit ngay sau khi tạo `Order`/`OrderSeller`/`OrderItem`**
|
||||
(không giữ mở chờ Payment nữa); COD vẫn xác nhận đồng bộ ngay sau đó (không đổi, không gọi ra
|
||||
ngoài); VNPay/Momo chuyển thành **bất đồng bộ** — response trả về ngay với
|
||||
`status: PENDING_PAYMENT_INIT`, Payment Service gọi gateway sau, qua message
|
||||
`PaymentInitRequested`. Xem mô tả đầy đủ state machine, timeout, idempotency ở
|
||||
`adr/ADR-013_bat-dong-bo-hoa-khoi-tao-thanh-toan.md §3`. **Chưa được Tech Lead/PO thật ký** —
|
||||
`ADR-013` đang `Proposed`.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Customer/Guest
|
||||
participant GW as ALB/Gateway
|
||||
participant CO as Cart & Order (CMP-04)
|
||||
participant CAT as Catalog&Inventory (CMP-03)
|
||||
participant PROMO as Promotion&Loyalty (CMP-07)
|
||||
participant PAY as Payment Service (CMP-11)
|
||||
participant DB as RDS chính
|
||||
participant BUS as SQS FIFO/EventBridge
|
||||
|
||||
C->>GW: POST /v1/checkout (Idempotency-Key)
|
||||
GW->>CO: forward request
|
||||
CO->>CAT: kiểm tra + giữ tồn kho (reserve)
|
||||
CAT-->>CO: OK / không đủ (409 ERR_CONFLICT)
|
||||
alt Không đủ tồn kho
|
||||
CO-->>C: 409 — yêu cầu điều chỉnh giỏ (B4)
|
||||
else Đủ tồn kho
|
||||
CO->>PROMO: áp dụng coupon/điểm (nếu có)
|
||||
PROMO-->>CO: giá trị giảm đã tính
|
||||
CO->>DB: BEGIN TX — tạo Order (cha) + N OrderSeller + OrderItem (B5)
|
||||
DB-->>CO: OK
|
||||
CO->>DB: COMMIT TX *(sửa v1.3 — commit ngay, không chờ Payment)*
|
||||
alt COD
|
||||
CO->>PAY: xác nhận COD, sync (Idempotency-Key)
|
||||
PAY-->>CO: xác nhận COD (B7)
|
||||
CO->>BUS: publish OrderPlaced (message group = seller_id)
|
||||
CO-->>C: 201 Created — status CONFIRMED (COD)
|
||||
else VNPay/Momo — bất đồng bộ (ADR-013)
|
||||
CO->>BUS: publish OrderPlaced + PaymentInitRequested (message group = seller_id, Idempotency-Key)
|
||||
CO-->>C: 201 Created — status PENDING_PAYMENT_INIT (chưa có redirectUrl)
|
||||
BUS->>PAY: consume PaymentInitRequested
|
||||
PAY->>PAY: gọi VNPay/Momo (timeout 10s kế thừa CTX §4.2, không còn bị ép ngắn)
|
||||
alt Init thành công
|
||||
PAY->>BUS: publish PaymentInitReady (redirectUrl)
|
||||
Note over C,PAY: FE lấy redirectUrl qua polling/kênh đẩy — cơ chế cụ thể chưa chốt, OQ-041
|
||||
else Init thất bại/timeout
|
||||
PAY->>BUS: publish PaymentInitFailed
|
||||
Note over C,PAY: FE cho khách chọn lại phương thức hoặc chuyển COD — ADR-013 §3.3
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
| Bước | Thành phần | Đồng bộ? | Timeout *(đề xuất, chi tiết `FAIL §1.2`/`ADR-013 §3.1`)* | Lỗi thì sao | `QAS` liên quan |
|
||||
|---|---|---|---|---|---|
|
||||
| Kiểm tra/giữ tồn kho | Cart&Order → Catalog | Sync (trong Nhóm Giao dịch) | 150ms | 409, yêu cầu điều chỉnh giỏ (B4) | `QAS-002` |
|
||||
| Áp dụng coupon/điểm | Cart&Order → Promotion&Loyalty | **Sync, cross-network** (2 ECS service riêng — `OQ-028`/`ASM-24`) | 400ms | Chưa chốt hành vi lỗi — phụ thuộc `OQ-017` (BA) | `QAS-002` |
|
||||
| Tạo Order/OrderSeller + COMMIT | Cart&Order → RDS chính | Sync, 1 transaction, **commit ngay sau bước này** *(sửa v1.3 — không còn giữ TX mở chờ Payment, giảm rủi ro đã nêu ở `FAIL OQ-037/038`)* | 300ms | Rollback toàn bộ TX | `QAS-002`, `QAS-006` |
|
||||
| Xác nhận COD *(nhánh COD, không đổi)* | Cart&Order → Payment Service | Sync (vượt ranh giới mạng), nội bộ không gọi gateway ngoài | 600ms | Lỗi → rollback nghiệp vụ (COD không cần gateway ngoài nên hiếm khi lỗi kỹ thuật) | `QAS-002` |
|
||||
| **Khởi tạo thanh toán VNPay/Momo *(nhánh online — sửa v1.3, `ADR-013`)*** | Payment Service → VNPay/Momo, **bất đồng bộ sau khi đã trả response** | Async — không tính vào `QAS-002` nữa; timeout tới gateway = 10s kế thừa `CTX §4.2` (không cần ép 1.500ms như đề xuất tạm ở `FAIL v1.0`) | Timeout/lỗi → `PAYMENT_INIT_FAILED`, khách chọn thử lại hoặc chuyển COD (`ADR-013 §3.3`) | `QAS-002` *(nay đạt về cấu trúc, không phụ thuộc SLA đối tác — `CON-04`/`ARISK-03`)* |
|
||||
| Publish OrderPlaced (+ PaymentInitRequested cho nhánh online) | Cart&Order → SQS FIFO | Async | N/A (fire-and-forget có retry của SQS) | Message vào DLQ nếu consumer lỗi lặp lại — ứng viên `fail` | `QAS-005` |
|
||||
|
||||
### 6.2 Xác nhận thanh toán qua webhook + đối soát bù (bất đồng bộ)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant GW3 as VNPay/Momo
|
||||
participant PAY as Payment Service (CMP-11)
|
||||
participant DB as RDS Payment
|
||||
participant BUS as SQS FIFO/EventBridge
|
||||
participant CO as Cart & Order (CMP-04)
|
||||
participant RECON as Job đối soát (scheduled)
|
||||
|
||||
GW3->>PAY: Webhook IPN (gateway_transaction_ref, signature)
|
||||
PAY->>PAY: Kiểm tra chữ ký + idempotency (ASR-004)
|
||||
PAY->>DB: Cập nhật Payment.status = success (nếu hợp lệ)
|
||||
PAY->>BUS: publish PaymentConfirmed (message group = seller_id)
|
||||
BUS->>CO: consume — cập nhật OrderSeller.status = confirmed
|
||||
|
||||
loop Mỗi ≤15 phút (đề xuất — QAS-014, chờ OQ-021)
|
||||
RECON->>GW3: Tra cứu trạng thái giao dịch (API đối soát)
|
||||
RECON->>DB: So khớp Payment.status thật vs ghi nhận
|
||||
alt Lệch phát hiện
|
||||
RECON->>RECON: Ghi ReconciliationLog + cảnh báo (QAS-013)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
| Bước | Thành phần | Đồng bộ? | Timeout *(đề xuất, chờ `fail`)* | Lỗi thì sao | `QAS` liên quan |
|
||||
|---|---|---|---|---|---|
|
||||
| Nhận webhook | VNPay/Momo → Payment Service | Async (webhook) | N/A (bên gọi retry theo chính sách của họ) | Idempotency key theo `gateway_transaction_ref` — gọi lại không tạo hiệu ứng phụ (`ASR-004`) | `QAS-010`, A4 |
|
||||
| Publish PaymentConfirmed | Payment Service → SQS FIFO | Async | N/A | DLQ nếu lỗi lặp lại — ứng viên `fail` | `QAS-005` |
|
||||
| Job đối soát bù | Payment Service → VNPay/Momo (polling) | Sync (trong job) | Chưa chốt — ứng viên `fail` | Ghi log + cảnh báo nếu lệch, **không tự động sửa** (cần CSKH/Ops can thiệp theo `IMPACT §1.5`/`PROCESS` B9) | `QAS-014`, `QAS-013` |
|
||||
|
||||
### 6.3 Danh sách phụ thuộc vượt ranh giới process — ứng viên cho hoạt động `FAIL`
|
||||
|
||||
*Theo `D6` — mọi phụ thuộc dưới đây phải trả lời 4 câu hỏi (chậm/hỏng/sai dữ liệu/hồi phục) ở
|
||||
hoạt động `fail` (hoạt động 8, chưa chạy). Liệt kê ở đây để không phải dò lại từ đầu.*
|
||||
|
||||
| # | Phụ thuộc | Loại | Timeout đề xuất *(kế thừa, chưa kiểm chứng)* | `IF-nnn` |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Cart&Order → Catalog&Inventory (kiểm tra/giữ tồn kho) | Internal call (cùng monolith) | Chưa chốt | `IF-005` |
|
||||
| 2 | Cart&Order → Promotion&Loyalty (áp dụng coupon/điểm) | **Cross-network REST** (2 ECS service riêng — sửa v1.2 từ "Internal call", xem `OQ-028`/`ASM-24`) | Chưa chốt — ưu tiên cao hơn cho `FAIL` (round-trip mạng thêm vào ngân sách `QAS-002`); hành vi lỗi phụ thuộc `IMPACT §1.5` OQ-017 (BA) | `IF-021` |
|
||||
| 3 | Cart&Order → Payment Service | Cross-network REST | Chưa chốt | `IF-006` |
|
||||
| 4 | Payment Service → VNPay | External REST + Webhook | 10s (đề xuất, `CTX §4.2`) | `IF-007` |
|
||||
| 5 | Payment Service → Momo | External REST + Webhook | 10s (đề xuất) | `IF-008` |
|
||||
| 6 | Shipping&Fulfillment → GHN | External REST + Webhook | 8s (đề xuất) | `IF-018` |
|
||||
| 7 | Shipping&Fulfillment → GHTK (fallback GHN) | External REST + Webhook | 8s (đề xuất) | `IF-019` |
|
||||
| 8 | Notification → Email/SMS Provider | External SDK/queue | 5s (đề xuất) | `IF-020` |
|
||||
| 9 | Nhóm Giao dịch/Nhóm Hỗ trợ → RDS chính | DB (SQL) | Chưa chốt | `IF-016` |
|
||||
| 10 | Payment Service → RDS Payment | DB (SQL) | Chưa chốt | `IF-017` |
|
||||
| 11 | Nhóm Giao dịch → ElastiCache Redis | Cache | Chưa chốt | `IF-015` |
|
||||
| 12 | Cart&Order/Payment → SQS FIFO/EventBridge | Queue (publish) | N/A (managed) | `IF-009` |
|
||||
| 13 | Nhóm Hỗ trợ ← SQS FIFO/EventBridge | Queue (consume) | N/A (managed) | `IF-009` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Deployment view
|
||||
|
||||
*Cái gì chạy ở đâu, mấy bản, ranh giới mạng, ranh giới tin cậy. AWS `ap-southeast-1`, đối chiếu
|
||||
`TCO_e-commerce_v1.0.md §3.2` (P2, kịch bản A/B).*
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph INTERNET["Internet"]
|
||||
Users["Guest/Customer/Seller/Admin"]
|
||||
ExtPay["VNPay · Momo"]
|
||||
ExtShip["GHN · GHTK"]
|
||||
ExtNotif["Email/SMS Provider"]
|
||||
end
|
||||
|
||||
subgraph AWS["AWS ap-southeast-1"]
|
||||
subgraph PublicSubnet["Public subnet"]
|
||||
WAF["WAF"]
|
||||
ALB["ALB"]
|
||||
CF["CloudFront"]
|
||||
NAT["NAT Gateway (2 AZ)"]
|
||||
end
|
||||
subgraph PrivateApp["Private subnet — ứng dụng"]
|
||||
subgraph ECSMono["ECS Fargate — Modular Monolith\n(⚠️ TCO tính gộp 1 dòng compute — xem OQ-026)"]
|
||||
ECSGD["Nhóm Giao dịch\n(tasks — số theo TCO §3.2, chưa tách riêng)"]
|
||||
ECSHT["Nhóm Hỗ trợ\n(tasks — số theo TCO §3.2, chưa tách riêng)"]
|
||||
end
|
||||
ECSPay["ECS Fargate — Payment Service\n(mạng riêng, IAM riêng)"]
|
||||
end
|
||||
subgraph PrivateData["Private subnet — dữ liệu"]
|
||||
RDSMain[("RDS PostgreSQL Multi-AZ chính\nA: r6g.xlarge · B: r6g.2xlarge + 1 read replica")]
|
||||
RDSPay[("RDS PostgreSQL Multi-AZ Payment\nA: t4g.medium · B: r6g.large")]
|
||||
Redis[("ElastiCache Redis\nA: r6g.large ×1 · B: r6g.xlarge ×1 + 1 replica")]
|
||||
end
|
||||
SQS[("SQS FIFO + EventBridge")]
|
||||
S3[("S3")]
|
||||
end
|
||||
|
||||
Users -->|HTTPS| WAF --> ALB --> ECSGD
|
||||
ALB --> ECSHT
|
||||
ALB --> ECSPay
|
||||
ECSGD --> RDSMain
|
||||
ECSHT --> RDSMain
|
||||
ECSPay --> RDSPay
|
||||
ECSGD --> Redis
|
||||
ECSGD --> SQS
|
||||
ECSPay --> SQS
|
||||
SQS --> ECSHT
|
||||
ECSGD -->|"IF-021/IF-022, REST sync — cross-network (OQ-028)"| ECSHT
|
||||
ECSGD --> S3
|
||||
CF --> S3
|
||||
ECSGD -.-> NAT
|
||||
ECSHT -.-> NAT
|
||||
ECSPay -.-> NAT
|
||||
ECSPay --> ExtPay
|
||||
ECSHT --> ExtShip
|
||||
ECSHT --> ExtNotif
|
||||
```
|
||||
|
||||
| Thành phần | Môi trường | Số bản *(A / B — `TCO §3.2`)* | Cấu hình | Vùng/AZ | Ranh giới tin cậy |
|
||||
|---|---|---|---|---|---|
|
||||
| WAF + ALB | Prod | Managed (không đếm instance) | — | Multi-AZ | Ranh giới internet → VPC |
|
||||
| ECS Fargate — Modular Monolith *(⚠️ xem `OQ-026`)* | Prod | A: ~4 tasks×1vCPU/2GB · B: ~10 tasks×1vCPU/2GB | Auto-scaling theo CPU/request count | Multi-AZ (private subnet) | Ranh giới VPC nội bộ — chưa tách riêng ranh giới mạng con giữa Nhóm Giao dịch/Nhóm Hỗ trợ. **v1.2:** `IF-021`/`IF-022` là cross-network REST giữa `ECSGD`↔`ECSHT` (cùng VPC, khác ECS service) — cơ chế kết nối thật (service discovery/internal LB, security group) **chưa thiết kế**, thuộc hoạt động `inf` (chưa chạy) |
|
||||
| ECS Fargate — Payment Service | Prod | A: 2 tasks×0,5vCPU/1GB · B: 4 tasks×0,5vCPU/1GB | Mạng/IAM riêng — không chung security group với monolith | Multi-AZ (private subnet riêng) | Ranh giới tin cậy cao nhất — PCI-DSS SAQ A (`ASR-002`) |
|
||||
| RDS chính | Prod | A: `r6g.xlarge` Multi-AZ · B: `r6g.2xlarge` Multi-AZ + 1 read replica | schema-per-module | Multi-AZ | Chỉ Nhóm Giao dịch/Nhóm Hỗ trợ truy cập |
|
||||
| RDS Payment | Prod | A: `t4g.medium` Multi-AZ · B: `r6g.large` Multi-AZ | Riêng biệt hoàn toàn | Multi-AZ | Chỉ Payment Service truy cập |
|
||||
| ElastiCache Redis | Prod | A: `r6g.large` ×1 · B: `r6g.xlarge` ×1 + 1 replica | Session/ownership/giỏ hàng | Multi-AZ | Chỉ Nhóm Giao dịch truy cập |
|
||||
| SQS FIFO + EventBridge | Prod | Managed | Message group = `seller_id` | Managed (không AZ cụ thể) | Ranh giới publish (GD/Payment) vs consume (HT) |
|
||||
| S3 + CloudFront | Prod | Managed | ~500GB (A) / ~1,5TB (B) | Managed | Public read (asset) vs private (KYC — chỉ Seller Mgmt/Admin) |
|
||||
| Non-prod (dev/stg) | Dev/Stg | ~35% Production (`TCO §3.2`) | Cấu hình thu nhỏ | ap-southeast-1 | Tách VPC/account với Production (chưa chốt — ứng viên `inf`) |
|
||||
|
||||
🔴 **`OQ-026` (mới):** `TCO §3.2` tính chi phí compute ECS Fargate P2 gộp thành **một dòng
|
||||
"monolith"** (~4 tasks kịch bản A / ~10 tasks kịch bản B), không tách riêng số task cho "Nhóm
|
||||
Giao dịch" và "Nhóm Hỗ trợ" như `ASR-001`/`ASR-014`/`OPT §3` mô tả (2 nhóm ECS Fargate riêng để
|
||||
scale độc lập). Đây có thể chỉ là cách gộp số để tính chi phí (2 nhóm vẫn cộng lại đúng tổng
|
||||
task), hoặc có thể phản ánh việc `TCO` thực sự mô hình hoá **1 ECS service duy nhất** cho toàn bộ
|
||||
monolith (không tách nhóm) — hai cách hiểu cho ra kết luận khác nhau về khả năng scale độc lập
|
||||
Nhóm Giao dịch theo `DRV-04`. **Không tự đổi số `TCO`** — ghi nhận lệch mức chi tiết ở đây, cần
|
||||
Tech Lead/Ops xác nhận ở hoạt động `inf` trước khi AG2. Nếu xác nhận là 1 ECS service duy nhất:
|
||||
`ASR-014`/`ADR-012` phải viết lại phần "2 nhóm ECS Fargate riêng để scale nhanh hơn" thành "2
|
||||
nhóm logic trong cùng 1 ECS service, scale chung" — ảnh hưởng trực tiếp khả năng đáp ứng
|
||||
`ASR-001`/tiêu chí "Đáp ứng DRV Must" đã chấm ở `OPT §4`.
|
||||
|
||||
🔴 **Cập nhật v1.2 (`OQ-028`):** sơ đồ deployment trước đây (v1.0/v1.1) **thiếu cạnh mạng** giữa
|
||||
`ECSGD` và `ECSHT` dù Container diagram (§4, mũi tên "11") và Component diagram (§5, mũi tên "21")
|
||||
đã thể hiện `Cart&Order` gọi `Promotion&Loyalty` qua REST — nay bổ sung cạnh này (nhãn
|
||||
`IF-021`/`IF-022`) để hết mâu thuẫn nội bộ. Cơ chế kết nối thật (service discovery/internal load
|
||||
balancer, security group giữa 2 ECS service) **chưa được thiết kế** — thuộc hoạt động `inf` (hoạt
|
||||
động 7, chưa chạy). 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 "chỉ sửa lỗi nhất quán" của lượt chạy này.
|
||||
|
||||
---
|
||||
|
||||
## 8. Quyết định kiến trúc đã ghi *(12 `ADR` đã viết ở hoạt động `adr` — 2026-09-15)*
|
||||
|
||||
*Cập nhật ở SAD v1.1 theo `DEC-17`: 12 `ADR` ứng viên dưới đây (đã duyệt từng phần ở
|
||||
`ASR_e-commerce_v1.0.md §B2`/`DEC-14`) nay đã được viết thành file thật trong
|
||||
`02-architecture/adr/`. **Không đổi số thứ tự, không đổi radar ước lượng** so với bảng đã duyệt.
|
||||
Tất cả giữ `Status: Proposed` — chưa ADR nào `Accepted` vì chưa có chữ ký Tech Lead + Security +
|
||||
Ops/SRE thật.*
|
||||
|
||||
| `ADR` | Quyết định | File | Status | Radar | Cần POC/bài đo trước `Accepted`? |
|
||||
|---|---|---|---|---|---|
|
||||
| `ADR-001` | Kiểu kiến trúc tổng thể — Modular Monolith P2, không phải Microservices P1 | `adr/ADR-001_kieu-kien-truc-tong-the-modular-monolith-p2.md` | `Proposed` | ~7 | Có — `POC-01`/`POC-02` (dưới ngưỡng 8 cứng nhưng `ASM-07`/`08` chưa xác minh) |
|
||||
| `ADR-002` | Payment Service là biên cô lập PCI-DSS SAQ A | `adr/ADR-002_payment-service-bien-co-lap-pci-dss.md` | `Proposed` | ~7 | Không bắt buộc POC (ràng buộc pháp lý) — cần Security ký |
|
||||
| `ADR-003` | Mô hình `Order`/`OrderSeller` — tách đơn theo seller | `adr/ADR-003_mo-hinh-order-orderseller-tach-don-theo-seller.md` | `Proposed` | ~6 | Không — nhưng chờ `OQ-011` (BA) |
|
||||
| `ADR-004` | Cơ chế idempotency & đối soát cho webhook thanh toán | `adr/ADR-004_idempotency-doi-soat-webhook-thanh-toan.md` | `Proposed` | ~6 | Không bắt buộc — chờ sandbox VNPay/Momo thật |
|
||||
| `ADR-005` | Message backbone — SQS FIFO + EventBridge | `adr/ADR-005_message-backbone-sqs-fifo-eventbridge.md` | `Proposed` | **~8** | **Có — bắt buộc `POC-01`, chưa chạy** |
|
||||
| `ADR-006` | Chiến lược dữ liệu — RDS gộp schema-per-module | `adr/ADR-006_chien-luoc-du-lieu-rds-gop-schema-per-module.md` | `Proposed` | **~8** | **Có — bắt buộc `POC-02`, chưa chạy** |
|
||||
| `ADR-007` | Chỗ ra quyết định ownership/authz — service + cache Redis | `adr/ADR-007_cho-quyet-dinh-ownership-authz-cart-order.md` | `Proposed` | ~6 | Không — khuyến nghị đo lại `QAS-003`/`004` |
|
||||
| `ADR-008` | Vùng lưu trữ PII & chính sách chia sẻ cho seller | `adr/ADR-008_vung-luu-tru-pii-chinh-sach-chia-se-seller.md` | `Proposed` | ~7 | Phủ quyết Security/Legal — chặn hoàn toàn tới khi có người (`OQ-007`) |
|
||||
| `ADR-009` | Chiến lược HA/DR cho nhóm dịch vụ giao dịch lõi | `adr/ADR-009_chien-luoc-ha-dr-dich-vu-giao-dich-loi.md` | `Proposed` | **~9** | **Có — bắt buộc diễn tập DR, chưa chạy, điều kiện tiên quyết AG2 (`OQ-022`)** |
|
||||
| `ADR-010` | Kiến trúc observability & alerting | `adr/ADR-010_kien-truc-observability-alerting.md` | `Proposed` | ~6 | Không bắt buộc |
|
||||
| `ADR-011` | Chính sách resilience đối tác thanh toán/vận chuyển | `adr/ADR-011_chinh-sach-resilience-doi-tac-ngoai.md` | `Proposed` | ~6 | Không bắt buộc — chờ sandbox 4 đối tác |
|
||||
| `ADR-012` | Ranh giới nhóm triển khai theo domain và năng lực đội | `adr/ADR-012_ranh-gioi-nhom-trien-khai-theo-domain.md` | `Proposed` | ~7 | Không — chờ `OQ-010` (số đội thật) + `OQ-026`/`OQ-027` (khớp `TCO`, vị trí Identity) |
|
||||
| `ADR-013` | Bất đồng bộ hoá bước khởi tạo thanh toán trong checkout (Lựa chọn B của `OQ-034`, hiện thực hoá §6.1 v1.3) | `adr/ADR-013_bat-dong-bo-hoa-khoi-tao-thanh-toan.md` | `Proposed` | 7 | Không bắt buộc (dưới ngưỡng 8) — khuyến nghị chạy `FIT-23` (chaos đo p95) trước go-live; bắt buộc Tech Lead + PO **thật** xác nhận (không chỉ ký thay) trước `Accepted` |
|
||||
|
||||
*Sổ đầy đủ: `../00-index/ADL_e-commerce.md` §2 — mục lục 13 ADR đã đồng bộ theo lượt chạy
|
||||
`adr` 2026-09-15 (12 ADR ban đầu + `ADR-013` bổ sung cùng ngày, hoạt động `adr`, phạm vi hẹp).*
|
||||
|
||||
---
|
||||
|
||||
## 9. Mối quan tâm xuyên suốt
|
||||
|
||||
| Mối quan tâm | Quyết định | Ở đâu | `ADR` |
|
||||
|---|---|---|---|
|
||||
| Định dạng log & correlation id | Chưa chốt | `AGD` (GĐ3) | `ADR-010` (ứng viên) |
|
||||
| Xử lý lỗi & mã lỗi | Đề xuất kế thừa `API_US002-003` §2 (`{error:{code,message,details}, traceId}`) — chưa xác nhận BE | `ICD` (hoạt động 4) | — |
|
||||
| Xác thực & phân quyền | JWT (Customer) / `X-Guest-Session-Id` (Guest), MFA Admin = TOTP app (**tạm**, `OQ-024` mở) | `SEC` (hoạt động 6) | `ADR-007` (ứng viên) |
|
||||
| Cấu hình & secret | Chưa chốt | `SEC`, `INF` (hoạt động 6–7) | — |
|
||||
| Múi giờ & định dạng thời gian | Chưa có trường thời gian nào ở phạm vi Cart (`API_US002-003 §1`) — chốt khi mở rộng sang Order lifecycle | `ICD` | — |
|
||||
| Số lớn (id/tiền) | `string` cho mọi id (khớp đề xuất BA `API_US002-003 §1`, khớp ví dụ SAD gốc) | `ICD` | — |
|
||||
| Đa ngôn ngữ | UI hệ thống có i18n; nội dung seller tự nhập **không dịch ở MVP (tạm)**, `OQ-025` mở | `AGD` (GĐ3), `DAT` nếu đổi | — (borderline, `ASR-015`) |
|
||||
| Idempotency | `Idempotency-Key` bắt buộc cho `POST /v1/checkout` (khớp `04-api-design.md §4.1.1`); webhook idempotent theo `gateway_transaction_ref` (`ASR-004`) | `ICD`, `FAIL` (hoạt động 4, 8) | `ADR-004` (ứng viên) |
|
||||
|
||||
---
|
||||
|
||||
## 10. Giả định & Ngoài phạm vi
|
||||
|
||||
**Giả định** *(tiếp số toàn dự án — `ASM-01…21` đã dùng ở `CTX`/`OPT`/`TCO`/`QAS`/`ASR`, bắt đầu `ASM-22`)*:
|
||||
|
||||
| ID | Giả định | Cách xác minh | Nếu sai |
|
||||
|---|---|---|---|
|
||||
| `ASM-22` | Identity & Access được xếp vào **Nhóm Giao dịch** (không phải nhóm riêng) — suy từ `ASR-010`/`ASR-011` (nhóm "giao dịch cốt lõi" = Payment + Cart&Order + Identity cho HA/DR/observability), dù `OPT §3`/`ASM-19` chỉ nêu rõ Catalog/Cart&Order cho "nhóm giao dịch" (scale) mà không nhắc Identity | Tech Lead xác nhận lại tại hoạt động `sad` kế tiếp/khi rà `ADR-012`, cùng lúc với `OQ-010` | `CMP-02`/§4.1, §7 — nếu Identity thực ra nên là nhóm riêng hoặc thuộc Nhóm Hỗ trợ, đổi cột "Nhóm triển khai" và deployment view §7 |
|
||||
| `ASM-23` | `TCO §3.2` dòng compute "monolith" phản ánh **tổng số task** của cả Nhóm Giao dịch và Nhóm Hỗ trợ cộng lại (2 ECS service logic vẫn tồn tại, chỉ gộp số để tính tiền), không phải 1 ECS service duy nhất | Ops/Tech Lead xác nhận ở hoạt động `inf` (`OQ-026`) | Nếu sai (là 1 service duy nhất): `ASR-014`/`ADR-012` phải viết lại phần "scale độc lập theo nhóm"; ảnh hưởng đáp ứng `DRV-04`/tiêu chí `OPT §4` |
|
||||
|
||||
*`ASM-01…21` của `CTX`/`OPT`/`TCO`/`QAS`/`ASR` vẫn áp dụng nguyên trạng — không lặp lại nội
|
||||
dung, chỉ tham chiếu (đặc biệt `ASM-07`→`ADR-005`, `ASM-08`→`ADR-006`, `ASM-19`→`ADR-012`,
|
||||
`ASM-20`→`CMP-02` MFA, `ASM-21`→`CMP-09`/`CMP-03` i18n).*
|
||||
|
||||
**Ngoài phạm vi** *(quy tắc `D11`)*:
|
||||
|
||||
- `ADR`, `ICD`, `DAT`, `SEC`, `INF`, `FAIL` chính thức — chưa thực hiện ở lượt chạy này (chỉ hoạt
|
||||
động `sad`). Mọi bảng "ứng viên" ở §4.1, §6.3, §9 là đầu vào, không phải kết luận cuối.
|
||||
- Component mức 3 (§5) chỉ vẽ cho container "Nhóm Giao dịch" (Cart & Order) — các container khác
|
||||
(Nhóm Hỗ trợ, Payment Service) chưa có Component diagram riêng, theo đúng khuyến nghị
|
||||
`SKILL.md` ("không vẽ mức Component cho mọi container").
|
||||
- OpenSearch — **không** đưa vào deployment view P2 vì `TCO §3.2`/`OPT §3` P2 hoãn dùng managed
|
||||
OpenSearch, dùng Postgres full-text search giai đoạn đầu; chuyển sang OpenSearch khi có bằng
|
||||
chứng tải thật cần (ngưỡng xét lại: traffic thật tiệm cận kịch bản B ×2, theo `QAS-009`).
|
||||
Không tự thêm OpenSearch vào sơ đồ vì `TCO`/`OPT` không tính chi phí đó cho P2 kịch bản A/B.
|
||||
- Google/Facebook OAuth — không vẽ ở Context (§3) theo đúng phạm vi bắt buộc của ghi chú người
|
||||
duyệt (chỉ 5 hệ ngoài: VNPay/Momo/GHN/GHTK/Email-SMS); vẫn thuộc Identity & Access ở mức
|
||||
Container/Component khi triển khai chi tiết (ngoài phạm vi tài liệu này).
|
||||
- Kiến trúc này (P2) không nhắm tới tải vượt kịch bản B (10.000 concurrent) ×2 mà chưa kiểm
|
||||
chứng lại bằng `POC`/bài đo thật — kế thừa nguyên trạng từ `QAS-009`/`OPT §1`.
|
||||
- Ranh giới mạng con (subnet) chi tiết giữa Nhóm Giao dịch và Nhóm Hỗ trợ trong cùng `ECSMono` —
|
||||
chưa thiết kế (thuộc hoạt động `inf`); hiện chỉ tách Payment ra ranh giới mạng riêng theo
|
||||
`ASR-002`.
|
||||
|
||||
## 11. Open Questions
|
||||
|
||||
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | Hệ quả nếu trả lời ngược |
|
||||
|---|---|---|---|---|---|
|
||||
| `OQ-026` | `TCO §3.2` tính compute ECS Fargate P2 là 1 dòng "monolith" gộp — có đúng là 2 ECS service riêng (Nhóm Giao dịch/Nhóm Hỗ trợ, như `ASR-001`/`ASR-014`/`OPT §3` mô tả) hay chỉ 1 ECS service duy nhất chưa tách nhóm? | Tech Lead + Ops/SRE | 2026-09-15 | §7 deployment view; `ADR-012`; khả năng đáp ứng `DRV-04` (scale-out độc lập Catalog/Cart&Order) | Nếu là 1 service duy nhất: mất khả năng scale riêng Nhóm Giao dịch khi flash sale — phải sửa `TCO` (thêm chi phí tách thành 2 service) hoặc chấp nhận scale chung (giảm điểm tiêu chí "Đáp ứng DRV Must" đã chấm P2=4 ở `OPT §4`, cần chấm lại) |
|
||||
| `OQ-027` | Identity & Access nên thuộc Nhóm Giao dịch (theo suy luận `ASM-22` từ `ASR-010`/`011`) hay là một nhóm triển khai riêng/thuộc Nhóm Hỗ trợ? `OPT §3` không nói rõ vị trí của Identity trong 2 nhóm ECS đề xuất. | Tech Lead | 2026-09-15 | `CMP-02`, §4.1 cột "Nhóm triển khai", §7 deployment view, `ADR-012` | Nếu Identity thuộc Nhóm Hỗ trợ: giảm mức độ cô lập HA/DR của `ASR-010` (Identity chung nhóm scale với các module ít quan trọng hơn) — cần đánh giá lại RPO/RTO ở hoạt động `inf` |
|
||||
|
||||
**Nhắc:** cộng với các `OQ` còn mở ảnh hưởng trực tiếp `SAD` — `OQ-010` (số đội thật, chặn
|
||||
`ASR-014`/`ADR-012`), `OQ-012` (thời điểm `POC-01`, chặn `ADR-005`), `OQ-007` (đại diện Pháp
|
||||
chế, chặn `ADR-008`), `OQ-022` (lịch diễn tập DR, điều kiện tiên quyết AG2), `OQ-024`/`OQ-025`
|
||||
(MFA Admin, phạm vi i18n — đã chốt TẠM, giữ mở) — xem sổ đầy đủ `00-index/OQ_e-commerce.md`.
|
||||
|
||||
**Nhắc AG2:** cần **Tech Lead + Security + Ops/SRE ký** — còn xa vì `ICD`/`DAT`/`SEC`/`INF`/
|
||||
`FAIL` (hoạt động 4–8) và toàn bộ `ADR-001…012` (hoạt động 9) chưa chạy/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 `SAD`, tự chấm sớm)*
|
||||
|
||||
| # | Tiêu chí | ☐/✅ | Ghi chú |
|
||||
|---|---|---|---|
|
||||
| — | `ASR` liệt kê yêu cầu định hình kiến trúc | ✅ *(đã đạt ở hoạt động `asr` trước)* | Xem `ASR_e-commerce_v1.0.md` |
|
||||
| — | `QAS` — mọi NFR đã lượng hoá | ✅ *(đã đạt ở hoạt động `qas` trước)* | Xem `QAS_e-commerce_v1.0.md` |
|
||||
| 1 | `SAD` có sơ đồ C4 mức Context và Container, có deployment view, mỗi `CMP-nn` ghi rõ trách nhiệm | ✅ | §3 (Context), §4 (Container + `CMP-01…15`), §5 (Component — Cart&Order), §7 (Deployment) |
|
||||
| 2 | `ADR-nnn` tồn tại cho mọi quyết định đạt ngưỡng radar | ☐ | **Chưa viết `ADR` nào** — đúng theo yêu cầu điều phối; 12 chỗ chờ đã đánh dấu ở §8 với radar ước lượng kế thừa từ `ASR` |
|
||||
| — | `ICD`/`DAT`/`SEC`/`INF`/`FAIL` | ☐ | Chưa tới — hoạt động 4–8. Đã để lại ứng viên: `IF-nnn` (§4.1, §6.3), thực thể dữ liệu (§4.1 cột "Dữ liệu sở hữu"), phụ thuộc cần `FAIL` (§6.3) |
|
||||
| — | `sa-conformance` báo coverage `ASR → ADR/CMP` ≥ 100% | 🟡 Một phần | `ASR → CMP` đạt 15/15 (§4.3); `ASR → ADR` vẫn 0/12 vì chưa viết `ADR` nào — kỳ vọng đúng lúc này, sẽ chặn AG2 thật nếu vẫn 0/12 khi hoạt động `adr` chạy xong |
|
||||
|
||||
**Kết luận tự chấm (riêng phần `SAD`):** Hoạt động `sad` hoàn tất đúng phạm vi được giao — C4 đủ
|
||||
3 mức (Context/Container/Component cho phần phức tạp nhất), deployment view đối chiếu `TCO` (1
|
||||
điểm lệch đã ghi `OQ-026`, không tự sửa), `CMP`/ma trận `ASR×CMP` đủ 15/15, không `CMP` mồ côi.
|
||||
AG2 **còn xa** vì 5/9 hoạt động khác của GĐ2 (`icd`/`dat`/`sec`/`inf`/`fail`) và hoạt động `adr`
|
||||
(viết 12 `ADR` đã đánh dấu) chưa chạy — đây là tiến độ kỳ vọng, không phải lỗi.
|
||||
|
||||
### ② Checklist D1–D12 *(`design-rules.md`)*
|
||||
|
||||
| # | Mục | ☐/✅ | Ghi chú |
|
||||
|---|---|---|---|
|
||||
| D1 | Một ADR một quyết định | N/A | Tài liệu này không viết `ADR` — chỉ đánh dấu 12 chỗ chờ, mỗi chỗ đã tách đúng 1 quyết định (kế thừa từ `ASR §B2`) |
|
||||
| D2 | Không NFR định tính; đủ 4 câu | N/A | `SAD` không phải `QAS` — mọi số liệu (deployment §7) tham chiếu đúng `TCO`/`QAS` đã lượng hoá, không tự đặt số mới |
|
||||
| D3 | Nêu phương án bị loại + lý do gắn `CON`/`QAS` | ✅ *(kế thừa)* | §2 tham chiếu `OPT §5` (P1/P3/P4 đã loại); không lặp lại nội dung, chỉ dẫn |
|
||||
| D4 | Sơ đồ khai báo mức + legend | ✅ | §3/§4/§5/§7 mỗi sơ đồ đều khai báo mức C4 (Context/Container/Component/Deployment) + có legend, không trộn mức |
|
||||
| D5 | Interface có chủ/contract | 🟡 Một phần | §4.1/§6.3 đã ghi 17 `IF-nnn` ứng viên *(sửa từ "22" ở v1.2 — đếm nhầm, xem `OQ-029`)* với hai đầu + giao thức + sync/async, nhưng "ai sở hữu contract"/"đường dẫn contract thật"/"versioning policy" chưa chốt — đúng phạm vi, để hoạt động `icd` (hoạt động 4) |
|
||||
| D6 | Phụ thuộc ngoài process có timeout/retry | 🟡 Một phần | §6.3 liệt kê đủ 13 phụ thuộc vượt ranh giới process, nhưng timeout/retry/idempotent đầy đủ theo 4 câu hỏi `D6` thuộc hoạt động `fail` (hoạt động 8), chưa chạy |
|
||||
| D7 | Một chủ sở hữu dữ liệu | ✅ *(ở mức khối)* | §4.1 mỗi `CMP` ghi đúng 1 tập thực thể sở hữu, không trùng lặp giữa các `CMP`; chi tiết consistency/retention để `DAT` (hoạt động 5) |
|
||||
| D8 | Ràng buộc có FIT hoặc nhãn khuyến nghị | N/A | Chưa tới `AGD`/`FIT` (GĐ3) |
|
||||
| D9 | Con số hạ tầng quy ra tiền + nguồn; `INF` khớp `TCO` | 🟡 Một phần | §7 dùng đúng số của `TCO §3.2` (có nguồn); phát hiện 1 điểm lệch mức chi tiết (ECS gộp vs tách nhóm) — ghi `OQ-026`, không tự đổi số, đúng theo `D9` "lệch thì TCO sai hoặc INF sai, không có khả năng thứ ba" (ở đây là SAD/TCO cần làm rõ mức chi tiết, chưa hẳn là sai) |
|
||||
| D10 | Không quyết định thay người có thẩm quyền | ✅ | `ASM-22`/`OQ-027` (vị trí Identity) và `OQ-026` (khớp TCO) đều trình dưới dạng câu hỏi kèm hệ quả, không tự quyết; `ADR-008` (PII) tiếp tục ghi rõ phủ quyết thuộc Security/Legal |
|
||||
| D11 | Có mục "Ngoài phạm vi" + `ASM-nn` | ✅ | §10 đầy đủ — `ASM-22/23` mới, có cách xác minh/hệ quả; "Ngoài phạm vi" liệt kê rõ OpenSearch/OAuth/subnet chi tiết chưa làm |
|
||||
| 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
|
||||
|
||||
| `BA` | Nội dung | `SA` tương ứng | Khớp? | Hành động |
|
||||
|---|---|---|---|---|
|
||||
| `PROCESS_CartCheckout` B1–B9 | Luồng checkout, tách đơn, chờ webhook | §6.1/§6.2 (sequence diagram) | ✅ | Không lệch — SAD hiện thực hoá đúng thứ tự bước đã có ở BA, thêm chi tiết component/hạ tầng |
|
||||
| `IMPACT_CartCheckout` §1.5 | Tích hợp VNPay/Momo (🔴), GHN/GHTK (🟠), Catalog nội bộ (🟠), Promotion&Loyalty nội bộ (🟠) | §3 Context (4 hệ ngoài bắt buộc) + §4 Container (mũi tên 5, 11, 12, 13) | ✅ | Không lệch — mọi điểm tích hợp BA nêu đều có mặt ở Container/Context |
|
||||
| `IMPACT_CartCheckout` §1.5 câu hỏi mới (Promotion&Loyalty lỗi thì bỏ qua hay chặn checkout) | Chưa chốt ở BA | §6.1 bảng bước "Áp dụng coupon/điểm" ghi "chưa chốt hành vi" | 🟡 Một phần | **BA cập nhật `IMPACT_CartCheckout` §6** khi có câu trả lời — SAD đã phản ánh đúng trạng thái "chưa chốt", không tự giả định |
|
||||
| `API_US002-003` (BA đề xuất) | 3 endpoint `GET/PATCH/DELETE /v1/cart*`, quy ước `id` dạng string, `Idempotency-Key` cho ghi | §9 Mối quan tâm xuyên suốt (số lớn, idempotency); §4.1 `CMP-04` sở hữu `Cart`/`CartItem` | ✅ | Không lệch — `ICD` (hoạt động 4) sẽ là nơi xác nhận chính thức theo `artifact-map.md §7` ("`ICD` thắng `API`") |
|
||||
| `docs/sections/03-kien-truc.md` §3.1 | ~10 microservices (P1, đã loại) | §2/§4 — modular monolith P2, **không** kế thừa số lượng/kiểu service của P1 | ✅ Đúng yêu cầu | Chỉ tái dùng danh sách 9 domain module + 5 tích hợp ngoài, không tái dùng kiểu kiến trúc — đúng ghi chú người duyệt |
|
||||
|
||||
### ④ Danh sách `OQ` mở kèm người phải trả lời, chặn gì
|
||||
|
||||
Xem §11 (`OQ-026`, `OQ-027` mới) cộng các `OQ` còn mở từ `CTX`/`OPT`/`TCO`/`ARISK`/`QAS`/`ASR` —
|
||||
sổ đầy đủ tại `00-index/OQ_e-commerce.md`. Ba câu quan trọng nhất cho AG2: **`OQ-012`** (`POC-01`
|
||||
chặn `ADR-005`), **`OQ-022`** (diễn tập DR, điều kiện tiên quyết AG2), **`OQ-007`** (đại diện
|
||||
Pháp chế, chặn `ADR-008`).
|
||||
|
||||
**Nhắc:** AG2 cần **Tech Lead + Security + Ops/SRE ký** — còn xa. Hoạt động kế tiếp có thể chạy
|
||||
song song: `icd` (dùng 17 `IF-nnn` ứng viên ở §4.1/§6.3, sửa từ "22" ở v1.2 — xem `OQ-029`), `dat` (dùng bảng "Dữ liệu sở hữu" ở
|
||||
§4.1), `sec` (dùng §9 mô hình xác thực/phân quyền sơ bộ), `inf` (dùng §7 deployment view, phải
|
||||
giải quyết `OQ-026` trước khi chốt), `fail` (dùng §6.3 danh sách phụ thuộc).
|
||||
Reference in New Issue
Block a user