# 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).