# ICD — Integration & Interface Catalog — | | | |---|---| | **Version** | 1.0 | | **Date** | YYYY-MM-DD | | **Author** | (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/.yaml#` hoặc `contracts/asyncapi/.yaml#`. 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` — | | | |---|---| | **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/.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` — *(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 | |---|---|---|---|---|---|