Mục tiêu: nền quản lý Partner để onboard đối tác đầu tiên chuẩn hoá, Founder điều hành không cần SQL thủ công.
Không mở rộng Platform Core · không Payment · không Frontend đầy đủ · không đổi deployment.
auth/api-key-store.ts): findActiveKey từ chối key nếu Partner chủ quản không active. ⇒ suspend/reactivate THUẬN NGHỊCH (không huỷ key). Không migration (customers.status đã có).
provisioning/provisioning-service.ts): createPartner(pending) · activatePartner · suspendPartner(reversible) · reactivatePartner · revokePartner(terminal) với guard invariant (PartnerTransitionError/PartnerNotFoundError); audit cho 7 thao tác (partner.* + apikey.issued/rotated/revoked), scope tenantId=partnerId, metadata sanitize.
ops/cli.ts): create-partner · create-tenant · seed-inventory · activate-partner · suspend-partner · reactivate-partner · revoke-partner(--confirm) · deliver-key · show-audit; issue-key thêm cờ opt-in --deliver (mặc định giữ nguyên pending_delivery). Transition sai → exit 2 (không throw thô, không 5xx).
docs/platform/PARTNER-LIFECYCLE.md — trạng thái, transition hợp lệ/không, invariant, audit.docs/operations/PARTNER-OPERATIONS.md — mọi thao tác + quy trình nghi lộ API key (không secret).docs/demo/PARTNER-MANAGEMENT-DEMO.md — 10 bước Founder tự chạy, mỗi bước có tiêu chí PASS.docs/platform/PARTNER-AUDIT-VERIFICATION.md — cách kiểm chứng audit (tự động + thủ công).platform-ci.yml → test:infra)partner-management-e2e.test.ts — luồng DoD qua HTTP thật: create→activate→issue→availability 200→rotate→key cũ 401→key mới 200→suspend→401→reactivate→200; assert đủ 7 audit event; assert không 5xx; assert key không bị huỷ khi suspend (bằng chứng thuận nghịch).
ops-partner.test.ts — vòng đời qua CLI (Founder path), invariant→exit 2, partner-không-tồn-tại→exit 2,bootstrap CLI trọn vẹn → key auth → suspend chặn → reactivate khôi phục, audit không lộ raw key.
npm run lint ✅ · npm run typecheck:all ✅npm run test:infra (Postgres ephemeral qua Docker): 185/185 PASS, 0 fail — gồm test mới + toàn bộ test cũ vẫn xanh.platform-ci.yml thật trên GitHub trong sprint này (đã verify cục bộ bằng chính lệnh CI dùng: lint + typecheck:all + test:infra). Job sẽ chạy khi push/PR lên main.provisionCustomer (tạo active, cho seed/back-compat) và createPartner (tạo pending, có audit) — không hợp nhất để tránh phá seed/Alpha.update và append có thể để lệch 1 event. *Giảm thiểu:* thao tác là single-row, cửa sổ hẹp. *Khắc phục:* Beta-5 gói prisma.$transaction.
customer mỗi lần auth key có customerId (Thấp): 2 point-lookup có index; chấp nhận được. *Tối ưu sau:* cache/@relation join khi cần (đo trước).
provisionCustomer active vs createPartner pending) (Thấp): có thể gây nhầm. *Giảm thiểu:* tài liệu nêu rõ; Beta-5 cân nhắc hợp nhất.revoke-partner terminal, không hoàn tác (Thấp, chủ ý): đúng thiết kế; khôi phục = tạo Partner mới.prisma.$transaction (khử rủi ro #1).provisionCustomer/createPartner về một API có status khởi tạo rõ ràng (giảm rủi ro #3), kèm test hồi quy seed/Alpha.platform-ci.yml trên PR; cân nhắc thêm job đo thời gian E2E.| Tiêu chí DoD | Kết quả |
|---|---|
| Founder quản lý Partner theo tài liệu demo | ✅ PARTNER-MANAGEMENT-DEMO.md 10 bước chạy được (CLI + curl) |
| API Key lifecycle đúng (issue/rotate/revoke, key cũ chết) | ✅ E2E: key cũ 401, key mới 200 |
| Suspend/Re-activate đúng | ✅ E2E: suspend→401, reactivate→200 (cùng key, thuận nghịch) |
| Audit đầy đủ | ✅ 7 event assert trong E2E + CLI |
| E2E PASS · CI PASS | ✅ 185/185 (lệnh CI cục bộ xanh); job chạy khi push main |
| Không lỗi 5xx | ✅ assert tường minh |
| Không cần thao tác DB trực tiếp | ✅ toàn bộ qua ops CLI |
| Ràng buộc QA | Kết quả |
|---|---|
| Không sửa Platform Core | ✅ packages/platform-core không đụng |
| Không đổi deployment | ✅ |
| Không ảnh hưởng Alpha/Legacy | ✅ test cũ 185 xanh; key legacy (customerId null) không hồi quy |
| Không phát sinh secret trong repo | ✅ secret scan sạch |
| Không migration ngoài phạm vi | ✅ 0 migration, schema.prisma không đổi |
Trạng thái Sprint: deliverable + DoD đạt trên kiểm chứng cục bộ (lint/typecheck/test:infra xanh, E2E phủ toàn luồng). Còn lại để "CI PASS" theo nghĩa quan sát: một lần chạy xanh platform-ci.yml khi mở PR lên main. Chờ Founder review.