182 lines
7.4 KiB
Markdown
182 lines
7.4 KiB
Markdown
# ICD — Integration & Interface Catalog — <PROJECT>
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Version** | 1.0 |
|
|
| **Date** | YYYY-MM-DD |
|
|
| **Author** | <SA> (skill sa-2-architecture) |
|
|
| **Status** | 🟡 Draft |
|
|
| **Approved by** | Tech Lead: — · BE Lead: — |
|
|
| **Source** | SAD_… v1.0 · API_… của BA · tài liệu API của … |
|
|
| **Scope** | |
|
|
| **Confidence** | 🟡 |
|
|
|
|
## Change Log
|
|
|
|
| Version | Date | Người sửa | Thay đổi | ADR |
|
|
|---|---|---|---|---|
|
|
| 1.0 | | | Bản đầu | — |
|
|
|
|
> 🔴 **Tài liệu này thắng `API` contract của bộ BA khi hai bên lệch.** BA viết contract đề
|
|
> xuất và đánh dấu *"chờ BE xác nhận"* — đây là chỗ xác nhận. Mọi chỗ lệch phải báo lại để BA
|
|
> cập nhật SRS.
|
|
|
|
---
|
|
|
|
## 1. Ba quy ước chốt một lần cho toàn hệ thống
|
|
|
|
*Ba chỗ này gây bug nhiều nhất và thường không ai hỏi. Chốt ở đây, ghi thành `ADR`.*
|
|
|
|
| # | Vấn đề | Quyết định | `ADR` | Vì sao |
|
|
|---|---|---|---|---|
|
|
| 1 | **Số lớn** (id, số tiền) truyền dạng gì | `string` / `number` | | Vượt `2^53` thì JavaScript làm tròn sai ⇒ id 19 chữ số hỏng **im lặng** |
|
|
| 2 | **Thời gian** định dạng gì, múi giờ nào | ISO-8601 UTC / … | | Trộn local time và UTC là bug không ai tìm ra |
|
|
| 3 | **Phân trang** kiểu gì | offset (`page`,`size`) / cursor | | Offset không trả `hasNext` ⇒ nút "trang sau" hỏng |
|
|
|
|
Bổ sung khi áp dụng:
|
|
|
|
| # | Vấn đề | Quyết định | `ADR` |
|
|
|---|---|---|---|
|
|
| 4 | Định dạng phản hồi chung | `{ code, message, data }` / … | |
|
|
| 5 | Lỗi nghiệp vụ trả HTTP nào | **4xx**, không phải 200 kèm cờ lỗi | |
|
|
| 6 | Ngôn ngữ thông điệp lỗi | trả mã (client tự dịch) / trả text theo header | |
|
|
| 7 | Khoá idempotency | tên header, cách sinh, giữ bao lâu | |
|
|
| 8 | Correlation id | tên header, truyền xuyên suốt thế nào | |
|
|
|
|
🔴 **Lỗi nghiệp vụ trả 200 kèm cờ lỗi là bug im lặng**: tầng gọi API coi là thành công và giao
|
|
diện không hiện lỗi. Chốt 4xx ngay ở đây.
|
|
|
|
---
|
|
|
|
## 2. Danh mục interface — `IF-nnn`
|
|
|
|
*Mọi lời gọi vượt ranh giới container phải có một dòng.*
|
|
|
|
| ID | Từ | Đến | Giao thức | Sync/Async | **Ai sở hữu contract** | Contract ở đâu | Versioning | Đầu kia hỏng thì sao | `FAIL` |
|
|
|---|---|---|---|---|---|---|---|---|---|
|
|
| `IF-001` | `CMP-01` | `CMP-03` | HTTP/JSON | sync | team … | `openapi/orders.yaml` | URL path `/v1` | degrade: … | `FM-03` |
|
|
| `IF-002` | `CMP-03` | Kafka | AsyncAPI | async | team … | `asyncapi/settlement.yaml` | schema registry, backward | buffer + retry | `FM-05` |
|
|
|
|
🔴 **Interface không biết ai sở hữu là interface sẽ bị đổi mà không ai báo.** Cột này không
|
|
được để trống, kể cả với hệ thống nội bộ.
|
|
|
|
🔴 **Cột "Contract ở đâu" phải trỏ tới file thật** trong `02-architecture/contracts/` do `CTR`
|
|
(`--focus ctr`) sinh: `contracts/openapi/<module>.yaml#<operationId>` hoặc
|
|
`contracts/asyncapi/<domain>.yaml#<channel>`. Ghi "dự kiến" ⇒ `OQ` + `Confidence` 🔴 và AG2 chặn.
|
|
Interface đối tác chưa có tài liệu ⇒ ghi `ARISK`, không tự viết contract thay đối tác.
|
|
|
|
### 2.1 Interface với hệ thống ngoài
|
|
|
|
| ID | Hệ thống | Ai liên hệ được | **SLA của họ** | Giới hạn tốc độ | Cơ chế xác thực | Môi trường thử | Đã gọi thử chưa |
|
|
|---|---|---|---|---|---|---|---|
|
|
| `IF-0nn` | | tên + kênh | uptime … · p95 … | … req/phút | | có/không | ☐ |
|
|
|
|
🔴 Hệ thống ngoài **không có SLA** ⇒ thiết kế như thể nó có thể hỏng bất cứ lúc nào, và ghi
|
|
`ARISK`.
|
|
|
|
---
|
|
|
|
## 3. Chi tiết từng interface
|
|
|
|
### 3.1 `IF-001` — <tên>
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Mục đích** | |
|
|
| **Từ → Đến** | `CMP-01` → `CMP-03` |
|
|
| **Giao thức** | |
|
|
| **Đồng bộ?** | sync · timeout … ms |
|
|
| **Quyền** | `ROLE-nn` *(map ở `SEC` §3)* |
|
|
| **Idempotent** | có/không · khoá: … |
|
|
| **Tần suất dự kiến** | … req/s trung bình, … đỉnh · nguồn: `QAS-nnn` |
|
|
|
|
**Contract**
|
|
|
|
Nguồn sự thật: `contracts/openapi/<module>.yaml` · `operationId: <…>` (xem `CTR` §2) — **không
|
|
chép nội dung contract vào đây**, chỉ ghi những điểm cần chú ý:
|
|
|
|
| Điểm cần chú ý | Quyết định |
|
|
|---|---|
|
|
| Trường nào là số lớn ⇒ string | |
|
|
| Trường nào có thể null và ý nghĩa của null | |
|
|
| Enum có mở rộng về sau không ⇒ client xử lý giá trị lạ thế nào | |
|
|
|
|
**Mã lỗi**
|
|
|
|
| HTTP | `code` | Khi nào | Client làm gì | Mã lỗi SRS của BA |
|
|
|---|---|---|---|---|
|
|
| 400 | `INVALID_PARAM` | | hiện lỗi tại field | `E-…-0010` |
|
|
| 403 | `FORBIDDEN` | | không xoá dữ liệu đã nhập | `E-…-0403` |
|
|
| 409 | | | | |
|
|
| 5xx | | | cho thử lại, **giữ nguyên dữ liệu đã nhập** | |
|
|
|
|
**Chính sách phiên bản**
|
|
|
|
| | |
|
|
|---|---|
|
|
| Cách đánh phiên bản | URL path / header / schema registry |
|
|
| Thay đổi nào là breaking | *(bỏ trường, đổi kiểu, thêm trường bắt buộc, thu hẹp enum)* |
|
|
| Hỗ trợ bản cũ bao lâu | |
|
|
| Cách báo trước | |
|
|
|
|
### 3.2 `IF-002` — <tên>
|
|
|
|
*(cùng cấu trúc)*
|
|
|
|
---
|
|
|
|
## 4. Hợp đồng sự kiện *(nếu có async)*
|
|
|
|
| Sự kiện | Nhà phát | Người nhận | Schema | Thứ tự có quan trọng | At-least-once? | Trùng thì sao |
|
|
|---|---|---|---|---|---|---|
|
|
| | | | | | | khoá khử trùng: … |
|
|
|
|
🔴 **Hầu hết message broker đảm bảo at-least-once, không phải exactly-once.** Mọi người nhận
|
|
phải khử trùng được. Ghi rõ khoá khử trùng và cửa sổ thời gian.
|
|
|
|
| Vấn đề | Quyết định |
|
|
|---|---|
|
|
| Message hỏng (poison message) xử lý thế nào | DLQ · giữ bao lâu · ai xử lý |
|
|
| Đọc lại từ đầu (replay) có được không | |
|
|
| Thứ tự đảm bảo trong phạm vi nào | *(partition key là gì)* |
|
|
|
|
---
|
|
|
|
## 5. Đối chiếu với `API` của bộ BA
|
|
|
|
| Endpoint trong `API` của BA | `IF-nnn` | Khớp | Lệch ở đâu | Hành động |
|
|
|---|---|---|---|---|
|
|
| `GET /api/v1/…` | `IF-001` | ✅ | | |
|
|
| `POST /api/v1/…` | `IF-003` | ❌ | BA đề xuất `id: number`, `ICD` chốt `string` | BA cập nhật SRS §… |
|
|
|
|
Endpoint trong `API` không có `IF-nnn` ⇒ hoặc BA đề xuất một endpoint không tồn tại, hoặc `ICD`
|
|
bỏ sót. Phải xử lý, không để treo.
|
|
|
|
## 6. Hành vi giao diện khi API lỗi
|
|
|
|
| Tình huống | Giao diện làm gì | `QAS`/`AC` |
|
|
|---|---|---|
|
|
| 401 hết phiên | Chuyển về đăng nhập, giữ đường dẫn để quay lại | |
|
|
| 403 | Hiện thông báo không đủ quyền, **không xoá dữ liệu đã nhập** | |
|
|
| 5xx / timeout | Hiện lỗi, cho thử lại, **giữ nguyên dữ liệu đã nhập** | |
|
|
| Mạng chậm | Trạng thái đang tải, **khoá nút gửi** để tránh gửi hai lần | |
|
|
|
|
🔴 Không khoá nút gửi ⇒ người dùng bấm hai lần tạo hai bản ghi. Đây là bug xuất hiện ở gần như
|
|
mọi hệ thống không chốt điểm này từ đầu.
|
|
|
|
## 7. Giả định & Ngoài phạm vi
|
|
|
|
**Giả định:**
|
|
|
|
| ID | Giả định | Cách xác minh | Nếu sai |
|
|
|---|---|---|---|
|
|
|
|
**Ngoài phạm vi:**
|
|
|
|
-
|
|
|
|
## 8. 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 |
|
|
|---|---|---|---|---|---|
|