Files
sys-analysis-design/.claude/skills/sa-2-architecture/templates/interface-catalog.md
Leonard-ThindPad-P50 c81f249920 init git
2026-09-08 10:26:21 +07:00

177 lines
7.0 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ộ.
### 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: `<đường dẫn file OpenAPI/AsyncAPI/proto>` — **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 |
|---|---|---|---|---|---|