This commit is contained in:
Leonard-ThindPad-P50
2026-09-08 10:26:21 +07:00
commit c81f249920
169 changed files with 38726 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
# PART 2 — biến thể `api-service`
> **Dùng khi** `PRODUCT = api-service` — sản phẩm không có giao diện; người tiêu thụ là hệ
> thống khác hoặc team khác. Cắm khối này vào chỗ PART 2 của [`../srs.md`](../srs.md).
>
> **Tiêu chí G3 riêng của biến thể này**: mỗi endpoint có bảng tham số/schema đầy đủ · mọi
> mã lỗi map về endpoint · đã trả lời xong ba câu idempotency / tương thích ngược / phân
> trang · có ít nhất một team tiêu thụ đã đọc và xác nhận.
🔴 **Với loại này, `API_<US>.md` là artifact chính, không phải phụ lục.** PART 2 ở đây mô tả
*hợp đồng nhìn từ phía người tiêu thụ*; chi tiết kỹ thuật từng endpoint vẫn ở
[`../api-contract.md`](../api-contract.md). Đừng chép trùng — PART 2 trả lời "có những khả
năng gì", `API` trả lời "gọi thế nào".
---
## 2.1 Người tiêu thụ
*Thay cho "danh sách màn hình". Ai gọi API này quyết định AC viết thế nào.*
| ID | Người tiêu thụ | Là ai | Gọi để làm gì | Tần suất dự kiến | Đầu mối |
|---|---|---|---|---|---|
| CON-01 | | Hệ thống nội bộ / Đối tác ngoài / App di động | | | |
**Ba câu bắt buộc:**
| Câu hỏi | Trả lời |
|---|---|
| Có người tiêu thụ nào **ngoài tổ chức** không? | *(quyết định mức chặt của versioning và bảo mật)* |
| Người tiêu thụ có tự thử được không, hay cần môi trường sandbox? | |
| Ai được thêm người tiêu thụ mới, và bằng quy trình gì? | |
## 2.2 Danh sách khả năng
| ID | Khả năng nghiệp vụ | Endpoint | Method | Người tiêu thụ | Đồng bộ/Bất đồng bộ | BR |
|---|---|---|---|---|---|---|
| CAP-01 | Tra cứu … | `/api/v1/…` | GET | CON-01 | Đồng bộ | |
| CAP-02 | Ghi nhận … | `/api/v1/…` | POST | CON-01, CON-02 | Bất đồng bộ (trả 202 + callback) | BR-0nn |
## 2.3 Sơ đồ luồng gọi
```mermaid
sequenceDiagram
autonumber
participant C1 as CON-01 (người gọi)
participant SVC as Service
participant DB as Cơ sở dữ liệu
participant Q as Hàng đợi
participant C2 as CON-02 (người tiêu thụ event)
C1->>SVC: POST /orders (Idempotency-Key)
SVC->>DB: Ghi bản ghi
alt Ghi thành công
DB-->>SVC: OK
SVC->>Q: publish OrderCreated
SVC-->>C1: 201 + id
Q-->>C2: OrderCreated
else Trùng Idempotency-Key
DB-->>SVC: đã tồn tại
SVC-->>C1: 200 + id cũ (không tạo bản ghi thứ hai)
else Lỗi ghi
DB--xSVC: lỗi
SVC-->>C1: 503 · E-XXX-0503 (retry được)
end
```
🔴 **Bắt buộc vẽ ba nhánh**: thành công · **gọi lại trùng** · lỗi. Nhánh giữa là nhánh chứng
minh §2.4.1 idempotency hoạt động — thiếu nó thì người tiêu thụ không biết gọi lại có an toàn không.
**Bảng đi kèm** *(quy tắc W13)*:
| Bước | Đồng bộ / Bất đồng bộ | Timeout | Retry được | Mã lỗi |
|---|---|---|---|---|
| 1 | Đồng bộ | 5s | ✅ với `Idempotency-Key` | |
| 5 | Bất đồng bộ | — | Hàng đợi tự retry 3 lần | |
Với luồng **bất đồng bộ**, bắt buộc trả lời ba câu — sơ đồ không nói được:
| Câu hỏi | Trả lời |
|---|---|
| Người gọi biết kết quả bằng cách nào | polling `GET /orders/{id}` · callback · event |
| Chờ tối đa bao lâu | |
| Quá hạn mà chưa có kết quả thì làm gì | |
---
## 2.4 CAP-01 — <Tên khả năng>
### 2.4.1 Hợp đồng
| | |
|---|---|
| **Endpoint** | `POST /api/v1/…` |
| **Quyền** | scope `…` / client `…` |
| **Idempotent** | ✅/❌ — nếu ✅: khoá idempotency là gì, giữ bao lâu |
| **Gọi lại an toàn (retry)** | ✅/❌ |
| **Thời gian phản hồi mục tiêu** | ≤ … ms (p95) |
| **Giới hạn tần suất** | … req/phút/client · vượt thì trả gì |
🔴 **Ba câu này là chỗ hay bỏ sót nhất của API spec:**
1. **Idempotency** — người gọi timeout rồi gọi lại, có tạo hai bản ghi không? Nếu không
idempotent thì phải nói rõ để người tiêu thụ tự xử lý.
2. **Retry** — lỗi nào được retry, lỗi nào không? Khuyến nghị backoff bao nhiêu?
3. **Đồng thời** — hai request cùng sửa một tài nguyên thì sao? Có optimistic locking không?
### 2.4.2 Tham số / Request
| Tên | Kiểu | Vị trí | Bắt buộc | Mặc định | Ràng buộc | BR |
|---|---|---|---|---|---|---|
| | string | query / path / body | ✅ | — | 3–20 ký tự, `^[A-Z0-9-]+$` | BR-0nn |
*Cột `Ràng buộc` là tương đương của "bảng field" ở biến thể `screen` — phải cụ thể ngang vậy.*
### 2.4.3 Response thành công
| Trường | Kiểu | Có thể null | Nghĩa nghiệp vụ | Ghi chú |
|---|---|---|---|---|
| | | | | |
### 2.4.4 Response lỗi
| HTTP | `code` | Khi nào | Người gọi nên làm gì | Mã lỗi SRS §4.1 |
|---|---|---|---|---|
| 409 | | | Không retry, sửa dữ liệu | `E-XXX-0001` |
| 503 | | | Retry với backoff | `E-XXX-0503` |
**Cột "Người gọi nên làm gì" là cột thay thế cho "hiển thị ở đâu" của biến thể `screen`.**
Không có nó thì mỗi team tiêu thụ tự đoán một kiểu xử lý lỗi.
---
## 2.5 Hợp đồng dữ liệu chung
| # | Vấn đề | Quyết định |
|---|---|---|
| 1 | **Số lớn** (id, số tiền) | `string` / `number` — vượt `2^53` thì JS làm tròn sai |
| 2 | **Thời gian** | Định dạng, múi giờ |
| 3 | **Phân trang** | offset / cursor · có `total`? có `hasNext`? |
| 4 | **Sắp xếp** | Cú pháp, trường nào cho phép |
| 5 | **Trường null vs. vắng mặt** | Có khác nghĩa không |
| 6 | **Enum** | Người tiêu thụ gặp giá trị lạ (mới thêm) thì xử lý sao |
## 2.6 Phiên bản & tương thích ngược
| | |
|---|---|
| **Cách đánh version** | URL `/v1/` · header · … |
| **Thay đổi nào là phá vỡ tương thích** | *(bỏ trường, đổi kiểu, thêm ràng buộc, đổi nghĩa mã lỗi)* |
| **Thay đổi nào là an toàn** | *(thêm trường optional, thêm giá trị enum — **chỉ khi** §2.5 #6 đã định nghĩa)* |
| **Báo trước bao lâu khi bỏ version cũ** | |
| **Chạy song song mấy version** | |
🔴 **Thêm một giá trị enum là thay đổi phá vỡ tương thích** nếu §2.5 #6 không nói người tiêu
thụ phải làm gì với giá trị lạ. Đây là lỗi tương thích phổ biến nhất và im lặng nhất.
## 2.7 Trạng thái tương đương "màn hình rỗng"
| Tình huống | Trả về gì | HTTP |
|---|---|---|
| Truy vấn hợp lệ, không có bản ghi nào | Mảng rỗng + paging `total: 0` — **không phải 404** | 200 |
| Tài nguyên không tồn tại | | 404 |
| Tài nguyên tồn tại nhưng không có quyền | 404 hay 403? *(404 giấu sự tồn tại — chọn theo mức nhạy cảm)* | |
## 2.8 Môi trường & tích hợp thử
| | |
|---|---|
| Sandbox | Có / Không — đường dẫn |
| Dữ liệu mẫu cho người tiêu thụ thử | |
| Cách cấp credential | |
| Tài liệu tích hợp bàn giao ở đâu | *(đây là `MANUAL` của GĐ5 với loại sản phẩm này)* |