Skip to content

Domain Model

Cả năm bảng nằm trong schema PostgreSQL licensing và được định nghĩa trong @nx/core tại packages/core/src/models/schemas/licensing/. @nx/licensing chỉ re-export repository.

1. ERD đầy đủ

2. Entities

Policy

Thuộc tínhGiá trị
Tablelicensing.Policy
Sourcepackages/core/src/models/schemas/licensing/policy/schema.ts
Soft-deletecó (generateCommonColumnDefs)
Owner ID column- (template cấp hệ thống)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePrimary key
namejsonb (i18n)-Tên hiển thị { default, en, vi }
descriptionjsonb (i18n)-Tuỳ chọn
producttext-Định danh product (có index)
typetext-PolicyTypes (xem enum)
statustextACTIVATEDPolicyStatuses
sequenceinteger0Thứ tự hiển thị
durationjsonb (IDuration)-{ unit, value }; null = vĩnh viễn
activationjsonb (IActivationConfig)-{ limit }; null = không giới hạn thiết bị
gracePeriodjsonb (IDuration)-Mở rộng cửa sổ xác thực sau khi hết hạn

Enum type (PolicyTypes):

Giá trịMô tả
000_TRIALGói dùng thử (free trial seed dùng cái này)
100_SUBSCRIPTIONSubscription có giới hạn thời gian
200_PERPETUALKhông hết hạn (đặt duration: null)

Enum status (PolicyStatuses): ACTIVATED · DEACTIVATED · ARCHIVED.

Index: IDX trên product, type, status.

PolicyFeature

Thuộc tínhGiá trị
Tablelicensing.PolicyFeature
Sourcepackages/core/src/models/schemas/licensing/policy-feature/schema.ts
Soft-deletekhông (generateTzColumnDefs({ deleted: { enable: false } }))
Owner ID columnpolicyId

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePrimary key
policyIdtext-FK → Policy.id (cascade delete)
codetext-Khoá feature (vd MAX_ALLOCATION_LAYOUTS)
dataTypetext-boolean / number / text / json (từ generateDataTypeColumnDefs)
boValueboolean-Giá trị khi dataType=boolean
nValuenumeric-Giá trị khi dataType=number
tValuetext-Giá trị khi dataType=text
jValuejsonb-Giá trị khi dataType=json
namejsonb (i18n)-Tên hiển thị
descriptionjsonb (i18n)-Tuỳ chọn
sequenceinteger0Thứ tự hiển thị
statustextACTIVATEDPolicyFeatureStatuses (ACTIVATED/DEACTIVATED)

Giá trị đa hình: LicensingBaseService.DATA_TYPE_RESOLVERS đọc cột khớp với dataType. Một feature DEACTIVATED giải về mặc định theo từng kiểu (false/0/''/null).

Index & ràng buộc: UQ trên (policyId, code); IDX trên policyId, status; FK cascade khi delete.

License

Thuộc tínhGiá trị
Tablelicensing.License
Sourcepackages/core/src/models/schemas/licensing/license/schema.ts
Soft-delete
Owner ID columnentityType + entityId (principal đa hình)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePrimary key
policyIdtext-FK → Policy.id
keytext-License key (PREFIX-XXXX-XXXX-XXXX-XXXX)
namejsonb (i18n)-Tên hiển thị
statustextACTIVATEDLicenseStatuses (xem enum)
entityTypetext-LicensePrincipalTypes: Merchant / User
entityIdtext-Id principal
certificatetext-Envelope cert đã ký mới nhất (base64)
overridejsonb-{ activation, features } - ghi đè mặc định Policy
issuedAttimestamptznow()-
startsAttimestamptznow()Bắt đầu hiệu lực
expiresAttimestamptz-null = vĩnh viễn
graceExpiresAttimestamptz-Hết cửa sổ grace sau hết hạn
lastValidatedAttimestamptz-Cập nhật (fire-and-forget) mỗi lần validate thành công

Enum status (LicenseStatuses):

Giá trịMô tả
ACTIVATEDĐang hoạt động và dùng được
SUSPENDEDTạm vô hiệu (có thể reinstate)
EXPIREDQua expiresAt + grace (đặt lazy khi validate)
REVOKEDChấm dứt vĩnh viễn

isActive = chỉ ACTIVATED; isInactive = {SUSPENDED, REVOKED, EXPIRED}.

Index & ràng buộc: UQ partial-unique trên key (where deletedAt IS NULL); IDX trên policyId, status, (entityType, entityId), entityId, expiresAt; FK → Policy.id.

Activation

Thuộc tínhGiá trị
Tablelicensing.Activation
Sourcepackages/core/src/models/schemas/licensing/activation/schema.ts
Soft-delete
Owner ID columnlicenseId

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePrimary key
licenseIdtext-FK → License.id (cascade delete)
fingerprinttext-Fingerprint thiết bị
labeltext-Tên thiết bị thân thiện
platformtext-OS / platform
hostnametext-Hostname thiết bị
iptext-IP thấy gần nhất

Index & ràng buộc: UQ partial-unique trên (licenseId, fingerprint) (where deletedAt IS NULL) - một activation mỗi thiết bị mỗi license; IDX trên licenseId; FK cascade.

LicenseEvent

Thuộc tínhGiá trị
Tablelicensing.LicenseEvent
Sourcepackages/core/src/models/schemas/licensing/license-event/schema.ts
Soft-deletekhông (audit chỉ-thêm)
Owner ID columnlicenseId (nullable)

Trường:

TrườngKiểuBắt buộcMặc địnhMô tả
idtextSnowflakePrimary key
licenseIdtext-FK → License.id (ON DELETE SET NULL)
eventtext-LicenseEventTypes (created/activated/deactivated/suspended/reinstated/renewed/expired/revoked)
iptext--
userAgenttext--
datajsonb{}Payload theo sự kiện
metadatajsonb--

Index: IDX trên licenseId, event; FK ON DELETE SET NULL (event sống sót qua việc xoá license).

3. Bất biến xuyên entity

Bất biếnCách thực thi
Số activation ≤ activation.limitActivationService.activate / ValidationService.tryCreateActivation: SELECT License FOR UPDATE → re-COUNT trong tx → rollback nếu >= limit
Một activation mỗi (licenseId, fingerprint)Partial-unique index + fast path find-before-create
License key duy nhất trong các hàng còn sốngPartial-unique index trên key WHERE deletedAt IS NULL
Giá trị feature khớp dataTypeDATA_TYPE_RESOLVERS đọc cột có kiểu; DEACTIVATED → mặc định theo kiểu
renew yêu cầu Policy có durationLỗi RENEW_PERPETUAL nếu duration là null
Chứng chỉ phản ánh trạng thái license hiện tạiRe-publish sau mỗi mutation vòng đời (issue/suspend/reinstate/renew/revoke) và khi lazy expiry

4. Hành vi Soft-delete

EntitySoft-deleteHard-deleteGhi chú
Policycó (deletedAt)qua repoPolicyController xoá theo status (không hard delete trong app)
Licensequa repoMặc định đọc deletedAt IS NULL
Activationcascade từ License (FK)Deactivate dùng deleteById
PolicyFeaturekhôngcascade từ Policy (FK)Cột deleted bị tắt
LicenseEventkhôngFK SET NULL khi xoá licenseAudit chỉ-thêm

5. Trang liên quan

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