Skip to content

Operations

1. Triển khai

Thuộc tínhGiá trị
Imageregistry/licensing:<tag>
Container Port3000 (ngoài 31120)
Base Path/v1/api/licensing
Snowflake worker11
Run modesRUN_MODE=startup (mặc định), RUN_MODE=migrate
Migration modebun run migrate / migrate:dev — seed permissions + Policy free-trial (tất cả alwaysRun)
ProbesGET /healthz (live), GET /readyz (ready) — mặc định IGNIS
Phụ thuộc lúc bootPostgreSQL (schema licensing), Redis cache, Identity JWKS

Traefik labels

yaml
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.licensing.rule=PathPrefix(`/v1/api/licensing`)"
  - "traefik.http.services.licensing.loadbalancer.server.port=3000"

Script build & run

ScriptMục đích
bun run rebuildClean + compile (luôn dùng cái này; prestart/pretest/premigrate nối vào nó)
bun run server:devDev server (NODE_ENV=development, .env.development)
bun run migrate:devChạy migrations / seeds
bun run testTests (cần .env.test)
bun run lint:fixESLint + Prettier

2. Observability

Tín hiệuNguồnXem ở đâu
Logsstdout (key-value có cấu trúc, key: %s)kubectl logs <pod> / Loki
HealthGET /healthz, GET /readyzPortal gateway
Audit trailbảng licensing.LicenseEventchỉ query DB — không endpoint REST nào đăng ký (RestPaths.LICENSE_EVENTS tồn tại nhưng chưa wire)

Trường log & tín hiệu chính

Trường / messageNguồnGhi chú
requestIdheader X-Request-IdLan truyền xuyên service
Ed25519 private key not configuredwarn publishCertificate()Cert đang bị bỏ qua — consumer thấy null
Application secret not configuredwarn publishCertificate()Như trên
Failed to update lastValidatedAterror validate()Không nghiêm trọng (fire-and-forget)
Failed to verify license certificateLicenseMiddleware (phía consumer)Cert sai/hết hạn/bị sửa → fail-open null

Loại sự kiện audit (LicenseEventTypes)

created · activated · deactivated · suspended · reinstated · renewed · expired · revoked. (Không validated, không heartbeat.)

3. Bảo mật

Mối quan tâmGiảm thiểu
AuthNJWT (ES256, JWKS từ identity) hoặc HTTP Basic
AuthZCasbin qua PolicyDefinition; permission seed bởi migration 0001/0003/0004. Route read License tạm authorize.skip — xem ADR-0003
Khoá ký certPrivate key Ed25519 trong APP_ENV_LICENSING_ED25519_PRIVATE_KEY — K8s Secret, không bao giờ trong code
Secret payload certAPP_ENV_APPLICATION_SECRET (AES-256-GCM) — phải khớp giữa signer và mọi verifier
Chống giả mạo certChữ ký Ed25519; verifier từ chối alg lạ và chữ ký sai
Hết hạn certcertExpiresAt trong payload + Redis EX — cả hai giới hạn bởi APP_ENV_LICENSING_CERT_TTL_SECONDS
SecretsK8s Secret, mount như env
TLSKết thúc tại gateway
Network policyCilium — chỉ cho gateway + Redis + Postgres + JWKS identity

Tin cậy fail-open: LicenseMiddleware coi Redis miss / xác minh thất bại / hết hạn là null ("unknown"), không phải "unlicensed". Cổng consumer phải quyết định rõ ràng cách xử lý null.

4. Runbook

4.1 Lớp cảnh báo

Cảnh báoKích hoạtKiểm traKhắc phụcLeo thang
licensingHighErrorRate5xx >5% trong 5mlogs level=errorKiểm kết nối DB / Redisbackend on-call
licensingCertsSkippedwarn key not configured lặp lạixác nhận env Ed25519 + app-secret đã đặtkhôi phục secret, re-publish (xem 4.2)backend on-call
licensingExpiryDriftlicense qua expiresAt vẫn ACTIVATEDkỳ vọng — hết hạn là lazytrigger validate, hoặc chạy quét thủ côngdoc — thường không phải sự cố

4.2 Thao tác thường gặp

Thao tácCách làm
Tail logskubectl logs -n <ns> -f deploy/licensing
Chạy migration / seedRUN_MODE=migrate bun run migrate (trong pod)
Ép làm tươi cert cacheKhông có endpoint riêng. Trigger bất kỳ hành động vòng đời nào re-publish: suspendreinstate, hoặc renew. CRUD PATCH /licenses/{id} và sửa feature không re-publish.
Xem audit trailQuery trực tiếp licensing.LicenseEvent (không bề mặt REST)
Giải phóng một seat activationDELETE /activations/{id} (không sự kiện audit) hoặc ActivationService.deactivate() (ghi sự kiện)

4.3 Xoay keypair Ed25519

Xoay public key trên consumer trước, rồi private key trên licensing, rồi re-publish. Xoay private key mà không re-publish để lại cert cũ không xác minh được (consumer fail-open về null).

4.4 Lưu ý đã biết (không phải bug)

Hành viChi tiết
Lazy expiryKhông reaper. Một license lật sang EXPIRED chỉ ở lần validate() tiếp theo. License không ai validate ở ACTIVATED quá hạn.
Không heartbeat / floating seatIActivationConfig = { limit } thôi; không lastHeartbeatAt, không /validation/heartbeat.
Sửa feature không lan toảvalidate() đọc DB tươi (tức thì), nhưng cert cache chỉ làm tươi khi có hành động vòng đời.
Bypass activation trực tiếpPOST /activations bỏ qua kiểm giới hạn có lock; ưu tiên validate(fingerprint) để cưỡng chế giới hạn.
Va chạm SVC-00110Service code đụng với @nx/outreach — xem ADR-0002.

4.5 Yêu cầu consumer xuyên service

Mỗi service verifier phải đặt, khớp với signer:

BiếnYêu cầu
APP_ENV_APPLICATION_SECRETCùng giá trị với licensing (secret AES-256-GCM)
APP_ENV_LICENSING_ED25519_PUBLIC_KEYPublic key Ed25519 khớp (PEM)

5. Trang liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.