Checklist review API — GIW POC Identity Platform

Trạng thái: POC · Ngày: 21/09/2026 Dành cho: Architecture · Backend · Frontend · Security · Integration

Câu trả lời được điền theo đúng hành vi thực tế của POC. Dấu ⚠️ đánh dấu chỗ người review nên phản biện. Mang phản biện tới §10.


1. Kiến trúc

Câu hỏi Trả lời
Ai sở hữu từng API? HR verify → đội HR (TBC, T-HR-SOR). Entitlement, Session, Portal → nền tảng Galaxy. Keycloak → Galaxy CIAM.
Hệ gốc của tình trạng lao động là gì? Hệ thống HR. Không bao giờ là Keycloak. Trạng thái được tra lại ở mỗi lần đăng nhập và không bao giờ cache.
Hệ gốc của danh tính là gì? Keycloak (Galaxy ID). ADR-002.
Cái gì quyết định quyền truy cập? Entitlement Service, và không gì khác. Keycloak phát token rồi dừng.
Có service nào mở mạng trực tiếp không? Không. grant bắt buộc có entitlementId, nếu không thì trả 422.
Session có tách được khỏi Entitlement không? Có — hai service riêng, hai lệnh gọi riêng, ADR-006.
Thiết kế có sống sót khi HR sập không? Có: xác thực fail closed. Không cấp một phần, không có đường vòng qua cache.
⚠️ Dùng một OIDC client thứ hai để diễn đạt luồng nhân viên có đúng không? Nó chạy được và giữ portal ở vai một relying party thuần. Cái giá là hai audience và hai hình dạng token. Người review quyết.

2. Bảo mật

Câu hỏi Trả lời
Authorization Code + PKCE? Có, bắt buộc S256 trên cả hai client.
Đã tắt implicit/ROPC chưa? Đã tắt trên cả hai client.
state có dùng một lần không? Có, xoá ngay ở callback đầu tiên.
Có kiểm nonce của id_token không? Có.
Token có được verify đầy đủ ở phía sau không? Có — danh sách thuật toán cho phép, chữ ký JWKS, iss, aud, exp, nbf.
Bên gọi có tự khai danh tính của mình được không? Không. subjectId trong body mâu thuẫn với sub → 403.
Xác thực giữa các service? X-API-Key, so sánh thời gian hằng số. ⚠️ Secret dùng chung, tĩnh — production cần mTLS.
Có secret nào bị commit không? Không. .env đã git-ignore; khoá HR đến Keycloak qua biến môi trường, không qua realm-export.json.
TLS? ⚠️ HTTP thuần. Chỉ localhost.
Chống brute force? Bảo vệ ở cấp realm cho đăng nhập mật khẩu; 5 lần thử mỗi phiên xác thực trên form nhân viên. ⚠️ Theo phiên, nên vẫn lách được.
Giới hạn tần suất? Chỉ HR (30/60 s). ⚠️ Entitlement và Session chưa có.
Dò tìm danh sách tài khoản? Đã chặn: body giống hệt nhau, so sánh thời gian hằng số, quét đều, thông báo giao diện giống hệt nhau. Có test khẳng định.
Chống phát lại? Code dùng một lần, state bị đốt, kiểm nonce, có idempotency key trên các đường ghi.
⚠️ POST /admin/fault có xác thực không? Không, và phải xoá trước mọi lần triển khai. Nó tồn tại để thử các kịch bản hỏng.

3. Quyền riêng tư

Câu hỏi Trả lời
Có dữ liệu cá nhân không? Có — employeeId, email, sub.
Có dữ liệu cá nhân nhạy cảm không? Có — citizenId (CCCD), Luật 91/2025/QH15.
CCCD có được lưu không? Không. Không trong Keycloak, không trong service nào, không trong cache nào.
CCCD có bị ghi log không? Không. Có test tự động quét log cả năm container để cưỡng chế.
CCCD có trong token không? Không. Có test tự động duyệt mọi claim để cưỡng chế.
CCCD có trong response lỗi không? Không. Mô hình lỗi không có trường nào cho nó.
CCCD có được che trên giao diện không? Có, type=password, autocomplete="off", không trả lại khi thử thất bại.
Dữ liệu test có phải dữ liệu tổng hợp không? Có, và file có ghi rõ như vậy.
Có thu thập sự đồng ý không? ⚠️ Không. Production bắt buộc phải có cho đường CCCD.
Có đường xoá dữ liệu không? ⚠️ Không. Production bắt buộc.
Đã xác định Bên kiểm soát / Bên xử lý chưa? ⚠️ Chưa — quyết định D7 còn mở. POC này không được chạm vào dữ liệu HR thật cho tới khi chốt.
⚠️ Có nên dùng CCCD hay không? ADR-003 và D3 nói bỏ. POC này vẫn làm vì task order yêu cầu. Production: TBC.

4. Tích hợp

