init git
This commit is contained in:
265
.claude/skills/sa-2-architecture/SKILL.md
Normal file
265
.claude/skills/sa-2-architecture/SKILL.md
Normal file
@@ -0,0 +1,265 @@
|
||||
---
|
||||
name: sa-2-architecture
|
||||
description: Giai đoạn 2 của quy trình Solution Architect — định nghĩa kiến trúc tới mức dev thi công được. Dùng để lượng hoá NFR thành quality attribute scenario có con số và cách đo, xác định yêu cầu định hình kiến trúc (ASR), phân rã hệ thống thành component/service với sơ đồ C4, viết Architecture Decision Record, chốt contract cho mọi interface, thiết kế kiến trúc dữ liệu và ownership, dựng threat model STRIDE và mô hình phân quyền, thiết kế hạ tầng với HA/DR RTO/RPO, và thiết kế đường lỗi (timeout, retry, circuit breaker, degradation). Kích hoạt khi người dùng nói "thiết kế kiến trúc", "vẽ sơ đồ hệ thống", "C4", "viết ADR", "chốt NFR", "quality attribute", "thiết kế API contract", "mô hình dữ liệu", "threat model", "phân quyền kỹ thuật", "HA DR", "RTO RPO", "timeout retry", "circuit breaker", "chia service thế nào". Input là OPT đã qua AG1; output vào sa-output/<PROJECT>/02-architecture/ và phải qua Gate AG2 (Ready for Build) trước khi dev bắt đầu.
|
||||
---
|
||||
|
||||
# GĐ2 · ARCHITECTURE — Định nghĩa kiến trúc
|
||||
|
||||
Mục tiêu duy nhất: **dev đọc xong thi công được, QA đọc xong biết đo cái gì, SRE đọc xong biết
|
||||
vận hành thế nào** — không ai phải quay lại hỏi "cái này để đâu, gọi ai, hỏng thì sao".
|
||||
|
||||
Output: `ASR` · `QAS` · `SAD` · `ADR` · `ICD` · `DAT` · `SEC` · `INF` · `FAIL` trong
|
||||
`sa-output/<PROJECT>/02-architecture/`
|
||||
|
||||
## Bốn nguyên tắc bất di bất dịch
|
||||
|
||||
1. **Không bịa con số** — thiếu ⇒ `OQ-nnn` + `Confidence` 🔴, không điền giá trị "hợp lý".
|
||||
2. **Không quyết định thay người có thẩm quyền** — trade-off nghiệp vụ là của PO, chấp nhận
|
||||
rủi ro bảo mật là của Security. Trình phương án kèm **hệ quả phương án ngược bằng số**.
|
||||
3. **Mọi quyết định phải truy vết được** về `DRV`, `CON`, `ASR` hoặc `QAS`. Không nguồn ⇒ `ASM-nn`.
|
||||
4. **Không ghi đè tài liệu đã qua gate** — sửa qua `ADR` mới có `Supersedes:`.
|
||||
|
||||
Nạp thêm: `../sa-lifecycle/references/design-rules.md` (D1–D12) ·
|
||||
`../sa-lifecycle/references/decision-radar.md` (ngưỡng ADR) ·
|
||||
`../sa-lifecycle/references/artifact-map.md` §3–§4 (header, vòng đời ADR).
|
||||
|
||||
## Bước 0 — Chốt input rồi dừng lại
|
||||
|
||||
**Chưa được ghi file.** Làm năm việc rồi **dừng chờ người dùng trả lời**:
|
||||
|
||||
1. **Input dùng được** — bảng `File/Nguồn | Vai trò | Độ tin cậy`. Ưu tiên: file trong hội
|
||||
thoại > `sa-output/…/01-context/` (`CTX`, `OPT`, `ARISK`) > `ba-output/…/02-analysis/` và
|
||||
`/03-specification/` (`BACKLOG`, `BR`, `RBAC`, `SRS`, `NFR`, `API`) > source code hiện có.
|
||||
2. **Kiểm AG1** — `OPT` đã `✅ Baselined` và có `Approved by` chưa? Chưa ⇒ báo rõ: thiết kế
|
||||
trên phương án chưa chốt sẽ phải làm lại. Vẫn chạy được nếu người dùng muốn, nhưng toàn bộ
|
||||
`Confidence` là 🔴.
|
||||
3. **Chọn phạm vi chạy** — làm cả 9 artifact hay chỉ một nhóm (`--focus`). Cả 9 là công việc
|
||||
nhiều tuần; hỏi rõ người dùng cần gì trước.
|
||||
4. **Cách hiểu bài toán** — 2–3 câu, kèm danh sách file định ghi ra.
|
||||
5. **Hỏi người dùng** xác nhận bốn điểm trên.
|
||||
|
||||
Bỏ bước dừng khi lệnh có `go`.
|
||||
|
||||
## Thực hiện — 9 hoạt động
|
||||
|
||||
Thứ tự **không tuỳ ý**: 1→2→3 bắt buộc trước; 4–8 chạy song song được; 9 chạy liên tục.
|
||||
Với `--focus`, vẫn phải đọc output của các bước trước, không được bỏ qua.
|
||||
|
||||
### 1 — Lượng hoá NFR thành `QAS` *(`--focus qas`)*
|
||||
|
||||
Điền `templates/quality-scenarios.md`. **Đây là bước quyết định chất lượng cả GĐ2.** Không có
|
||||
con số thì không có kiến trúc, chỉ có sơ đồ hộp.
|
||||
|
||||
Mỗi `QAS-nnn` phải đủ **sáu phần**:
|
||||
|
||||
```
|
||||
QAS-004 | Thông lượng đối soát
|
||||
Nguồn kích thích : Job đối soát nửa đêm
|
||||
Kích thích : 1,2 triệu bản ghi POS của một ngày
|
||||
Môi trường : Giờ thấp điểm, 1 node worker, DB không có tải khác
|
||||
Phản hồi : Đối soát xong và sinh báo cáo chênh lệch
|
||||
Đo lường : ≤ 45 phút (p95 trong 30 lần chạy)
|
||||
Đo bằng cách nào : Bài đo `perf/settlement-batch.js` trên môi trường stg với
|
||||
bộ dữ liệu sinh 1,2M bản ghi · chạy trước mỗi release
|
||||
Ai đo : QA + SRE
|
||||
Nguồn : DRV-02, BR-014 · Mức: Must
|
||||
```
|
||||
|
||||
Rà đủ **bảy nhóm thuộc tính**, nhóm nào không áp dụng phải ghi "không áp dụng vì …":
|
||||
|
||||
| Nhóm | Câu hỏi lượng hoá | Bẫy |
|
||||
|---|---|---|
|
||||
| Hiệu năng | p50/p95/p99 của thao tác nào, ở tải nào | Chỉ ghi trung bình — trung bình che giấu đuôi |
|
||||
| Thông lượng | Bao nhiêu đơn vị/giây, đỉnh gấp mấy lần | Không phân biệt trung bình và đỉnh |
|
||||
| Sẵn sàng | % uptime ⇒ **quy ra ngân sách lỗi phút/tháng** | 99.9% nghe giống 99.99% nhưng chênh 10× |
|
||||
| Mở rộng | Tải tăng bao nhiêu trong bao lâu, scale bằng cách nào | Thiết kế cho tải hôm nay |
|
||||
| Bảo mật | Mối đe doạ nào, biện pháp gì, kiểm chứng thế nào | Ghi "bảo mật" như một mục |
|
||||
| Bảo trì | Onboard bao lâu, sửa một bug mất bao lâu | Không đo được ⇒ bỏ, đừng ghi định tính |
|
||||
| Quan sát được | Sự cố phát hiện sau bao lâu, truy nguyên mất bao lâu | Quên hẳn nhóm này |
|
||||
|
||||
🔴 **Ngân sách lỗi là cách duy nhất làm SLA có nghĩa.** 99.9%/tháng = 43 phút; 99.99% = 4,3
|
||||
phút. Hỏi PO: *"Chấp nhận hệ thống dừng 43 phút/tháng hay 4 phút/tháng?"* — câu hỏi đó quyết
|
||||
định kiến trúc HA và chi phí, và PO trả lời được. "Sẵn sàng cao" thì không ai trả lời được.
|
||||
|
||||
Mỗi `QAS` gắn mức **Must / Should / Could**. `Must` là "không đạt thì không được go-live".
|
||||
|
||||
### 2 — Chưng cất `ASR` *(`--focus asr`)*
|
||||
|
||||
Điền `templates/quality-scenarios.md` §ASR. `ASR` là **số ít** yêu cầu thực sự định hình kiến
|
||||
trúc — thường 8–15 mục cho một hệ thống trung bình, không phải 200.
|
||||
|
||||
Một yêu cầu là `ASR` khi có ≥ 1 điều:
|
||||
|
||||
- Ép một cấu trúc: *"phải xử lý được khi hệ thống POS ngoài mất kết nối 4 giờ"* ⇒ ép có hàng đợi
|
||||
- Ép một ràng buộc không đảo ngược: *"dữ liệu cá nhân phải nằm trong lãnh thổ Hàn Quốc"*
|
||||
- Ép một đánh đổi: *"số dư ví phải luôn chính xác"* ⇒ loại eventual consistency ở nhánh đó
|
||||
- Có `QAS` mức Must đứng sau
|
||||
|
||||
Mỗi `ASR-nnn` ghi: phát biểu · nguồn (`DRV`/`CON`/`QAS`/`BR`) · **ép ra cấu trúc gì** ·
|
||||
`ADR` nào hiện thực hoá nó.
|
||||
|
||||
### 3 — Phân rã hệ thống và viết `SAD` *(`--focus sad`)*
|
||||
|
||||
Điền `templates/sad.md`. Bốn việc, theo thứ tự:
|
||||
|
||||
**a. Chọn kiểu kiến trúc** — và viết `ADR` cho nó. Không chọn theo xu hướng; chọn theo `ASR`
|
||||
và `CON-04` (số người, ai vận hành). Bảng quyết định nhanh:
|
||||
|
||||
| Tín hiệu | Nghiêng về |
|
||||
|---|---|
|
||||
| ≤ 2 team, chưa rõ ranh giới nghiệp vụ | Modular monolith *(mặc định hợp lý, đừng ngại)* |
|
||||
| Nhiều team release độc lập, ranh giới đã rõ và ổn định | Service tách theo bounded context |
|
||||
| Tải rất lệch giữa các phần, cần scale riêng | Tách đúng phần lệch, giữ phần còn lại chung |
|
||||
| Xử lý nền, chịu được trễ, cần chống mất việc | Thêm hàng đợi / event-driven cho nhánh đó |
|
||||
| Đội vận hành nhỏ, không có kinh nghiệm phân tán | **Đừng phân tán.** Chi phí vận hành là thật |
|
||||
|
||||
**b. Vẽ C4 mức Context và Container** — bắt buộc cả hai, mỗi sơ đồ có legend và khai báo mức
|
||||
(quy tắc `D4`). Mức Component chỉ vẽ cho container phức tạp nhất, không vẽ cho tất cả.
|
||||
|
||||
**c. Bảng `CMP-nn`** — mỗi container/component ghi: trách nhiệm (một câu) · **cái nó KHÔNG
|
||||
làm** · dữ liệu nó sở hữu · interface vào/ra · team sở hữu · `ASR` nào ép ra nó.
|
||||
|
||||
Cột "cái nó KHÔNG làm" là cột ngăn phình chức năng. Component không có ranh giới sẽ nuốt dần
|
||||
mọi thứ.
|
||||
|
||||
**d. Deployment view** — cái gì chạy ở đâu, mấy bản, ranh giới mạng, ranh giới tin cậy.
|
||||
|
||||
### 4 — Interface catalog `ICD` *(`--focus icd`)*
|
||||
|
||||
Điền `templates/interface-catalog.md`. Mọi lời gọi **vượt ranh giới container** phải có một
|
||||
dòng `IF-nnn`.
|
||||
|
||||
Bảy cột bắt buộc mỗi interface: hai đầu · giao thức · sync/async · **ai sở hữu contract** ·
|
||||
đường dẫn contract thật (OpenAPI/AsyncAPI/proto) · chính sách versioning · hành vi khi đầu kia hỏng.
|
||||
|
||||
Ba thứ phải chốt **một lần cho toàn hệ thống**, ghi thành `ADR`:
|
||||
|
||||
| # | Vấn đề | Vì sao chốt sớm |
|
||||
|---|---|---|
|
||||
| 1 | Số lớn (id, tiền) truyền dạng gì | 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, múi giờ | Trộn local time và UTC là bug không ai tìm ra |
|
||||
| 3 | Phân trang: offset hay cursor, có `hasNext` không | Offset không có `hasNext` ⇒ nút "trang sau" hỏng |
|
||||
|
||||
🔴 **Đối chiếu với `API` của bộ BA.** BA viết contract đề xuất và đánh dấu *"chờ BE xác nhận"*
|
||||
— `ICD` chính là chỗ xác nhận. Mọi endpoint trong `API` phải có `IF-nnn`; lệch nhau ⇒ ghi `OQ`,
|
||||
`ICD` thắng, và **báo lại cho BA cập nhật SRS**.
|
||||
|
||||
### 5 — Kiến trúc dữ liệu `DAT` *(`--focus dat`)*
|
||||
|
||||
Điền `templates/data-architecture.md`. Nguyên tắc `D7`: mỗi thực thể có **đúng một** chủ.
|
||||
|
||||
Sáu mục bắt buộc:
|
||||
|
||||
1. **Bảng ownership** — thực thể × hệ thống chủ × bản sao ở đâu × độ trễ tối đa cho phép
|
||||
2. **Mô hình dữ liệu mức khái niệm** — thực thể và quan hệ, chưa phải schema
|
||||
3. **Consistency** — chỗ nào cần mạnh, chỗ nào chấp nhận eventual và **trễ tối đa bao lâu**
|
||||
4. **Giao dịch xuyên service** — saga / outbox / 2PC / không có, kèm cách bù trừ khi lỗi
|
||||
5. **Phân loại dữ liệu** — công khai / nội bộ / cá nhân (PII) / nhạy cảm, kèm retention và
|
||||
cách xoá theo yêu cầu pháp lý
|
||||
6. **Migration** — nguồn, cách đối chiếu, **cách rollback**, cách chạy song song hai hệ thống
|
||||
|
||||
🔴 **Migration không có rollback là migration một chiều.** Trước khi cắt chuyển phải trả lời
|
||||
được: nếu sau 2 giờ phát hiện sai thì quay lại thế nào, dữ liệu phát sinh trong 2 giờ đó xử lý ra sao.
|
||||
|
||||
### 6 — Kiến trúc bảo mật `SEC` *(`--focus sec`)*
|
||||
|
||||
Điền `templates/security-architecture.md`. Bốn mục:
|
||||
|
||||
**a. Threat model STRIDE** cho mỗi luồng nhạy cảm (đăng nhập, thanh toán, dữ liệu cá nhân,
|
||||
thao tác quản trị). Mỗi `THR-nn`: mối đe doạ · thành phần bị nhắm · biện pháp · **cách kiểm
|
||||
chứng biện pháp có hiệu lực**.
|
||||
|
||||
**b. Mô hình xác thực** — cơ chế, nơi giữ trạng thái, thời hạn, cách thu hồi, cách xoay khoá.
|
||||
|
||||
**c. Mô hình phân quyền** — RBAC/ABAC, **chỗ ra quyết định** (gateway hay service), và bảng
|
||||
map `ROLE-nn` của bộ BA xuống quyền kỹ thuật. Mỗi ô ghi rõ có ràng buộc dữ liệu không (ví dụ
|
||||
"chỉ cửa hàng mình phụ trách").
|
||||
|
||||
**d. Dữ liệu nhạy cảm** — phân loại, mã hoá at-rest/in-transit, quản lý secret, audit log ghi gì.
|
||||
|
||||
🔴 **Security có quyền phủ quyết AG2.** Đưa họ vào từ đầu bước này, không phải lúc trình gate.
|
||||
Phát hiện muộn nhất và đau nhất luôn đến từ đây.
|
||||
|
||||
### 7 — Hạ tầng & triển khai `INF` *(`--focus inf`)*
|
||||
|
||||
Điền `templates/infrastructure-design.md`. Năm mục:
|
||||
|
||||
1. **Topology môi trường** — dev/stg/prod khác nhau chỗ nào, và **chỗ khác nhau đó có làm sai
|
||||
lệch kết quả đo `QAS` không**
|
||||
2. **HA** — chịu được mất gì (một node / một AZ / một vùng), cơ chế chuyển đổi, thời gian chuyển
|
||||
3. **DR** — **RTO và RPO bằng số**, cách khôi phục, **lần diễn tập gần nhất là khi nào**
|
||||
4. **Scale** — dọc/ngang, ngưỡng kích hoạt, giới hạn trên, thời gian scale mất bao lâu
|
||||
5. **Observability** — log/metric/trace ghi gì, giữ bao lâu, ai đọc, **chi phí bao nhiêu**
|
||||
|
||||
🔴 **RTO/RPO chưa diễn tập là RTO/RPO trên giấy.** Ghi rõ ngày diễn tập gần nhất; chưa từng
|
||||
diễn tập ⇒ `Confidence` 🔴 và tạo `ARISK`.
|
||||
|
||||
`INF` phải **khớp số với `TCO`** (quy tắc `D9`). Lệch ⇒ một trong hai sai.
|
||||
|
||||
### 8 — Đường lỗi `FAIL` *(`--focus fail`)*
|
||||
|
||||
Điền `templates/failure-mode.md`. **Đây là phần phân biệt SA giỏi và SA vẽ sơ đồ**, và là
|
||||
phần bị bỏ nhiều nhất.
|
||||
|
||||
Mỗi phụ thuộc vượt ranh giới process (HTTP, DB, cache, queue, file, hệ thống ngoài) phải trả
|
||||
lời **bốn câu** của quy tắc `D6`, và ghi bảng:
|
||||
|
||||
| Phụ thuộc | Timeout | Retry | Idempotent | Hết retry thì sao | Người dùng thấy gì | `QAS` liên quan |
|
||||
|---|---|---|---|---|---|---|
|
||||
|
||||
Bốn câu bắt buộc mỗi phụ thuộc:
|
||||
|
||||
1. **Nó chậm thì sao?** — nguy hiểm hơn hỏng, vì nó giữ tài nguyên và lan ngược lên
|
||||
2. **Nó hỏng thì sao?** — degrade được không, hay chết cả luồng
|
||||
3. **Nó trả sai dữ liệu thì sao?** — có phát hiện được không
|
||||
4. **Nó hồi phục thì sao?** — retry storm, thundering herd, cần backpressure không
|
||||
|
||||
Cộng ba cơ chế phải quyết định cho toàn hệ thống: circuit breaker (ngưỡng mở/đóng) ·
|
||||
backoff (kiểu, jitter) · bulkhead (tách pool tài nguyên).
|
||||
|
||||
### 9 — Viết `ADR` — chạy liên tục
|
||||
|
||||
Điền `templates/adr.md`. Mỗi quyết định đạt ngưỡng ở `../sa-lifecycle/references/decision-radar.md`
|
||||
⇒ một file `adr/ADR-<nnn>_<slug>.md`.
|
||||
|
||||
Quy tắc `D1`: một ADR, một quyết định. Quy tắc `D3`: bắt buộc nêu phương án đã loại.
|
||||
|
||||
Điểm radar ≥ 8 ⇒ **không được chuyển `Accepted` khi chưa có POC hoặc bài đo**. Giữ ở
|
||||
`Proposed` và tạo mục trong `ARISK`.
|
||||
|
||||
## Trước khi kết thúc
|
||||
|
||||
In bốn thứ:
|
||||
|
||||
**① Bảng tự chấm Gate AG2** (`../sa-lifecycle/references/workflow.md` §2) dạng ☐/✅.
|
||||
|
||||
**② Checklist D1–D12** dạng ☐/✅.
|
||||
|
||||
**③ Bảng đối chiếu với bộ BA** — `NFR`↔`QAS`, `API`↔`ICD`, `RBAC`↔`SEC`, `BR`↔`ADR`. Mọi chỗ
|
||||
lệch phải liệt kê kèm hành động ("BA cập nhật SRS §… theo `IF-007`").
|
||||
|
||||
**④ Danh sách `OQ` mở** kèm người phải trả lời và **hệ quả nếu trả lời ngược**.
|
||||
|
||||
Rồi nhắc người dùng: AG2 cần **Tech Lead + Security + Ops/SRE ký**.
|
||||
|
||||
## Bẫy thường gặp
|
||||
|
||||
**Vẽ sơ đồ trước khi lượng hoá NFR.** Sơ đồ vẽ trước sẽ được bảo vệ bằng mọi giá sau đó. Làm
|
||||
`QAS` trước — con số sẽ tự loại phần lớn phương án và sơ đồ trở nên dễ vẽ.
|
||||
|
||||
**Chia service theo tầng thay vì theo nghiệp vụ.** "Service API, service business, service
|
||||
data" là monolith bị cắt sai chỗ: mọi thay đổi nghiệp vụ đều phải sửa cả ba, deploy cả ba.
|
||||
Cắt theo bounded context.
|
||||
|
||||
**Sơ đồ đẹp, mũi tên không nhãn.** Mũi tên không ghi giao thức và sync/async không mang thông
|
||||
tin. Kiểm tra: che phần chữ đi, sơ đồ còn nói được gì không?
|
||||
|
||||
**Bỏ qua đường lỗi vì "sẽ xử lý lúc code".** Lúc code, mỗi dev xử lý một kiểu, và không ai
|
||||
biết tổng thể hệ thống hỏng thế nào. Đây là nguồn của phần lớn sự cố production.
|
||||
|
||||
**Ghi ADR sau khi đã code xong.** ADR viết sau là biên bản hợp thức hoá, không phải quyết
|
||||
định. Giá trị của ADR nằm ở chỗ nó buộc phải nêu phương án đã loại **trước khi** cam kết.
|
||||
|
||||
**Thiết kế cho tải chưa bao giờ tới.** `QAS` nói tải × 3 trong 2 năm thì thiết kế cho × 3, đừng
|
||||
thiết kế cho × 100. Ghi vào "Ngoài phạm vi": *"Kiến trúc này không nhắm tới tải × 100; ngưỡng
|
||||
phải xét lại là …"*.
|
||||
Reference in New Issue
Block a user