Files
Canhchimlac 343ad8bbbc save
2026-09-15 16:02:30 +07:00

75 KiB
Raw Permalink Blame History

DAT — Data Architecture — e-commerce

Version 1.1
Date 2026-09-15
Author SA (skill sa-2-architecture, chế độ go, hoạt động dat)
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 bảng ownership 15 CMP (§1), mô hình Order/OrderSeller/OrderItem + payment_init_status (ADR-013, §2), snapshot giá/sellerName, idempotency store (§4.2), PITR RPO ≤15 phút (§9). Chấp nhận TẠM (🔴): ASM-35 (1 Order = 1 Payment) — OQ-043 giữ nguyên mở; chọn Transactional Outbox cho OQ-044 — yêu cầu SA viết ADR-014 (Proposed) ở lượt hoạt động adr kế tiếp, OQ-044 giữ mở tới khi có ADR; chọn phương án (a) — mỗi module tự ghi audit_log riêng cho OQ-047, không thêm CMP-16; ngưỡng job quét Order kẹt 5 phút cho OQ-042; cơ chế FE polling cho OQ-041 — cả bốn OQ-041/042/044/047 giữ nguyên mở, chờ Tech Lead thật xác nhận. OQ-045/OQ-046 giữ nguyên mở, không có hướng TẠM. §5 (phân loại PII/retention/whitelist chia sẻ seller) CHƯA CÓ HIỆU LỰC — chờ đại diện Pháp chế/Bảo mật phủ quyết (OQ-007), không nằm trong phạm vi duyệt lần này. Ghi thêm DEC-25. Security/Legal: — (chưa ký; §5 chặn hoàn toàn tới khi có người, OQ-007) · Ops/SRE: — (chưa ký). OQ-004 (tính hợp lệ ký thay) vẫn mở. Confidence giữ nguyên 🔴 — duyệt từng phần không phải bằng chứng nguồn mới. Status giữ 🟡 Draft — AG2 chưa đủ ba chữ ký thật/hợp lệ.
Source 02-architecture/SAD_e-commerce_v1.0.md v1.3 §4.1 (bảng CMP-nn, cột "Dữ liệu sở hữu"), §6.1/§6.3, §7 · 02-architecture/ICD_e-commerce_v1.0.md v1.0 §3.1.1, §3.7, §5 (denormalize sellerName, unitPriceSnapshotVnd) · 02-architecture/FAIL_e-commerce_v1.0.md v1.1 §1.2, §4, §7, §9 (khoảng trống outbox, OQ-040/042) · 02-architecture/QAS_e-commerce_v1.0.md QAS-003/004/006/008/011/014 · 02-architecture/ASR_e-commerce_v1.0.md ASR-002/003/006/008 · 02-architecture/adr/ADR-002_*.md, ADR-003_*.md, ADR-004_*.md, ADR-005_*.md, ADR-006_*.md, ADR-007_*.md, ADR-008_*.md, ADR-009_*.md, ADR-011_*.md, ADR-013_*.md, ADR-014_*.md · 00-index/OQ_e-commerce.md v1.20 · 00-index/DEC_e-commerce.md v1.21 · 01-context/TCO_e-commerce_v1.0.md §3.2 · ba-output/e-commerce/02-analysis/BR_CartCheckout_v1.0.md §4 (ERD khái niệm), §3 (vòng đời) · ba-output/e-commerce/02-analysis/RBAC_CartCheckout_v1.0.md §4 (dữ liệu nhạy cảm) · ba-output/e-commerce/03-specification/SRS_US002-003_v1.0.md · e-commerce/docs/sections/05-thiet-ke-du-lieu.md (tham khảo P1 — database-per-service, Kafka/MSK; không kế thừa kiểu kiến trúc đó, chỉ tham khảo tên bảng/cột và số retention đề xuất)
Scope Toàn sàn e-commerce theo P2 (SAD v1.3) — kiến trúc dữ liệu + ownership cho toàn bộ 15 CMP-01…15. Chi tiết nhất: Cart & Order (CMP-04), Payment (CMP-11/CMP-14), và mọi thực thể chứa PII (CMP-02 Identity, CMP-04 địa chỉ giao hàng, CMP-05 KYC seller). Các CMP còn lại (Catalog, Seller quản trị, Commission, Promotion, Review, Notification, Shipping) ở mức ownership + entity list, không đào sâu schema vật lý (thuộc dev). Đây là hoạt động 5/9 của sa-2-architecture.
Confidence 🔴 Giả định chưa xác minh — theo yêu cầu điều phối, tiếp nối Confidence 🔴 của SAD/ICD/FAIL/ASR/QAS. AG1 chưa ký thật; AG2 chưa tới hạn; ADR-005/ADR-006/ADR-009 (radar ≥8) chưa Accepted (chờ POC-01/POC-02/diễn tập DR); ADR-008 (PII) chặn hoàn toàn vì chưa có đại diện Pháp chế/Bảo mật (OQ-007). Mọi con số retention/index/pool trong tài liệu này là đề xuất SA, chưa đo thật.

Change Log

Version Date Người sửa Thay đổi ADR/DEC
1.0 2026-09-15 SA (qua skill sa-2-architecture, chế độ go, hoạt động dat) Bản đầu — hoạt động 5/9 của GĐ2. Bảng ownership D7 cho toàn bộ thực thể của 15 CMP (schema-per-module theo ADR-006, RDS Payment riêng theo ADR-002); mô hình Order/OrderSeller/OrderItem chi tiết theo ADR-003, bổ sung order.payment_init_status (PENDING_PAYMENT_INIT/PAYMENT_INIT_READY/PAYMENT_INIT_FAILED) theo ADR-013, cart_item.seller_name_snapshot/unit_price_snapshot theo ICD §3.1.1/§3.7 (OQ-033); phân loại dữ liệu PII/Payment/nghiệp vụ kèm đề xuất retention (chờ Legal, OQ-007) và whitelist chia sẻ seller theo ADR-008; chiến lược đọc/ghi (index cho QAS-003/004/006, read replica chỉ dùng cho Catalog, đánh giá cache nội dung Cart cho OQ-040); ranh giới transaction + đề xuất outbox pattern cho khoảng trống FAIL §7 (ADR ứng viên, chưa viết); idempotency store cho POST /v1/checkout; backup/PITR đối chiếu QAS-008/ADR-009; migration/versioning schema (đề xuất Flyway); dữ liệu đối soát (ReconciliationLog, ADR-004) và job dọn Order kẹt (đề xuất ngưỡng cho OQ-042). Đối chiếu docs/sections/05-thiet-ke-du-lieu.md (P1) — 5 khác biệt chính được ghi nhận. Thêm OQ-043…047, cập nhật OQ-007/040/042, ASM-35…38. Ghi DEC-24 (tiếp nối DEC-01…23, ngoại lệ gate tiếp tục GĐ2 hoạt động dat). Không sửa SAD/ICD/FAIL/ADR. Confidence 🔴 toàn bộ. DEC-24
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 bảng ownership 15 CMP, mô hình Order/OrderSeller/OrderItem + payment_init_status (ADR-013), snapshot giá/sellerName, idempotency store, PITR RPO ≤15 phút. Chấp nhận TẠM (🔴): ASM-35 (OQ-043 giữ mở); chọn Transactional Outbox cho OQ-044 — yêu cầu ADR-014 (Proposed) ở lượt adr kế tiếp; chọn phương án (a) mỗi module tự ghi audit_log cho OQ-047 — không thêm CMP-16; ngưỡng job quét 5 phút cho OQ-042; polling cho OQ-041 — cả bốn giữ nguyên mở. OQ-045/OQ-046 giữ mở. §5 (PII/retention/whitelist) CHƯA CÓ HIỆU LỰC — chờ Legal/Security phủ quyết (OQ-007). 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-25. DEC-25
1.1 2026-09-15 SA (qua skill sa-2-architecture, chế độ go, hoạt động adr) Chỉ link ADR, không đổi nội dung. ADR-014 (Transactional Outbox, Proposed) vừa được viết theo hướng TẠM đã chọn ở OQ-044/DEC-25 — thay các dòng "chưa viết"/"Ứng viên — chưa viết" ở §4.1 bằng đường dẫn adr/ADR-014_transactional-outbox-publish-su-kien.md. OQ-044 giữ nguyên mở (chờ Tech Lead thật xác nhận thiết kế relay, xem ADR-014 §3). Không sửa nội dung chuyên môn nào khác của DAT. Ghi DEC-31 (tiếp nối DEC-01…30). ADR-014, DEC-31

Sơ đồ thắng về quan hệ và luồng (ai sở hữu gì, ai đọc/ghi ai). Bảng/văn bản thắng về ràng buộc và con số (retention, index, TTL, RPO/RTO). Mâu thuẫn ngoài hai loại trên là lỗi tài liệu, phải sửa chứ không chọn bên (D12).


0. Ghi chú Preflight & ngoại lệ gate — bắt buộc đọc trước

AG1 vẫn chưa ký thật; AG2 (gate của chính GĐ2) chưa tới hạn. Theo SKILL.md, hoạt động 1 (QAS) → 2 (ASR) → 3 (SAD) đã hoàn tất và được duyệt từng phần (DEC-12/14/16); hoạt động 4 (ICD) và 8 (FAIL) đã chạy (DEC-18…23), ADR-001…013 đã viết (tất cả Proposed). Điều kiện đầu vào cho hoạt động 5 (DAT) đã đủ. Người dùng (vai điều phối dự án chạy thử) đã được cảnh báo lại và khẳng định muốn tiếp tục.

