Source document
docs/operations/PARTNER-OPERATIONS.md
Source version
0.0.0
Generated time
2026-07-06T14:59:19.317Z
Owner
Unassigned
Audience
Internal
Status
Approved

Partner Operations Guide (Beta-4)

Sổ tay vận hành đối tác qua ops CLI — KHÔNG cần thao tác SQL trực tiếp. Mọi thao tác có audit.
Nguồn sự thật: packages/platform-infrastructure/src/ops/cli.ts. Vòng đời: ../platform/PARTNER-LIFECYCLE.md.
KHÔNG chứa secret. Raw API key chỉ hiển thị một lần lúc cấp/rotate — giao khách qua kênh an toàn.

Chạy CLI

cd packages/platform-infrastructure
# Cần DATABASE_URL trỏ tới Postgres tương ứng (staging/prod đã kiểm soát).
npm run ops -- <command> [flags]
# Thêm --json để lấy output máy-đọc.
Các lệnh nguy hiểm (revoke-key, revoke-partner, churn-customer, outbox-replay) bắt buộc --confirm;
thiếu → exit 2, không thực thi.

Bảng lệnh Partner

ViệcLệnh
Tạo Partner (→ pending)create-partner --name <tên> [--contact c] [--owner o]
Gắn Tenant cho Partnercreate-tenant --partner <partnerId> --tenant <tenantId> [--name n]
Nạp inventory mẫu (để test Availability)seed-inventory --tenant <tenantId>
Kích hoạt (pending → active)activate-partner --partner <partnerId>
Suspend (active → suspended, thuận nghịch)suspend-partner --partner <partnerId> [--reason r]
Re-activate (suspended → active)reactivate-partner --partner <partnerId>
Revoke Partner (terminal, huỷ mọi key)revoke-partner --partner <partnerId> [--reason r] --confirm
Cấp API key`issue-key --customer <partnerId> --env <sandbox\production> [--deliver]`
Bàn giao key (pending_delivery → active)deliver-key --key <keyId>
Rotate API keyrotate-key --key <keyId> [--grace-days N] [--reason r]
Revoke API keyrevoke-key --key <keyId> --reason <r> --confirm
Xem hồ sơ/keys của Partnershow-provisioning [--customer <partnerId>]
Xem lịch sử audit của Partnershow-audit --partner <partnerId>
partnerId == customerId. issue-key dùng cờ --customer (tương thích lịch sử) nhưng nhận chính partnerId.

Quy trình chuẩn

1. Tạo Partner

npm run ops -- create-partner --name "Đối tác A" --owner ops@bng --json
# → { "partnerId": "…", "status": "pending" }

Partner ở pendingchưa dùng key được.

2. Kích hoạt

npm run ops -- create-tenant --partner <partnerId> --tenant t_partner_a --name "Tenant A"
npm run ops -- activate-partner --partner <partnerId>     # → active
issue-key yêu cầu Partner đã có Tenant (create-tenant).

3. Cấp key

npm run ops -- issue-key --customer <partnerId> --env sandbox --deliver --json
# In BANNER + raw key MỘT LẦN, rồi { keyId, prefix, environment, status:"active" }

4. Suspend

npm run ops -- suspend-partner --partner <partnerId> --reason nonpayment

Hiệu lực tức thì: mọi request của partner → 401. Key KHÔNG bị huỷ (thuận nghịch).

5. Re-activate

npm run ops -- reactivate-partner --partner <partnerId>

Đúng key cũ hoạt động trở lại — không cần cấp lại.

6. Revoke (chấm dứt)

npm run ops -- revoke-partner --partner <partnerId> --reason offboarding --confirm

Terminal: revoke mọi key. Không khôi phục (muốn dùng lại = tạo Partner mới).

7. Rotate API Key

npm run ops -- rotate-key --key <keyId> --json                 # cutover ngay: key cũ revoke
npm run ops -- rotate-key --key <keyId> --grace-days 7 --json  # key cũ còn dùng 7 ngày rồi hết hạn

In raw key mới một lần. Key cũ:

Quy trình xử lý khi NGHI NGỜ LỘ API KEY

Ưu tiên: cắt hiệu lực trước, điều tra sau. Guardrail bất khả xâm phạm = không để key lộ tiếp tục dùng được.
  1. Chặn ngay (chọn 1):

rotate-key để cấp key mới cho đối tác (hoặc issue-key mới).

(chặn toàn bộ key của partner tức thì, thuận nghịch — khôi phục nhanh sau khi xử lý).

  1. Cấp key thay thế: rotate-key (giữ lineage) hoặc issue-key --deliver, giao qua kênh an toàn.
  2. Điều tra: show-provisioning --customer <id> (xem lastUsedAt, prefix, status — không có raw/hash),

show-audit --partner <id> (lịch sử issue/rotate/revoke/suspend).

  1. Khôi phục: sau khi đã rotate + xác minh, reactivate-partner (nếu đã suspend).
  2. Ghi nhận: lý do đã nằm trong revokedReason/audit. Không dán raw key vào ticket/log.
Raw key không lưu ở đâu (DB chỉ giữ hash sha256). "Xem lại" key cũ là không thể — mất/lộ ⇒ rotate.

An toàn & bảo mật