Câu hỏi Trả lời
Hợp đồng với HR có tối thiểu không? Có — phán quyết, employeeRef, trạng thái, công ty, điều kiện hưởng. Không tên, không phòng ban, không thông tin liên hệ.
Thử lại có an toàn không? HR verify: có, chỉ đọc. Đổi token: không, code chỉ dùng một lần. Entitlement/Session: có, nhờ idempotency key.
Idempotency đã triển khai hay chỉ nằm trong tài liệu? Đã triển khai và có test — tạo trùng và thu hồi trùng đều trả replayed: true.
Trùng danh tính thì sao? IDENTITY_LINK_CONFLICT, luồng dừng lại. Không đoán, không gộp im lặng.
Timeout có tường minh không? Có, trên mọi lệnh gọi đi ra. Giá trị là giả định của POC.
Nếu hợp đồng HR thay đổi thì sao? Bán kính ảnh hưởng là HrVerificationClient cộng bốn ánh xạ claim. Đổi tên một trường là chặn xác thực của mọi nhân viên — bắt buộc phải có phiên bản hoá trước khi HR là hệ thật.
Có callback bất đồng bộ không? Không. Khi thêm, nó cần correlationId, subjectId, sessionId, một idempotency key và chữ ký HMAC trên raw body — xem API-MATRIX.md §4 và ADR-009.

5. Xử lý lỗi

Câu hỏi Trả lời
Có một mô hình lỗi thống nhất không? Có, bốn trường, mọi API tự xây đều dùng.
Mã lỗi có ổn định và máy đọc được không? Có, 14 mã trong ERROR-CATALOG.md.
Lỗi có làm lộ nội bộ không? Không stack trace, không hostname, không body gốc của hệ phía trên.
Có lần hỏng nào lọt xuống thành cấp quyền không? Không. Mọi đường hỏng đều đã test và không đường nào cấp quyền.
Các trường hợp hỏng có được test không? Có — 11 trong 39 test là đường hỏng.

6. Khả năng quan sát

Câu hỏi Trả lời
Correlation ID? Có, X-Correlation-ID trên mọi request và response, tự sinh nếu thiếu.
Nó có đi suốt hành trình không? Có: Portal → Keycloak → Authenticator → HR → Entitlement → Session.
Nó có được dẫn xuất từ dữ liệu cá nhân không? Không — corr-<uuid4>, có chủ đích.
Log có cấu trúc không? Có, JSON một dòng ở mọi nơi.
Dấu vết audit có đủ để trả lời "vì sao người này được truy cập" không? Có: correlationId → employeeRef → entitlementId → sessionId.
Metric / tracing? ⚠️ Không có. Không Prometheus, không xuất OpenTelemetry.
Cảnh báo? ⚠️ Không có.

7. Hiệu năng

Câu hỏi Trả lời
Có ngân sách độ trễ công bố không? ⚠️ Không. Chỉ có timeout.
Timeout HR 3000 ms, 2 lần → tệ nhất khoảng 6 s trước khi người dùng thấy lỗi. ⚠️ Dài với một captive portal.
Đổi token 5000 ms
Entitlement / Session 5000 ms mỗi bên
Đã test tải chưa? ⚠️ Chưa. Chưa thử.
Nút thắt đã biết Bản đồ phiên của portal và cả hai kho trong bộ nhớ đều phình ra mà không có cơ chế loại bỏ.

8. Phiên bản và tương thích

Câu hỏi Trả lời
Cách đánh phiên bản? Theo đường dẫn URI, /api/v1/..., trên mọi API tự xây.
Các endpoint OIDC chuẩn? Keycloak đánh phiên bản; không thuộc quyền của chúng ta.
Quy tắc thay đổi phá vỡ tương thích Xoá một trường, đổi tên một trường, thu hẹp một kiểu, thêm một trường bắt buộc vào request, hay đổi code của lỗi đều là phá vỡ → cần /v2.
Không phá vỡ tương thích Thêm một trường tuỳ chọn vào request, thêm một trường vào response, thêm một code lỗi mới mà client hiện tại coi là không rõ.
Chính sách ngừng hỗ trợ ⚠️ Chưa định nghĩa. Đề xuất: thông báo, chạy song song v1 và v2 trong một chu kỳ phát hành, rồi gỡ.
Tương thích của claim trong token Thêm claim thì an toàn. Xoá hoặc đổi kiểu của user_type, employee_verified, employee_ref hay company sẽ phá việc đánh giá entitlement.
Nếu HR đổi hợp đồng Keycloak là bên tiêu thụ duy nhất nên bán kính ảnh hưởng nhỏ — nhưng nó nằm trên đường xác thực, nên một thay đổi âm thầm sẽ khoá mọi nhân viên ra ngoài. Bắt buộc có contract test trước khi HR là hệ thật.

9. Độ phủ test

Mảng Số test
Health 2
Luồng khách hàng 7
Luồng nhân viên 5
Trường hợp hỏng 11
Hợp đồng API 11
Chống lọt CCCD 2
Tổng 39, tất cả đều pass

Chạy: node tests/e2e.mjs

10. Ký duyệt của người review

Vai trò Tên Ngày Kết luận Phản biện
Architecture
Backend
Frontend
Security
Integration
Legal / DPO

Dòng Legal/DPO không phải tuỳ chọn. Câu hỏi về CCCD (§3, dòng cuối) không thể được đóng lại bởi năm vai trò còn lại.

GIW POC Identity Platform · bản demo local · không phải production · sinh từ repository