DEC-24 (SA) — Tiếp tục sa-2-architecture (hoạt động 5 — DAT) cho e-commerce trong khi AG1 chưa ký thật và AG2 chưa tới hạn — tiếp nối DEC-01…23. Quyết định: Thiết kế kiến trúc dữ liệu + ownership cho 15 CMP dựa trên SAD v1.3/ICD v1.0/FAIL v1.1/ADR-001…013 đã có, giữ Confidence 🔴 cho tới khi: (a) AG1/AG2 ký thật, (b) POC-02 (tải RDS gộp) chạy xong để xác nhận connection pool/index đề xuất, (c) đại diện Pháp chế/Bảo mật xác nhận phân loại PII và retention (OQ-007), (d) Tech Lead xác nhận cơ chế outbox/idempotency store đề xuất (OQ-044/045). Người quyết: Điều phối dự án (đại diện PO, dự án chạy thử). Radar (ước lượng cho việc tiếp tục dưới ngoại lệ): ~4 — chi phí đảo ngược thấp (đây là ghi tài liệu thiết kế, chưa có dòng code phụ thuộc) · bán kính ảnh hưởng: hoạt động sec/inf kế tiếp và toàn bộ dev BE dùng DAT làm nguồn sự thật ownership, nhưng bản thân việc ghi tài liệu dưới ngoại lệ thì nhỏ · có chạm QAS-003/004/006/008/011/014 Must trực tiếp (đang hiện thực hoá thành index/consistency/retention) nhưng chưa phải cam kết thi công · không ràng buộc dài hạn tự thân (văn bản DAT sửa được qua version mới) · không tranh cãi mới, tiếp nối tiền lệ DEC-11…23 → ghi DEC-nn, không cần ADR cho việc chạy dưới ngoại lệ. Hệ quả nếu không chấp nhận ngoại lệ: hoạt động sec/inf (hoạt động 6–7) không có ownership dữ liệu/chiến lược consistency để thiết kế threat model dữ liệu và backup/DR theo schema — chậm tiến độ chạy thử tương ứng thời gian xử lý các OQ đang mở, đặc biệt OQ-007 (chặn ADR-008).

🔴 Nhắc quan trọng: đây là hoạt động 5/9. SEC, INF (hoạt động 6–7) chưa được tạo. Tài liệu này là input trực tiếp cho cả hai — đặc biệt phân loại PII (§5) cho sec, và backup/RPO-RTO (§9) cho inf.


1. Nguyên tắc: mỗi thực thể có đúng một chủ

Quy tắc D7. Cột "Schema" theo ADR-006 (1 cụm RDS chính, schema-per-module) trừ Payment/ PaymentTransaction/PaymentReconciliationLog nằm ở RDS Payment hoàn toàn riêng biệt theo ADR-002 — không module nào khác được join/truy vấn SQL trực tiếp vào RDS Payment; mọi trao đổi chỉ qua IF-006 (sync, khởi tạo), sự kiện PaymentConfirmed/PaymentInitReady/ PaymentInitFailed (async), hoặc job đối soát nội bộ Payment.

1.1 Nhóm Giao dịch — CMP-02 Identity & Access (schema identity)

Thực thể SoT Bản sao ở đâu Cập nhật bằng cơ chế gì Trễ tối đa Lệch quá thì sao
user_account CMP-02 Cache JWT claims đã xác thực trong Redis (CMP-15) Ghi tại lúc đăng nhập/refresh token TTL access token (đề xuất 15-60 phút, ICD §1 mục 9) Token hết hạn tự nhiên — không phải "lệch", là thiết kế
customer_profile, customer_address CMP-02 Không có bản sao RDS; cart_item.seller_name_snapshot/checkout copy tên người nhận vào order_seller là snapshot một chiều, không phải bản sao đồng bộ Snapshot tại thời điểm checkout (không cập nhật ngược khi khách đổi địa chỉ sau đó) N/A — snapshot cố ý, không phải cache Không áp dụng — đơn đã tạo giữ nguyên địa chỉ tại thời điểm đặt hàng (đúng thông lệ thương mại điện tử)
oauth_identity, mfa_device CMP-02 Không có — — —
Session (Guest X-Guest-Session-Id, ownership cache) CMP-15 (Redis) — đây là SoT của session, không phải read model vì session không có bản ghi RDS song song Không — TTL 30 ngày không hoạt động (ICD §1 mục 10) Hết TTL → Guest mất phiên, phải tạo giỏ mới (đúng thiết kế BR-CART §3)

1.2 Nhóm Giao dịch — CMP-03 Catalog & Inventory (schema catalog)

Thực thể SoT Bản sao ở đâu Cập nhật bằng cơ chế gì Trễ tối đa Lệch quá thì sao
category, category_i18n, product, product_i18n CMP-03 Chỉ mục tìm kiếm — hoãn dùng OpenSearch ở P2 MVP (SAD §10), dùng Postgres full-text search trực tiếp trên schema catalog N/A (không có read model phái sinh ở MVP) N/A N/A
product_variant (giá price_amount) CMP-03 cart_item.unit_price_snapshot, order_item.unit_price_snapshot (snapshot một chiều, không đồng bộ ngược) Snapshot lúc thêm giỏ/lúc đặt hàng N/A — cố ý đóng băng Khách thấy priceChanged=true ở GET /v1/cart (ICD §3.1.1) nếu giá hiện tại khác snapshot — không tự cập nhật unit_price_snapshot, chỉ hiển thị cảnh báo
inventory_stock (quantity_available, quantity_reserved) CMP-03 Không có bản sao — mọi kiểm tra/giữ tồn kho gọi trực tiếp IF-005 (in-process, ASR-006) N/A 0 (đọc trực tiếp SoT) N/A — đúng lý do không cache: tồn kho là dữ liệu cần chính xác tức thời (chống oversell, BR-CART-02)
wishlist_item, language, currency, exchange_rate CMP-03 Cache exchange_rate ở Redis, TTL 1 giờ (tham khảo docs/05 §5.3.1, chỉ hiển thị, không dùng để thanh toán) Batch job refresh 1 giờ Hiển thị quy đổi lệch tạm thời — chấp nhận vì không dùng để tính tiền thật

1.3 Nhóm Giao dịch — CMP-04 Cart & Order (+ Dispute) (schema cart_order) — chi tiết nhất

Thực thể SoT Bản sao ở đâu Cập nhật bằng cơ chế gì Trễ tối đa Lệch quá thì sao
cart, cart_item CMP-04 Không có bản sao RDS. Nội dung giỏ hiện không cache ở Redis (chỉ session/ownership cache) — xem đánh giá OQ-040 ở §7.3 — — QAS-003 không đạt khi RDS chậm và không có fallback (xem FAIL FM-06)
order (đơn cha) CMP-04 Không có — — —
order_seller, order_item, order_status_history CMP-04 commission_transaction.order_seller_id, shipment.order_seller_id, dispute.order_seller_id (FK logic, tiêu thụ qua sự kiện OrderPlaced/PaymentConfirmed, không SQL trực tiếp) Consume event OrderPlaced (per-seller, ADR-005) Fan-out lag ≤5 giây (QAS-005) Vượt 5 giây → cảnh báo lag hàng đợi (OQ-036, ứng viên inf)
return_request CMP-04 Không có — — —
dispute CMP-04 payout_hold.release_status (Commission & Payout) tiêu thụ trạng thái dispute qua sự kiện (chưa thiết kế tên sự kiện cụ thể — ứng viên module Quản lý đơn hàng, ngoài phạm vi US-002/003) Sự kiện (chưa đặt tên) Chưa chốt Chưa chốt — ngoài phạm vi module Giỏ hàng & Checkout, ghi nhận điểm nối cho module kế tiếp
outbox_event (mới, đề xuất — xem §4.1) CMP-04 Không — bảng nội bộ, không phải dữ liệu nghiệp vụ — — —
idempotency_key (mới, đề xuất — xem §4.2) CMP-04 Không — — —

1.4 Payment — CMP-11/CMP-14 (RDS Payment riêng, cô lập hoàn toàn theo ADR-002)

Thực thể SoT Bản sao ở đâu Cập nhật bằng cơ chế gì Trễ tối đa Lệch quá thì sao
payment CMP-11 order.payment_init_status (Cart & Order, schema cart_order) là read model tối thiểu — chỉ phản ánh 1 trong 4 trạng thái sơ khởi (not_applicable/pending_payment_init/payment_init_ready/payment_init_failed), không phải bản sao đầy đủ của payment Consume PaymentInitReady/PaymentInitFailed (ADR-013) Theo ADR-013 §3.1: ngưỡng UX "kẹt" 15 giây Quá 15 giây chưa cập nhật → coi là bất thường, xem job dọn ở §4.3
payment_transaction (mới, đề xuất — xem §1.4.1) CMP-11 Không — — —
payment_reconciliation_log CMP-11 Không — — —
outbox_event (bản riêng của Payment, khác bảng của CMP-04 — 2 DB khác nhau) CMP-11 Không — — —

1.4.1 Vì sao cần payment_transaction tách khỏi payment

payment là bản ghi theo Order (xem §2.2 — 1 Order có 0..1 payment). Nhưng ADR-013 cho phép khách thử lại khởi tạo thanh toán sau PAYMENT_INIT_FAILED (§3.3 của ADR-013), và mỗi lần thử là một lời gọi riêng tới VNPay/Momo với gateway_transaction_ref riêng (có thể). Nếu chỉ có 1 dòng payment, mỗi lần thử lại phải ghi đè gateway_transaction_ref cũ — mất dấu vết đối soát các lần thử thất bại trước đó (vi phạm BR-CART-06/ADR-004 — "bản ghi thanh toán không bao giờ bị xoá"). payment_transaction ghi mỗi lần gọi gateway (init hoặc webhook xác nhận) như một dòng riêng, payment.status là trạng thái tổng hợp mới nhất suy ra từ dòng payment_transaction gần nhất thành công.

1.5 Nhóm Hỗ trợ — 6 CMP còn lại (schema-per-module trong cùng RDS chính, ADR-006)

