Skip to content

Architecture

1. Bối cảnh hệ thống (C4 L1)

2. Góc nhìn Container (C4 L2)

Không tồn tại container Kafka consumer, BullMQ worker, hay WebSocket emitter — service là một process REST duy nhất cộng một entry migration.

3. Góc nhìn Component (C4 L3) — Phân lớp nội bộ

LớpTrách nhiệm
RoutesBề mặt HTTP, khai báo trong RestPaths + definitions.ts theo từng controller
ControllersControllerFactory.defineCrudController (Policy/PolicyFeature/License/Activation) + handler vòng đời @post tuỳ chỉnh; cổng auth + permission
ServicesBusiness logic, transaction, re-publish chứng chỉ (LicenseManagementService, ActivationService, ValidationService)
LicensingBaseServiceBase dùng chung: sinh key, giải feature, publishCertificate(), logEvent(), createActivation()
RepositoriesRe-export từ @nx/core; soft-delete qua generateCommonColumnDefs
ComponentsChỉ Redis cache (phân phối cert + cache authz)

4. Chỉ mục máy trạng thái

EntityTrạng tháiSơ đồ
LicenseACTIVATED, SUSPENDED, EXPIRED, REVOKED→ nhảy tới

PolicyPolicyFeature dùng status vòng đời chung (ACTIVATED/DEACTIVATED/ARCHIVED) không có chuyển trạng thái có guard. Activation không có cột status — vòng đời của nó là create/delete.

License

TừSự kiệnĐếnĐiều kiện
* (mới)issueACTIVATEDPolicy phải tồn tại; sinh key; publish cert
ACTIVATEDsuspendSUSPENDEDPhải isActive() nếu không SUSPEND_INVALID_STATUS
SUSPENDEDreinstateACTIVATEDPhải SUSPENDED nếu không REINSTATE_INVALID_STATUS
ACTIVATEDvalidate (lazy)EXPIREDexpiresAt < now VÀ qua graceExpiresAt; UPDATE ... WHERE status=ACTIVATED có điều kiện
ACTIVATED/EXPIREDrenewACTIVATEDTừ chối REVOKED/SUSPENDED; Policy phải có duration (nếu không RENEW_PERPETUAL)
bất kỳ không-REVOKEDrevokeREVOKEDGuard idempotent REVOKE_ALREADY_REVOKED

Hết hạn là lazy. Không có reaper định kỳ. Một license lật sang EXPIRED chỉ khi ValidationService.validate() chạy và quan sát thấy expiresAt và cửa sổ grace đã qua cả hai.

5. Kịch bản runtime

5.1 Phát hành một license

5.2 Xác thực một key (lazy expiry + activation ngầm)

5.3 Kích hoạt một thiết bị (giới hạn seat an toàn với race)

5.4 Tiêu thụ chứng chỉ (service khác)

6. Mối quan tâm xuyên suốt

Mối quan tâmCách service này xử lý
AuthNJWT (Issuer = identity, JWKS) hoặc HTTP Basic — [AuthenticateStrategy.JWT, AuthenticateStrategy.BASIC] trên mọi route
AuthZCasbin qua PolicyDefinition; permission seed bởi migration 0001/0003/0004. Route read License tạm authorize.skip (ADR-0003)
i18ncột jsonb i18n ({ default, en, vi }) trên Policy.name/description, PolicyFeature.name/description, License.name
LoggingCó cấu trúc, key-value (key: %s); scope theo method qua this.logger.for(name)
TracingNo-op (chưa wire tracer)
IdempotencyFast-path activation (find theo licenseId+fingerprint trước lock); issueFreeTrial trả về trial có sẵn; lật expiry qua UPDATE có điều kiện; partial-unique index trên (licenseId, fingerprint)
ConcurrencySELECT … FOR UPDATE row-lock trên hàng License cho mọi mutation vòng đời và kiểm giới hạn activation
Soft-deleteLicense, Policy, Activation mang deletedAt (qua generateCommonColumnDefs); PolicyFeature & LicenseEvent tắt cột deleted
IDsSnowflake qua IdGenerator, worker 11

7. Trang liên quan

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