CMP Schema Thực thể chính SoT Đối chiếu docs/05 (P1)
CMP-05 Seller Management seller seller, kyc_document, seller_bank_account CMP-05 Giữ nguyên tên bảng/cột docs/05 §5.2.5 — chỉ đổi database-per-service → schema-per-module
CMP-06 Commission & Payout commission commission_rule (gồm hold_days), commission_transaction, payout, payout_hold CMP-06 Giữ nguyên docs/05 §5.2.6, kể cả trạng thái payout_hold.release_status (holding/released/disputed_frozen/reversed)
CMP-07 Promotion & Loyalty promotion promotion, promotion_usage, loyalty_account, loyalty_transaction, membership_tier CMP-07 Giữ nguyên docs/05 §5.2.7
CMP-08 Review review review CMP-08 Giữ nguyên docs/05 §5.2.8
CMP-09 Notification notification notification_log, template CMP-09 Giữ nguyên docs/05 §5.2.9 (thêm bảng template — không có trong docs/05, do SAD §4.1 liệt kê CMP-09 sở hữu "Template")
CMP-10 Shipping & Fulfillment shipping shipment, shipment_event CMP-10 Giữ nguyên docs/05 §5.2.10

Các module này không thuộc phạm vi "chi tiết nhất" của ghi chú người duyệt — chỉ xác nhận ownership + tên bảng kế thừa từ docs/05 (điều chỉnh sang schema-per-module). Schema chi tiết đầy đủ (kiểu dữ liệu, index) thuộc dev khi module đó tới lượt thiết kế chi tiết ở GĐ2 kế tiếp.

1.6 Hạ tầng dữ liệu dùng chung

Hạ tầng Vai trò Ai sở hữu Dữ liệu tồn tại bao lâu
CMP-13 RDS chính Physical host cho 8 schema (identity/catalog/cart_order/seller/commission/promotion/review/notification/shipping) Ops/DBA Theo backup/PITR §9
CMP-14 RDS Payment Physical host riêng cho schema payment Ops/DBA (quyền tách biệt hoàn toàn, ADR-002) Theo backup/PITR §9
CMP-15 Redis Cache session/ownership (hiện có); nội dung Cart (đề xuất, chưa chốt — OQ-040) Ops/SRE (hạ tầng) + module tương ứng (key schema) TTL theo loại key (§1.1, §7.3)
CMP-12 Message Backbone (SQS FIFO + EventBridge) Transit, không phải kho dữ liệu bền vững Platform/SRE DLQ giữ 14 ngày (đề xuất TẠM, OQ-036)
S3 + CloudFront (SAD §4) Ảnh sản phẩm (public), KYC documents (private) Ops/SRE + CMP-05/CMP-03 Xem §6

🔴 15/15 CMP đã có bảng ownership ở trên — không CMP mồ côi dữ liệu, không thực thể nào có hai chủ. CMP-01 (ALB) và CMP-12 (Message Backbone) không sở hữu dữ liệu bền vững (đúng theo SAD §4.1 "không" ở cột dữ liệu sở hữu).


2. Mô hình dữ liệu mức khái niệm

Thực thể và quan hệ, chưa phải schema vật lý. Chi tiết nhất: Cart & Order + Payment.

2.1 ERD — Cart & Order + Payment (chi tiết nhất, theo yêu cầu)

erDiagram
    CART ||--o{ CART_ITEM : contains
    ORDER ||--o{ ORDER_SELLER : "splits_into (ADR-003)"
    ORDER ||--o| PAYMENT : "paid_by (1 payment / order — xem OQ-043)"
    ORDER_SELLER ||--o{ ORDER_ITEM : contains
    ORDER_SELLER ||--o{ ORDER_STATUS_HISTORY : tracks
    ORDER_SELLER ||--o{ RETURN_REQUEST : may_have
    ORDER_SELLER ||--o{ DISPUTE : may_have
    PAYMENT ||--o{ PAYMENT_TRANSACTION : "mỗi lần gọi gateway"
    PAYMENT ||--o{ PAYMENT_RECONCILIATION_LOG : reconciled_by

    CART {
        uuid id PK
        uuid customer_id FK "logic, nullable — Guest"
        string session_id "dùng khi Guest"
        enum status "active/converted/abandoned — BR-CART §3"
    }
    CART_ITEM {
        uuid id PK
        uuid cart_id FK
        uuid product_variant_id FK "logic → catalog"
        uuid seller_id FK "logic → seller"
        string seller_name_snapshot "MỚI — ICD §3.1.1/§3.7, OQ-033 chốt TẠM"
        int quantity
        numeric unit_price_snapshot "VND, snapshot lúc thêm giỏ"
    }
    ORDER {
        uuid id PK
        uuid customer_id FK "logic, nullable — Guest checkout"
        string order_number "khoá nghiệp vụ"
        numeric total_amount "= Σ order_seller.subtotal_amount"
        enum payment_init_status "MỚI — ADR-013: not_applicable/pending_payment_init/payment_init_ready/payment_init_failed"
        string idempotency_key "khoá gốc của POST /v1/checkout, ADR-004/013"
        timestamp placed_at
    }
    ORDER_SELLER {
        uuid id PK
        uuid order_id FK
        uuid seller_id FK "logic → seller"
        string sub_order_number "khoá nghiệp vụ"
        numeric subtotal_amount
        enum status "pending/confirmed/cancelled — BR-CART §3 (đoạn khởi tạo)"
    }
    ORDER_ITEM {
        uuid id PK
        uuid order_seller_id FK
        uuid product_variant_id FK "logic → catalog"
        string product_name_snapshot
        int quantity
        numeric unit_price_snapshot "VND, snapshot lúc đặt hàng — có thể khác cart_item nếu giá đổi giữa 2 mốc"
    }
    ORDER_STATUS_HISTORY {
        bigint id PK
        uuid order_seller_id FK
        string status
        timestamp changed_at
    }
    RETURN_REQUEST {
        uuid id PK
        uuid order_seller_id FK
        string status
    }
    DISPUTE {
        uuid id PK
        uuid order_seller_id FK
        uuid assigned_csr_id FK "logic → identity"
        string status
    }
    PAYMENT {
        uuid id PK
        uuid order_id "logic — KHÔNG FK vật lý, khác RDS (ADR-002)"
        enum method "vnpay/momo/cod"
        numeric amount
        enum status "pending_init/success/failed/refunded"
        timestamp paid_at
    }
    PAYMENT_TRANSACTION {
        uuid id PK
        uuid payment_id FK
        enum direction "init/webhook"
        string gateway_transaction_ref
        jsonb gateway_response_snapshot "không chứa số thẻ/CVV — BR-CART-05"
        string status
        timestamp created_at
    }
    PAYMENT_RECONCILIATION_LOG {
        uuid id PK
        uuid payment_id FK
        string gateway_status
        string discrepancy_note
        timestamp reconciled_at
    }

Legend: ||--o{ một-nhiều · ||--o| một-không hoặc một · đường nối PAYMENT↔ORDER là FK logic (khác RDS, không ràng buộc vật lý được — kiểm chứng bằng IF-006/sự kiện, không bằng JOIN SQL).

🔴 Khác biệt so với BR_CartCheckout §4 (BA): BA chưa biết ADR-013 khi viết ERD — DAT bổ sung order.payment_init_status và order.idempotency_key, cart_item.seller_name_snapshot. Đây là bổ sung kỹ thuật, không đổi mô hình nghiệp vụ BA đã chốt (Order/OrderSeller/ OrderItem giữ nguyên cấu trúc cha-con). Không sửa BR_CartCheckout — ghi nhận ở §12 (đối chiếu BA).

2.2 Bảng thực thể chi tiết (Cart & Order + Payment)

Thực thể Ý nghĩa nghiệp vụ Khoá nghiệp vụ Ước lượng số bản ghi (năm 1 / năm 3) Tăng trưởng Nguồn
cart Giỏ hàng (id kỹ thuật) 🔴 Chưa có số — TCO §2 chỉ có concurrent user (2.000/10.000), không có số giỏ hàng tuyệt đối Theo QAS-009 (×3/2 năm) BR_CartCheckout §4.1
cart_item Dòng sản phẩm trong giỏ (cart_id, product_variant_id) 🔴 Chưa có số Theo cart BR_CartCheckout §4.1
order/order_seller/order_item Đơn hàng cha/con/dòng order_number/sub_order_number Kịch bản A: ~400 đơn/giờ đỉnh · B: ~15.000 đơn/giờ đỉnh (QAS-002 nguồn) — chưa có số/ngày hay /năm tuyệt đối, Confidence 🔴 Theo QAS-009 QAS-002, TCO §2
payment Giao dịch thanh toán (1/order) — ≈ bằng số order (trừ đơn hủy trước khi khởi tạo thanh toán) Theo order Suy từ order
payment_transaction Mỗi lần gọi gateway (init/webhook) — ≥1× số payment (có thể nhiều nếu khách thử lại — ADR-013 §3.3) Theo payment × tỷ lệ thử lại (chưa đo — ADR-013 §7) §1.4.1
payment_reconciliation_log Log đối soát định kỳ — Số payment × số chu kỳ đối soát chạy trong đời payment (đề xuất ≤15 phút/lần, QAS-014) — có thể lớn hơn nhiều lần số payment, cần retention ngắn (§6) Cao — cần partition theo tháng (tham khảo docs/05 §5.3.3) ADR-004

🔴 TCO §2/QAS-009 chỉ có số concurrent user và đơn/giờ đỉnh, không có ước lượng số bản ghi tuyệt đối theo năm — mục "Ước lượng số bản ghi" của template không điền được đầy đủ. Không bịa con số — đây là khoảng trống thật, ghi OQ-047 (mới, §11).

2.3 Entity list rút gọn — các module còn lại

Không lặp lại docs/05 §5.2 — chỉ liệt kê để đối chiếu ownership (đã có ở §1.5), tên bảng/cột đầy đủ xem tài liệu tham khảo đó (điều chỉnh database-per-service → schema-per-module).


3. Chọn công nghệ lưu trữ

Kho Loại Chứa gì Vì sao loại này ADR
RDS PostgreSQL Multi-AZ chính Quan hệ 8 schema (Identity, Catalog, Cart&Order, Seller, Commission, Promotion, Review, Notification, Shipping) Gắn QAS-006 (p95 write ≤300ms, read ≤200ms, tải gộp); Conway (CON-05) — 1 instance thay vì ~9-10 ADR-006
RDS PostgreSQL Multi-AZ riêng Quan hệ Schema payment (payment, payment_transaction, payment_reconciliation_log) Gắn ASR-002/QAS-011 — cô lập PCI-DSS SAQ A ADR-002
ElastiCache Redis Khoá-giá trị Session, ownership cache (hiện có); nội dung Cart (đề xuất — §7.3) Gắn QAS-003/QAS-004/QAS-010 ADR-007
S3 + CloudFront Object storage Ảnh sản phẩm (public), KYC documents (private) Kế thừa SAD §4, không đổi —
Postgres full-text search (trong schema catalog) Tìm kiếm (tạm) Chỉ mục tìm kiếm sản phẩm SAD §10: hoãn OpenSearch ở P2 MVP, dùng FTS Postgres tới khi có bằng chứng tải cần OpenSearch (ngưỡng: traffic thật ≥ kịch bản B ×2, QAS-009) —
SQS FIFO + EventBridge Message queue Transit sự kiện OrderPlaced/PaymentConfirmed/PaymentInitRequested/PaymentInitReady/PaymentInitFailed Gắn QAS-005 ADR-005

Phương án bị loại (kế thừa từ OPT/ADR-001, không lặp lại chi tiết — quy tắc D3):

Loại Loại vì Xét lại khi
Database-per-service (mỗi CMP một RDS riêng, như docs/05 P1) Vi phạm Conway với năng lực team hiện tại (CON-05), tăng chi phí vận hành ~9-10 instance thay vì 2 POC-02 FAIL nghiêm trọng và team đủ lớn để vận hành nhiều DB (ADR-006 §4)
OpenSearch ngay từ đầu TCO §3.2/OPT §3 P2 hoãn chi phí này ở MVP Traffic thật ≥ kịch bản B ×2 chưa kiểm chứng (SAD §10)
Kafka/MSK thay SQS/EventBridge Đội chưa xác nhận kinh nghiệm production (CON-05, OQ-010) POC-01 FAIL nghiêm trọng (ADR-005 §4)

4. Consistency

Nhánh dữ liệu Mức nhất quán Trễ tối đa Vì sao chấp nhận được Ai chấp nhận ADR/QAS
Tạo Order/OrderSeller/OrderItem trong 1 lần checkout Mạnh (1 transaction ACID, schema cart_order) 0 ASR-003 — cấu trúc cha-con phải tạo trọn vẹn hoặc không tạo gì SA + Tech Lead ADR-003, QAS-002
order.payment_init_status phản ánh kết quả khởi tạo thanh toán online Eventual Ngưỡng UX 15 giây (ADR-013 §3.1); ngưỡng "kẹt" cần job dọn — đề xuất §4.3 Khách chấp nhận chờ ngắn để đổi lấy QAS-002 luôn đạt (ADR-013, đã chọn Lựa chọn B) Tech Lead + PO (đã chốt hướng, chờ ký thật) ADR-013, QAS-002
payment.status (Payment Service) ↔ trạng thái thật ở VNPay/Momo Eventual, có giới hạn thời gian bù bằng job đối soát ≤15 phút (QAS-014, đề xuất — OQ-021 chưa xác nhận) Không thể đảm bảo mạnh vì phụ thuộc bên thứ ba (ASR-004) — job đối soát bù là biện pháp bắt buộc, không phải "chấp nhận rủi ro" Tech Lead (kỹ thuật) — không phải quyết định nghiệp vụ, vì đây là ràng buộc vật lý (không kiểm soát được uptime đối tác) ADR-004, QAS-014
OrderSeller.status (Cart&Order) ← PaymentConfirmed (Payment) Eventual Fan-out lag ≤5 giây (QAS-005) Người dùng không cần thấy cập nhật tức thời sau khi đã thấy trang xác nhận đặt hàng PO (đã ngụ ý chấp nhận qua QAS-005) ADR-005
CommissionTransaction/NotificationLog/Review (eligibility)/Shipment ← OrderPlaced Eventual Fan-out lag ≤5 giây (QAS-005) + xử lý riêng từng consumer (chưa đo) Không nằm trên đường găng checkout; nghiệp vụ chấp nhận trễ vài giây tới vài phút PO ADR-005
inventory_stock.quantity_reserved khi checkout thất bại/hủy Mạnh trong phạm vi 1 transaction cho bước reserve; compensation bất đồng bộ khi PAYMENT_INIT_FAILED không được khách xử lý (job dọn, §4.3) giải phóng reserve Theo ngưỡng job dọn — đề xuất 5 phút (§4.3, OQ-042) BR-CART-02 yêu cầu không oversell — reserve phải mạnh; nhưng release khi hủy có thể trễ vài phút không gây oversell (chỉ tạm "khoá nhầm" tồn kho) Tech Lead ASR-006, BR-CART-02

🔴 "Eventual" không có con số trễ là câu nói suông (D2/template §4) — mọi dòng trên đều có con số hoặc tham chiếu tới OQ đang chờ con số (OQ-021 cho tần suất đối soát thật).

4.1 Giao dịch xuyên service — khoảng trống outbox (FAIL §7)

FAIL_e-commerce_v1.0.md §7 đã ghi nhận khoảng trống: nếu service chết sau COMMIT transaction tạo Order nhưng trước khi publish OrderPlaced/PaymentInitRequested thành công, sự kiện bị mất vĩnh viễn — không consumer nào (Commission, Promotion, Notification, Shipping, Payment) biết Order đó tồn tại. Đây là bài toán dual write kinh điển (ghi DB + gọi message queue không nguyên tử).

Hai phương án đã cân nhắc (quy tắc D3 — chưa viết ADR chính thức, xem cảnh báo dưới):

Phương án Mô tả Ưu Nhược
PA-1 — Job quét đối chiếu Job định kỳ (đề xuất mỗi 5 phút) quét order không có event tương ứng đã publish thành công (dựa cột đánh dấu event_published_at), publish lại Không cần bảng/hạ tầng mới Cần một cột đánh dấu đủ tin cậy; có race condition giữa "đang xử lý" và "đã mất" nếu không thiết kế cẩn thận; không tổng quát cho các module khác publish event sau này
PA-2 — Transactional Outbox (đề xuất SA) Ghi một dòng outbox_event trong cùng transaction DB với việc tạo Order/OrderSeller/OrderItem (cùng schema cart_order, cùng ACID). Một relay (poller nội bộ hoặc job định kỳ ngắn, đề xuất mỗi 1-2 giây) đọc outbox_event trạng thái pending, publish lên SQS/EventBridge, đánh dấu published khi thành công Đảm bảo tính nguyên tử thật sự giữa ghi DB và phát sự kiện (industry-standard, dùng được cho mọi module publish event sau này — Payment cũng dùng bảng outbox_event riêng trong RDS Payment của nó) Thêm bảng + một relay process cần giám sát (lag alerting); độ trễ publish tăng nhẹ (1-2 giây thay vì tức thời)

Đề xuất SA: PA-2 (Outbox pattern). Vì đây là quyết định thiết lập tiền lệ cho toàn hệ thống (mọi module publish event sau này sẽ dùng cùng cơ chế, không chỉ Cart & Order) — theo decision-radar.md §4 ("ngoại lệ tiền lệ"), ước lượng radar ~6/10 (đảo ngược trung bình=1 · bán kính: Cart&Order + Payment (2 CMP publish) + tiền lệ cho các module tương lai=1 · chạm QAS-005/gián tiếp DRV-08 (không mất giao dịch)=1 · ràng buộc trở thành chuẩn chung ≥1 năm=2 · chưa tranh cãi=0, +1 vì thiết lập tiền lệ áp dụng toàn hệ thống) → ADR bắt buộc — xem adr/ADR-014_transactional-outbox-publish-su-kien.md (Proposed, viết ở lượt hoạt động adr kế tiếp). OQ-044 giữ nguyên mở, chờ Tech Lead thật xác nhận thiết kế relay (số instance, HA) trước khi ADR-014 chuyển Accepted — xem ADR-014 §3.

Bù trừ khi lỗi giữa chừng (nếu PA-2 được chọn):

Bước lỗi Ai phát hiện Xử lý
Relay chết trước khi publish Alerting theo outbox_event tuổi > ngưỡng (đề xuất 1 phút, chưa xác nhận) chưa published Restart relay (nhiều instance, không đơn điểm lỗi) — outbox_event vẫn còn trong DB, không mất
Publish thành công nhưng đánh dấu published thất bại (crash giữa hai bước) Relay quét lại thấy pending dù đã publish Chấp nhận at-least-once — consumer đã có dedupe theo eventId (ICD §4), publish trùng không gây hiệu ứng phụ
outbox_event tồn đọng số lượng lớn (relay chậm hơn tốc độ ghi) CloudWatch metric số dòng pending Backpressure — chưa thiết kế cụ thể, ứng viên inf

Bảng theo template (saga/outbox/2PC/không có):

Luồng nghiệp vụ Cơ chế Bù trừ khi lỗi giữa chừng Ai phát hiện lệch ADR
Checkout → publish OrderPlaced/PaymentInitRequested Outbox Xem bảng trên Alerting lag outbox_event (inf, chưa thiết kế) ADR-014 (Proposed, OQ-044 giữ mở)
Payment Service → publish PaymentConfirmed/PaymentInitReady/PaymentInitFailed Outbox (bảng riêng trong RDS Payment) (cùng cơ chế) Tương tự Tương tự ADR-014
Webhook VNPay/Momo → cập nhật payment.status Không saga — xử lý đồng bộ trong 1 transaction schema payment, bù bằng job đối soát nếu webhook không tới (ADR-004) Job đối soát ≤15 phút phát hiện lệch, ghi payment_reconciliation_log, cảnh báo — không tự động sửa Job đối soát ADR-004
Checkout thất bại giữa chừng (VD IF-005 timeout trước bước ghi Order) Không có gì để bù — transaction chưa BEGIN/đã ROLLBACK, không có trạng thái nửa vời N/A N/A —

4.2 Idempotency store cho POST /v1/checkout

Theo ADR-004/ICD §1 mục 7 — Idempotency-Key bắt buộc cho POST /v1/checkout.

Thực thể Cột Ý nghĩa
idempotency_key (mới, schema cart_order) idempotency_key (UNIQUE) Giá trị header Idempotency-Key do client gửi
endpoint VD POST /v1/checkout — cho phép tái sử dụng bảng này cho các endpoint ghi khác sau này
request_hash Hash body request — phát hiện client gửi lại cùng key nhưng khác nội dung (lỗi client, phải từ chối 409, không âm thầm dùng response cũ)
response_snapshot (jsonb) Response đã trả lần đầu — trả lại nguyên vẹn nếu gọi lại trong TTL
status processing (đang xử lý, tránh race hai request đồng thời cùng key) / completed
expires_at Đề xuất TTL 48 giờ (đủ dài cho khách quay lại thử thanh toán trong ngày, đủ ngắn để không phình bảng vô hạn) — 🔴 chưa xác nhận Tech Lead

Webhook thanh toán KHÔNG dùng bảng này — dùng khoá nghiệp vụ tự nhiên payment_transaction.gateway_transaction_ref (UNIQUE constraint), đúng theo ICD §1 mục 7 (đối tác ngoài không tự đặt Idempotency-Key).

4.3 Job dọn Order kẹt ở PENDING_PAYMENT_INIT — đề xuất cho OQ-042

OQ-042 (00-index/OQ_e-commerce.md) hỏi ngưỡng thời gian giữ Order ở PENDING_PAYMENT_INIT trước khi coi là "kẹt". Đây là đề xuất của DAT, không tự quyết — Tech Lead xác nhận.

Đề xuất SA
Ngưỡng quét order.payment_init_status = pending_payment_init và order.placed_at cũ hơn 5 phút (gấp ~2× ngưỡng UX "kẹt" 15 giây × margin an toàn cho retry/hàng đợi chậm — không dùng chung ngưỡng 15 giây của UX vì đó là ngưỡng hiển thị cho khách, không phải ngưỡng hệ thống coi là thất bại vĩnh viễn)
Tần suất job Mỗi 5 phút (tham khảo mẫu tương tự docs/05 §5.2.6 job quét payout_hold)
Hành động khi phát hiện (1) Cập nhật order.payment_init_status = payment_init_failed (nếu chưa có sự kiện PaymentInitFailed nào tới — coi như mất sự kiện); (2) Giải phóng inventory_stock.quantity_reserved tương ứng (gọi IF-005 release, đối xứng với bước reserve ở checkout); (3) Ghi order_status_history; (4) Cảnh báo Ops nếu số lượng "kẹt" phát hiện trong 1 lần quét vượt ngưỡng bất thường (đề xuất >5 đơn/lần quét — chưa xác nhận)
Rủi ro ngưỡng quá ngắn Hủy nhầm Order mà VNPay/Momo chỉ đang xử lý chậm bất thường (chưa timeout thật ở phía Payment Service)
Rủi ro ngưỡng quá dài Order "ma" tồn đọng lâu, tồn kho reserve bị khoá không cần thiết, nhiễu báo cáo doanh số

🔴 Cập nhật OQ-042 trong sổ 00-index/OQ_e-commerce.md với đề xuất này (giữ nguyên mở, chờ Tech Lead xác nhận) — xem §11.


5. Phân loại dữ liệu & tuân thủ

🔴 ADR-008 (Security/Legal) chưa có người ký (OQ-007) — bảng dưới là đề xuất phân loại + retention của SA, không phải quyết định cuối. Phủ quyết thuộc Pháp chế/Bảo mật.

Nhóm dữ liệu Mức nhạy cảm Ví dụ trường Lưu ở đâu Mã hoá at-rest Che khi hiển thị Retention (đề xuất, chờ Legal) Cách xoá theo yêu cầu
Danh tính & liên hệ khách hàng PII user_account.email/phone, customer_profile.full_name/date_of_birth schema identity RDS KMS (mặc định) + mã hoá tầng ứng dụng cho mfa_device.secret_encrypted (khuyến nghị, sec xác nhận) Không che với chính chủ; không hiển thị cho seller Ẩn danh hoá trong 30 ngày kể từ yêu cầu xoá hợp lệ (NĐ13/2023), giữ order/payment liên quan ở dạng tách định danh (tham khảo docs/05 §5.3.6, assumption ASM-37) Ẩn danh hoá (anonymize), không xoá cứng bản ghi tài chính liên quan
Địa chỉ giao hàng PII customer_address.recipient_name/phone/address_line, snapshot trong order_seller lúc checkout schema identity (SoT) + snapshot trong cart_order (một chiều) RDS KMS Whitelist cho seller theo ADR-008 PA-2 (đề xuất, chờ Security/Legal): chỉ recipient_name/phone/address_line của OrderSeller tương ứng — không chia sẻ email, lịch sử mua hàng, hay địa chỉ của seller khác trong cùng Order Cùng nhóm với danh tính khách hàng ở trên Cùng cơ chế trên
Tên gian hàng (denormalize) Nội bộ (không PII) cart_item.seller_name_snapshot schema cart_order Không cần mã hoá riêng (dữ liệu công khai — tên gian hàng hiển thị công khai trên sàn) Không cần che Theo vòng đời cart (§6) Xoá cùng cart
KYC seller PII nhạy cảm kyc_document.file_url_s3 (ảnh CMND/giấy phép kinh doanh), seller.tax_code/business_license_number schema seller + S3 bucket riêng (private) S3 server-side encryption + RDS KMS; đề xuất mã hoá tầng ứng dụng cho object S3 (khuyến nghị sec xác nhận) Chỉ Admin/CSR được duyệt xem (RBAC của module Seller, ngoài phạm vi US-002/003) Tối thiểu 5 năm sau khi seller ngừng hoạt động (tham khảo docs/05 §5.3.6, assumption ASM-37, chờ Legal) Không xoá trong thời hạn lưu trữ pháp lý — chỉ ẩn khỏi truy cập vận hành thường ngày sau khi seller đóng
Thông tin tài khoản ngân hàng seller Payment seller_bank_account.account_number/account_holder_name schema seller Bắt buộc mã hoá tầng ứng dụng (không chỉ dựa KMS) — đề xuất, sec xác nhận Che một phần khi hiển thị (VD ****1234) — chi tiết thuộc sec Theo thời hạn hợp đồng seller + tối thiểu 10 năm sau giao dịch cuối (kế toán, tham khảo docs/05) Không xoá trong thời hạn kế toán
Dữ liệu thanh toán khách hàng Payment — KHÔNG lưu số thẻ/CVV (BR-CART-05, SAQ A) payment.amount, payment_transaction.gateway_transaction_ref, gateway_response_snapshot (đã lọc, không chứa thẻ) schema payment (RDS riêng, ADR-002) RDS KMS + mã hoá tầng ứng dụng cho gateway_transaction_ref (khuyến nghị) Chỉ hiển thị tham chiếu rút gọn cho khách, không hiển thị gateway_response_snapshot thô Tối thiểu 10 năm (chứng từ kế toán, tham khảo docs/05 §5.3.6, ASM-37) Không xoá — dữ liệu tài chính bắt buộc lưu theo luật kế toán
Dữ liệu nghiệp vụ công khai/nội bộ Công khai/nội bộ product, category, review, commission_rule Các schema tương ứng RDS KMS mặc định Không cần che Theo vòng đời nghiệp vụ (§6) Xoá thường theo yêu cầu quản trị (không liên quan NĐ13/2023)

5.1 Ràng buộc pháp lý

Ràng buộc pháp lý Nguồn Hệ quả kiến trúc
Dữ liệu cá nhân phải xác nhận nơi lưu trữ đáp ứng NĐ13/2023 CON-06, ASM-04 (chưa xác nhận), ADR-008 RDS/S3 đặt tại ap-southeast-1 — chưa được Legal xác nhận đủ (OQ-007); áp dụng cho cả backup/snapshot, không chỉ dữ liệu online (xem cảnh báo dưới)
PCI-DSS SAQ A — không lưu thẻ/CVV CON-06, BR-CART-05, ADR-002 Không trường nào trong bất kỳ schema nào ngoài payment được chứa dữ liệu thẻ; payment_transaction.gateway_response_snapshot phải được lọc trước khi ghi (loại bỏ trường thẻ nếu gateway trả về, dù không mong đợi)
Quyền được xoá (NĐ13/2023) CON-06 Ẩn danh hoá, không xoá cứng, cho dữ liệu có ràng buộc tài chính/kế toán song song (xem bảng §5)

🔴 Backup và log cũng chứa PII (design-rules.md D9/template §5) — snapshot PITR của schema identity/cart_order chứa toàn bộ PII chưa ẩn danh tại thời điểm backup; payment_transaction. gateway_response_snapshot trong backup cũng phải tuân cùng ràng buộc residency. Retention backup (§9) phải đối chiếu lại với retention dữ liệu ở bảng trên khi Legal xác nhận — hiện chưa đối chiếu được vì Legal chưa có (OQ-007).

5.2 Whitelist chia sẻ PII cho seller — hiện thực hoá ADR-008 PA-2

ADR-008 (Security/Legal, chưa ký) đề xuất whitelist recipient_name/phone/address_line. DAT hiện thực hoá thành cơ chế: order_seller (schema cart_order) chỉ lưu snapshot đúng 3 trường này của địa chỉ giao hàng liên quan tới OrderSeller đó — không lưu tham chiếu tới toàn bộ customer_address/user_account của khách. Bất kỳ API nào trả dữ liệu OrderSeller cho Seller Management (IF tương lai, ngoài phạm vi US-002/003) chỉ đọc 3 trường này, không JOIN ngược sang schema identity.

🔴 Đây là thiết kế hiện thực hoá đề xuất PA-2 của ADR-008 — không phải quyết định độc lập của DAT. Nếu Security/Legal từ chối PA-2 khi có người ký, thiết kế này phải sửa theo phương án được chọn (ADR-008 vẫn Proposed, chưa Accepted).


6. Vòng đời & lưu trữ dài hạn

Thực thể Dữ liệu nóng Chuyển sang lạnh sau Xoá sau Ai duyệt
cart (Guest) Redis/RDS, hoạt động — 7 ngày không hoạt động → abandoned (BR-CART §3, tham khảo docs/05 §5.3.1) Tech Lead (đã có tiền lệ tham khảo)
cart (Customer) RDS, hoạt động — 30 ngày không hoạt động → abandoned (tham khảo docs/05, BR-CART §3 chưa chốt số chính thức — OQ của BA) PO/Tech Lead
order/order_seller/order_item RDS, 12 tháng gần nhất Partition theo tháng (tham khảo docs/05 §5.3.3), archive sau 12 tháng sang storage rẻ hơn (đề xuất, chưa xác nhận) Không xoá — dữ liệu tài chính/pháp lý (10 năm, xem §5) Tech Lead + Kế toán
payment/payment_transaction/payment_reconciliation_log RDS Payment, 12 tháng gần nhất Partition theo tháng Không xoá trong 10 năm (§5) Tech Lead + Kế toán
outbox_event (cả hai schema) RDS, vài giờ gần nhất — Xoá sau 7 ngày kể từ published (đề xuất — không cần giữ lâu, chỉ phục vụ relay + debug ngắn hạn) Tech Lead
idempotency_key RDS — Xoá khi expires_at qua (đề xuất 48 giờ, §4.2) — job dọn định kỳ Tech Lead
notification_log, shipment_event RDS 90 ngày (tham khảo docs/05 §5.3.6) Archive lạnh hoặc xoá sau 90 ngày Ops
kyc_document (S3 + metadata) S3 versioning + cross-region replication — Tối thiểu 5 năm sau khi seller ngừng hoạt động (§5, ASM-37) Legal + PO

7. Hiệu năng dữ liệu

7.1 Chỉ mục cho QAS-003/QAS-004/QAS-006

Truy vấn quan trọng Tần suất Khối lượng quét Chỉ mục cần QAS
GET /v1/cart — lấy cart theo customer_id/session_id + cart_item theo cart_id Đọc nhiều (mỗi lần mở SCR-04) ≤50 dòng/giỏ (ASM-16, QAS §A3) index(cart.customer_id), index(cart.session_id), index(cart_item.cart_id) QAS-003
PATCH/DELETE /v1/cart/items/{id} Ghi đơn lẻ 1 dòng PK cart_item.id (đủ, không cần thêm) QAS-004
POST /v1/checkout — ghi order+N order_seller+N order_item Ghi theo tải đỉnh (QAS-002) N ≤ số seller trong giỏ (thường nhỏ) PK tự nhiên đủ; cần index(order.customer_id, placed_at DESC) cho truy vấn lịch sử đơn sau này QAS-002, QAS-006
Kiểm tra/giữ tồn kho (IF-005) Đọc+ghi trong mọi checkout 1 dòng/product_variant PK inventory_stock.variant_id (1-1, đã đủ) QAS-006
Job đối soát (payment_reconciliation_log) Theo chu kỳ (≤15 phút, QAS-014) Số payment đang pending_init/success gần đây index(payment.status, paid_at) QAS-014

7.2 Read replica

Quyết định
Có read replica không Có — nhưng chỉ tồn tại ở kịch bản B (SAD §7: "B: r6g.2xlarge + 1 read replica"; kịch bản A không có)
Route cái gì sang replica Đề xuất SA: Catalog & Inventory (đọc nhiều, phục vụ tìm kiếm/duyệt sản phẩm — không nằm trên đường găng ghi) route sang replica khi có (kịch bản B). Cart & Order KHÔNG route sang replica — GET /v1/cart cần đọc-ngay-sau-ghi (khách vừa PATCH xong phải thấy kết quả ngay), replica lag (ASM-36, chưa đo) có thể vi phạm tính đúng đắn cảm nhận được, rủi ro cao hơn lợi ích latency
Vì sao Gắn QAS-003/QAS-006 — Catalog chịu tải đọc gấp ~10× tải ghi (QAS-006 nguồn: "~150.000 truy vấn catalog/giờ so với ~15.000 đơn/giờ"), hưởng lợi rõ từ replica; Cart&Order tải đọc/ghi cân bằng hơn và nhạy cảm với độ tươi dữ liệu
ADR Không đạt ngưỡng ADR (radar ước lượng ~3: đảo ngược thấp, bán kính 1 module, không chạm QAS Must trực tiếp theo hướng tiêu cực, có thể đổi routing qua config) — ghi OQ-046 (§11), không cần ADR

7.3 Cache nội dung Cart — đánh giá cho OQ-040

OQ-040 (FAIL §4) hỏi: có nên thêm cache nội dung Cart/CartItem vào Redis để GET /v1/cart có fallback thật khi RDS chậm không? Đây là đánh giá của DAT, không tự quyết.

Phương án A — Không cache (giữ nguyên) Phương án B — Thêm cache nội dung Cart
Mô tả GET /v1/cart luôn đọc RDS; RDS chậm/lỗi → 503 (timeout 200ms theo FAIL FM-06) Cache-aside: ghi cache khi PATCH/DELETE/thêm giỏ (write-through), đọc cache trước, fallback RDS nếu miss; TTL đề xuất ngắn (5-10 phút) vì giá/tồn kho có thể đổi
Đạt QAS-003 khi RDS chậm ❌ Không — trả lỗi nhanh hơn, không phải trả đúng ✅ Có — miễn cache còn dữ liệu
Rủi ro dữ liệu cũ Không có (luôn đọc SoT) Giá/tồn kho hiển thị có thể lệch trong TTL — đã có cơ chế priceChanged (ICD §3.1.1) giảm nhẹ rủi ro giá, nhưng không giảm rủi ro hiển thị sai quantity nếu khách sửa giỏ ở tab khác trong TTL
Độ phức tạp thêm Không Cần thiết kế invalidation (write-through khi PATCH/DELETE), thêm 1 loại key Redis mới, thêm giám sát hit/miss ratio
Chi phí hạ tầng Không đổi Redis hiện tại (CMP-15) đã có sẵn — chi phí thêm chủ yếu là dung lượng bộ nhớ (nhỏ, giỏ hàng ≤50 dòng) — không cần instance Redis mới
Khuyến nghị SA — Nghiêng về B nếu Tech Lead chấp nhận độ phức tạp invalidation, vì chi phí hạ tầng thấp và cải thiện trực tiếp khả dụng đúng lúc tải cao (flash sale — thời điểm RDS dễ chậm nhất, theo QAS-006/ARISK-02)

🔴 Cập nhật OQ-040 trong sổ với bảng đánh giá này (giữ nguyên mở, chờ Tech Lead quyết định cuối) — xem §11.

7.4 Bảng quyết định chung

Vấn đề Quyết định ADR
Phân mảnh (sharding/partitioning) Không sharding ở MVP (kế thừa lý do docs/05 §5.3.4 — schema-per-module đã là lớp scale đầu tiên); partitioning theo tháng cho order/order_seller/order_item, payment/payment_transaction/payment_reconciliation_log (tăng trưởng nhanh nhất, tham khảo docs/05 §5.3.3) Không cần ADR riêng (kỹ thuật thi công, radar thấp)
Đọc/ghi tách nhau Có, chỉ Catalog dùng read replica (kịch bản B) — xem §7.2 Không cần ADR (OQ-046)
Cache: cái gì, invalidate thế nào Session/ownership (đã có, ADR-007); nội dung Cart (đề xuất, chưa chốt — OQ-040) ADR-007 (đã có); cache Cart chưa cần ADR nếu chỉ áp dụng 1 module (radar thấp)

🔴 Cache invalidation phải thiết kế cùng lúc với cache (D template) — nếu Phương án B ở §7.3 được chọn, cơ chế invalidate (write-through khi PATCH/DELETE) phải triển khai đồng thời, không được để cache "TTL tự nhiên" là biện pháp duy nhất.


8. Migration dữ liệu & Versioning schema

8.1 Migration dữ liệu legacy

Không áp dụng — dự án greenfield, theo CTX/docs/05 §5.3.5: không có hệ thống cũ cần migrate cho module Giỏ hàng & Checkout. Dữ liệu khởi tạo chỉ gồm cấu hình tĩnh (language, currency, commission_rule mặc định — thuộc các module khác, ngoài phạm vi chi tiết của DAT lượt này).

8.2 Versioning schema (đề xuất — chưa chốt)

Đề xuất SA
Công cụ Flyway (SQL migration thuần, phổ biến với PostgreSQL, không yêu cầu ORM cụ thể) — đề xuất, chưa xác nhận Tech Lead (ICD §2 đã ghi "Flyway/Liquibase chưa chọn"); ghi OQ-045
Chính sách thay đổi schema Additive trước, breaking sau — khớp ICD §2 IF-016/017 ("Migration versioned tăng dần, không breaking ngược")
Ranh giới migration theo schema Mỗi schema (identity/catalog/cart_order/.../payment) có thư mục migration riêng, chạy độc lập — khớp nguyên tắc schema-per-module (ADR-006), migration của payment chạy trên RDS Payment hoàn toàn tách biệt (không chung pipeline CI/CD deploy với schema khác, để giữ ranh giới cô lập ADR-002)
Rollback schema Mỗi migration có script down tương ứng (Flyway Community không hỗ trợ auto-rollback — cần viết migration bù thủ công nếu cần lùi) — 🔴 đây là giới hạn công cụ cần Tech Lead biết trước khi chọn

9. Sao lưu & khôi phục

Đối chiếu QAS-008/ADR-009 (RPO ≤15 phút, RTO ≤1 giờ cho Payment, Cart&Order, Identity — "nhóm giao dịch cốt lõi") và TCO §3.2 (dòng "Backup & DR" ≈$30/$60/tháng).

RDS chính (8 schema) RDS Payment
Tần suất backup Automated backup + PITR liên tục (WAL archiving) Automated backup + PITR liên tục
Retention PITR 🔴 Đề xuất 35 ngày (tham khảo docs/05 §5.3.2 cho nhóm "giao dịch cốt lõi") — chưa xác nhận Ops/SRE 🔴 Đề xuất 35 ngày (cùng lý do — dữ liệu tài chính)
Lần khôi phục thử gần nhất Chưa từng thử — Confidence 🔴, ARISK (đã ghi ở ADR-009) Chưa từng thử — cùng ARISK
RPO ≤15 phút (mục tiêu QAS-008, chưa diễn tập) ≤15 phút (cùng mục tiêu)
RTO ≤1 giờ (mục tiêu QAS-008, chưa diễn tập) ≤1 giờ (cùng mục tiêu)

🔴 Phát hiện quan trọng — RPO/RTO đồng nhất ngoài ý muốn giữa module lõi và không lõi: vì ADR-006 gộp 8 schema vào 1 RDS instance, backup/PITR/Multi-AZ failover áp dụng ở mức instance, không phân biệt được schema cart_order/identity (lõi, cần RPO≤15 phút) với schema seller/commission/promotion/review/notification/shipping (không lõi, docs/05 §5.3.2 P1 đề xuất RPO/RTO lỏng hơn — ví dụ ≤1 giờ/≤4 giờ hoặc ≤24 giờ/≤24 giờ tuỳ nhóm). Hệ quả: mọi schema trong RDS chính đều được hưởng RPO/RTO chặt của nhóm lõi "miễn phí" (tốt hơn yêu cầu tối thiểu cho module không lõi) — không phải lỗi, nhưng khác với giả định phân tầng chi phí của docs/05 P1 (vốn tách theo instance để có backup rẻ hơn cho module ít quan trọng). TCO §3.2 hiện chỉ có 1 dòng "Backup & DR" chung, khớp với thực tế 1 instance — không có mâu thuẫn số liệu, chỉ ghi nhận đây là đặc điểm của kiến trúc gộp, không phải khác biệt cần sửa.

S3 (KYC, ảnh sản phẩm) Đề xuất
Versioning Bật cho bucket KYC (PII pháp lý)
Cross-region replication Bật cho bucket KYC — tham khảo docs/05 §5.3.2
Lifecycle Ảnh sản phẩm ít truy cập → storage rẻ hơn sau 90 ngày (tham khảo docs/05)

10. Đối chiếu với docs/sections/05-thiet-ke-du-lieu.md (P1) — chỉ tham khảo

Theo ghi chú người duyệt: tài liệu P1 chỉ dùng để tham khảo tên bảng/cột/số retention đề xuất, không kế thừa kiểu kiến trúc. Danh sách khác biệt chính:

# P1 (docs/05) P2 (DAT này) Ghi chú
1 Database-per-service (mỗi service 1 RDS) 1 RDS chính schema-per-module + 1 RDS Payment riêng (ADR-006/ADR-002) Đã ghi ở §3
2 Kafka/MSK cho event SQS FIFO + EventBridge (ADR-005) Ảnh hưởng cơ chế dedupe/ordering — đã thiết kế lại ở ICD §4
3 Không có trạng thái PENDING_PAYMENT_INIT/PAYMENT_INIT_READY/PAYMENT_INIT_FAILED ở order Có, theo ADR-013 (bất đồng bộ hoá khởi tạo thanh toán) P1 không có yêu cầu này vì chưa phát hiện xung đột ngân sách QAS-002 — đặc thù của P2
4 Có service Audit & Compliance riêng (audit_log tập trung, v3) P2 SAD §4 (15 CMP) KHÔNG có CMP Audit & Compliance riêng 🔴 Khoảng trống thật — chưa kiến trúc audit trail xuyên module cho P2 dù RBAC_CartCheckout §5 (BA) và ADR-008 §6 (audit định kỳ PII) đều cần. Ghi OQ-047 (§11), ngoài phạm vi giải quyết đầy đủ ở DAT lượt này
5 cart_item không có seller_name_snapshot; order_item.unit_price không phân biệt snapshot vs giá hiện tại cart_item.seller_name_snapshot, unit_price_snapshot; order_item.unit_price_snapshot Bổ sung theo ICD §3.1.1/§3.7 (OQ-033 chốt TẠM)
6 Retention cụ thể theo bảng (docs/05 §5.3.6) Kế thừa làm đề xuất khởi điểm, chưa xác nhận Legal (OQ-007) Không copy nguyên trạng làm quyết định — chỉ dùng làm baseline đề xuất

11. Giả định & Ngoài phạm vi

Giả định (tiếp số toàn dự án — ASM-01…34 đã dùng, bắt đầu ASM-35):

ID Giả định Cách xác minh Nếu sai
ASM-35 1 Order (cha) có đúng 1 Payment bất kể checkout gồm bao nhiêu seller/phương thức (theo BR_CartCheckout §4 ERD gốc: `ORDER --o
ASM-36 Read replica (kịch bản B) có độ trễ nhân bản đủ thấp (<1 giây) để không ảnh hưởng cảm nhận "mới cập nhật" khi dùng cho Catalog Đo thật sau khi có replica (inf/POC-02) Nếu lag cao hơn: cần điều chỉnh chiến lược cache Catalog (TTL ngắn hơn) hoặc không dùng replica cho các API vừa ghi vừa đọc gần nhau (VD Seller vừa cập nhật giá)
ASM-37 Số năm retention tham khảo từ docs/05 §5.3.6 (30 ngày ẩn danh hoá, 5 năm KYC, 10 năm tài chính) là điểm khởi đầu hợp lý cho P2, dù kiến trúc lưu trữ đã đổi (schema-per-module) Đại diện Pháp chế/Bảo mật xác nhận khi có người (OQ-007) Nếu Legal yêu cầu số khác: sửa bảng §5/§6, có thể ảnh hưởng thiết kế partition (docs/05 §5.3.3 tham khảo) nếu retention ngắn hơn nhiều
ASM-38 Outbox relay có thể chạy trong cùng process/task với module publish (Cart & Order, Payment) bằng polling loop 1-2 giây, không cần dịch vụ riêng, ở quy mô kịch bản A/B hiện tại Đo thật khi có POC throughput hoặc sau go-live Nếu tải cao hơn dự kiến khiến polling loop không theo kịp: cần tách relay thành service riêng hoặc dùng CDC (Debezium) — thay đổi hạ tầng đáng kể

Ngoài phạm vi:

  • Schema chi tiết đầy đủ (kiểu dữ liệu cột, index đầy đủ, constraint) cho 6 module Nhóm Hỗ trợ (Seller, Commission, Promotion, Review, Notification, Shipping) — chỉ xác nhận ownership + entity list (§1.5), kế thừa tên bảng từ docs/05; chi tiết hoá đầy đủ thuộc dev khi module đó tới lượt.
  • Kiến trúc audit trail xuyên module (Audit & Compliance Service kiểu P1, hoặc phương án khác) — khoảng trống ghi nhận ở §10 dòng 4, OQ-047, thuộc hoạt động sec/adr kế tiếp.
  • Thiết kế chi tiết OpenSearch (schema chỉ mục, đồng bộ) — hoãn tới khi có bằng chứng tải cần, theo SAD §10.
  • ADR chính thức cho outbox pattern (§4.1) — chỉ trình bày phân tích + đề xuất, chưa viết ADR, thuộc hoạt động adr kế tiếp (OQ-044).
  • Cấu hình connection pool cụ thể theo module (OQ-037, đã có ở FAIL) — DAT chỉ xác nhận ranh giới schema cần pool riêng (§1), số cụ thể chờ POC-02.
  • Chi tiết mã hoá tầng ứng dụng (thuật toán, quản lý khoá) cho các trường đánh dấu "khuyến nghị mã hoá" ở §5 — thuộc hoạt động sec (hoạt động 6, chưa chạy).

12. Open Questions

Tiếp số sổ SA (00-index/OQ_e-commerce.md đang ở OQ-042) — bắt đầu OQ-043.

ID Câu hỏi Hỏi ai Từ ngày Chặn gì Hệ quả nếu trả lời ngược
OQ-043 1 Order (cha) có đúng 1 Payment (đa seller, 1 phương thức chung) hay có ngoại lệ tách Payment theo OrderSeller/phương thức? (nối OQ-030 của ICD) Tech Lead + PO 2026-09-15 Mô hình payment.order_id; IF-006 request/response (ICD §3.3); order.payment_init_status Nếu tách theo OrderSeller: cần N lời gọi gateway thay vì 1, ảnh hưởng cả ADR-013 (mỗi OrderSeller có trạng thái init riêng, phức tạp hơn UX hiện tại) và chi phí giao dịch (một số gateway tính phí theo giao dịch)
OQ-044 Chấp nhận Transactional Outbox pattern (outbox_event + relay poller) làm cơ chế chính thức xử lý khoảng trống "commit Order nhưng publish event thất bại" (FAIL §7) không, hay dùng job quét đối chiếu đơn giản hơn (PA-1, §4.1)? Radar ước lượng ~6/10 — ADR bắt buộc, chưa viết. Tech Lead 2026-09-15 ADR mới ở hoạt động adr kế tiếp; thiết kế relay ở inf Chọn PA-1 (job quét): tiết kiệm 1 bảng/relay nhưng cần thiết kế cột đánh dấu đủ tin cậy và có race condition tiềm ẩn; không tổng quát cho module publish event sau này — mỗi module tự nghĩ cách riêng
OQ-045 Công cụ quản lý migration schema — Flyway hay Liquibase (hoặc khác)? Tech Lead 2026-09-15 Quy trình CI/CD; khả năng rollback schema (§8.2) Flyway: đơn giản, SQL thuần, nhưng Community không auto-rollback (cần viết migration bù thủ công). Liquibase: hỗ trợ rollback tốt hơn nhưng cú pháp XML/YAML phức tạp hơn, đường cong học tập cao hơn cho team chưa dùng
OQ-046 Đọc Cart/Order có nên route sang RDS read replica (chỉ có ở kịch bản B) hay luôn đọc primary? SA đề xuất: chỉ Catalog dùng replica, Cart&Order luôn đọc primary (§7.2). Tech Lead 2026-09-15 Cấu hình routing đọc ở inf; độ tươi dữ liệu GET /v1/cart Nếu Cart&Order cũng dùng replica để giảm tải primary: có thể vi phạm read-your-write ngay sau PATCH, gây bug khó tái hiện ("tôi vừa sửa giỏ mà sao không thấy")
OQ-047 P2 (SAD 15 CMP) không có CMP Audit & Compliance riêng như P1 (docs/05 v3) — audit trail xuyên module (RBAC_CartCheckout §5, ADR-008 §6) nên kiến trúc theo cách nào: (a) mỗi module tự ghi audit_log trong schema riêng, hay (b) thêm 1 CMP Audit tập trung? Tech Lead + Security 2026-09-15 Danh sách CMP (có thể thêm CMP-16); ADR-001 (nếu thêm component mới ảnh hưởng cấu trúc tổng thể) Chọn (a): đơn giản hơn, không thêm component, nhưng khó tổng hợp audit xuyên module khi CSR/Admin cần tra cứu. Chọn (b): tập trung hoá tra cứu nhưng thêm 1 CMP/1 điểm publish event bắt buộc từ mọi module — cần rà lại SAD §4

Cập nhật các OQ đã mở, không tạo ID mới (ghi trong sổ 00-index/OQ_e-commerce.md, xem §13 đối chiếu):

  • OQ-007 — bổ sung: DAT §5 đã phân loại PII/Payment/nghiệp vụ + đề xuất retention (30 ngày ẩn danh hoá PII khách hàng, 5 năm KYC, 10 năm tài chính — tham khảo docs/05, ASM-37) và whitelist chia sẻ seller (recipient_name/phone/address_line, hiện thực hoá ADR-008 PA-2 ở §5.2) — vẫn chờ đại diện Pháp chế/Bảo mật phủ quyết, giữ nguyên mở.
  • OQ-040 — bổ sung: DAT §7.3 đánh giá 2 phương án (không cache / cache-aside nội dung Cart) kèm hệ quả — SA nghiêng về Phương án B nếu Tech Lead chấp nhận độ phức tạp invalidation, giữ nguyên mở.
  • OQ-042 — bổ sung: DAT §4.3 đề xuất ngưỡng quét 5 phút + tần suất job 5 phút + hành động (cập nhật trạng thái, giải phóng tồn kho reserve, cảnh báo Ops) — giữ nguyên mở, chờ Tech Lead xác nhận.

13. Tự chấm

① Bảng tự chấm Gate AG2 (workflow.md §2 — chỉ dòng liên quan tới DAT, tự chấm sớm)

# Tiêu chí ☐/✅ Ghi chú
— ASR/QAS/SAD/ICD/FAIL ✅ (đã đạt ở các hoạt động trước) Không lặp lại
— ADR-nnn tồn tại cho mọi quyết định đạt ngưỡng radar 🟡 Một phần 13 ADR đã có (ADR-001…013); DAT phát hiện 1 quyết định mới đạt ngưỡng (outbox pattern, radar ~6) chưa viết ADR — đúng phạm vi (dat không bao gồm viết ADR), ghi OQ-044, chờ hoạt động adr
1 DAT — mỗi thực thể dữ liệu có đúng một chủ sở hữu; có phân loại PII và retention ✅ §1 (ownership đủ 15 CMP, không thực thể mồ côi/hai chủ), §5 (phân loại PII/Payment/nghiệp vụ + retention đề xuất)
— SEC/INF ☐ Chưa tới — hoạt động 6-7
— sa-conformance báo coverage ASR → ADR/CMP ≥ 100% (không đổi bởi DAT) DAT không tạo CMP/ASR mới

Kết luận tự chấm (riêng phần DAT): Hoạt động dat hoàn tất đúng phạm vi được giao — ownership đủ 15/15 CMP không mồ côi/không hai chủ (D7), mô hình Order/OrderSeller/ OrderItem chi tiết theo ADR-003/ADR-013, phân loại PII/retention đề xuất (chờ Legal), chiến lược đọc/ghi/cache/consistency đầy đủ theo QAS-003/004/006/008/014, phát hiện 1 khoảng trống cần ADR mới (outbox, chưa viết — đúng phạm vi). AG2 còn thiếu SEC/INF (hoạt động 6-7) và chữ ký thật của Tech Lead + Security + Ops/SRE.

② Checklist D1–D12 (design-rules.md)

# Mục ☐/✅ Ghi chú
D1 Một ADR một quyết định N/A DAT không viết ADR mới (outbox là ứng viên, chưa viết — §4.1)
D2 Không NFR định tính ✅ Mọi ngưỡng consistency/retention/TTL đều có con số hoặc tham chiếu OQ đang chờ số
D3 Nêu phương án bị loại + lý do ✅ §3 (database-per-service/OpenSearch/Kafka bị loại, kế thừa OPT); §4.1 (PA-1 job quét bị loại thay bằng đề xuất PA-2 outbox, có bảng so sánh)
D4 Sơ đồ khai báo mức + legend ✅ §2.1 khai báo "mức khái niệm" + legend; không trộn với mức schema vật lý
D5 Interface có chủ/contract N/A Đã xử lý ở ICD (hoạt động 4); DAT chỉ tham chiếu
D6 Phụ thuộc ngoài process có timeout/retry N/A Đã xử lý ở FAIL (hoạt động 8); DAT chỉ bổ sung khía cạnh dữ liệu (outbox, idempotency store)
D7 Một chủ sở hữu dữ liệu ✅ §1 — bảng ownership đầy đủ 15 CMP, mỗi thực thể đúng 1 SoT, mọi bản sao ghi rõ cơ chế/độ trễ
D8 Ràng buộc có FIT hoặc nhãn khuyến nghị 🟡 Một phần Đề xuất FIT-26 (schema owner check mở rộng FIT-09 đã có ở ADR-006), FIT-27 (outbox lag monitor), FIT-28 (idempotency TTL test) — ứng viên GĐ3, chưa viết thật
D9 Con số hạ tầng quy ra tiền + nguồn 🟡 Một phần §9 dùng đúng số TCO §3.2 (có nguồn); retention/backup cụ thể (35 ngày) là đề xuất tham khảo docs/05, chưa có báo giá riêng cho từng mức retention — không ảnh hưởng TCO hiện tại (1 dòng chung)
D10 Không quyết định thay người có thẩm quyền ✅ §5 (PII/retention — chờ Legal), §7.3 (cache Cart — chờ Tech Lead), §4.1 (outbox — chờ Tech Lead + adr) đều trình phương án kèm hệ quả, không tự quyết
D11 Có mục "Ngoài phạm vi" + ASM-nn ✅ §11 đầy đủ — ASM-35…38 mới, có cách xác minh/hệ quả
D12 Câu quy định thẩm quyền sơ đồ vs văn bản ✅ Có ngay sau Change Log

③ Bảng đối chiếu với bộ BA

BA Nội dung DAT tương ứng Khớp? Hành động
BR_CartCheckout §4 (ERD khái niệm) Order/OrderSeller/OrderItem/Payment, không có payment_init_status §2.1 (bổ sung payment_init_status, idempotency_key, seller_name_snapshot) 🟡 Một phần Bổ sung kỹ thuật theo ADR-013/ICD, không đổi mô hình nghiệp vụ BA đã chốt — BA không cần cập nhật BR_CartCheckout vì đây là chi tiết kỹ thuật (state machine nội bộ), không phải quy tắc nghiệp vụ mới; nếu US-004 (Checkout) được BA viết SRS riêng sau này, cần phản ánh 4 trạng thái này ở đó (đã ghi OQ-038 của FAIL)
RBAC_CartCheckout §4 (mức che PII khi hiển thị cho seller — chưa chốt) Whitelist recipient_name/phone/address_line (§5.2, hiện thực hoá ADR-008 PA-2) §5, §5.2 🟡 Một phần DAT đề xuất cơ chế kỹ thuật (snapshot 3 trường, không JOIN ngược) — vẫn chờ Security/Legal chốt chính thức (OQ-007/RISK-03 của BA), DAT không tự đóng câu hỏi này
RBAC_CartCheckout §5 (lưu vết/audit — "chưa chốt thời hạn lưu") §10 dòng 4 (khoảng trống Audit & Compliance CMP) 🟡 Một phần DAT phát hiện P2 chưa có kiến trúc audit trail xuyên module — BA cần biết đây là khoảng trống kỹ thuật đang mở (OQ-047), chưa có nơi lưu vết chi tiết như RBAC §5 kỳ vọng
BR_CartCheckout §4.3 (thực thể ngoài phạm vi — CUSTOMER/SELLER/PRODUCT_VARIANT tham chiếu qua FK logic, snapshot giá) §1.1/§1.2 (ownership CMP-02/CMP-05/CMP-03, snapshot unit_price_snapshot) ✅ Khớp hoàn toàn — DAT xác nhận đúng nguyên tắc BA đã nêu (FK logic, snapshot giá)

④ Danh sách OQ mở kèm người phải trả lời, chặn gì

Xem §12 (OQ-043…047 mới) cộng cập nhật OQ-007/040/042. Ba câu hỏi quan trọng nhất cho sec/ inf kế tiếp: OQ-007 (PII/residency, chặn ADR-008 và toàn bộ §5), OQ-044 (outbox pattern, chặn ADR mới + thiết kế relay ở inf), OQ-043 (cardinality Payment/Order, chặn thiết kế cuối cùng của IF-006). Sổ đầy đủ: 00-index/OQ_e-commerce.md.

Nhắc: AG2 cần Tech Lead + Security + Ops/SRE ký — còn thiếu SEC/INF (hoạt động 6-7) và 1 ADR mới (outbox, OQ-044). Hoạt động kế tiếp có thể chạy song song: sec (dùng §5 phân loại PII làm input threat model), inf (dùng §9 backup/RPO-RTO, §7.2 read replica, §4.1 relay outbox nếu được chấp nhận).