@xemahq/entitlement-client 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installation-license.d.ts","sourceRoot":"","sources":["../../src/lib/installation-license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InstallationLicense = exports.DISTRIBUTION_UNDECLARED_REFUSAL = exports.LicenseRefusalKind = exports.LICENSE_ENV_VAR = void 0;
4
+ exports.worstWarningSeverity = worstWarningSeverity;
5
+ exports.isUnprovisionedBuildRefusal = isUnprovisionedBuildRefusal;
6
+ const entitlement_1 = require("@xemahq/kernel-contracts/entitlement");
7
+ const license_verifier_1 = require("@xemahq/license-verifier");
8
+ const license_warnings_ts_1 = require("./license-warnings.js");
9
+ exports.LICENSE_ENV_VAR = 'XEMA_LICENSE';
10
+ var LicenseRefusalKind;
11
+ (function (LicenseRefusalKind) {
12
+ LicenseRefusalKind["Unverifiable"] = "unverifiable";
13
+ LicenseRefusalKind["NotEntitled"] = "not-entitled";
14
+ LicenseRefusalKind["DistributionUndeclared"] = "distribution-undeclared";
15
+ })(LicenseRefusalKind || (exports.LicenseRefusalKind = LicenseRefusalKind = {}));
16
+ exports.DISTRIBUTION_UNDECLARED_REFUSAL = {
17
+ kind: LicenseRefusalKind.DistributionUndeclared,
18
+ remediation: 'Mount the distribution lock (XEMA_DISTRIBUTION_LOCK_PATH) so this ' +
19
+ 'deployment declares which Xema distribution it runs, or set ' +
20
+ 'XEMA_DISTRIBUTION_ID explicitly.',
21
+ };
22
+ class InstallationLicense {
23
+ config;
24
+ verification;
25
+ highestObservedTimeMs;
26
+ constructor(config) {
27
+ this.config = config;
28
+ }
29
+ evaluate(query, options = {}) {
30
+ const effective = this.effective();
31
+ if (!effective.ok) {
32
+ return {
33
+ granted: false,
34
+ refusal: {
35
+ kind: LicenseRefusalKind.Unverifiable,
36
+ code: effective.code,
37
+ message: effective.message,
38
+ remediation: (0, license_warnings_ts_1.platformLicenseRemediation)(effective.code),
39
+ },
40
+ };
41
+ }
42
+ const decision = (0, license_verifier_1.evaluateEntitlement)(effective.license, query, this.stateOptions(options));
43
+ this.observe(decision.state.evaluatedAtMs);
44
+ if (decision.granted) {
45
+ return {
46
+ granted: true,
47
+ matched: decision.matched,
48
+ state: decision.state,
49
+ };
50
+ }
51
+ return {
52
+ granted: false,
53
+ refusal: {
54
+ kind: LicenseRefusalKind.NotEntitled,
55
+ reason: decision.reason,
56
+ state: decision.state,
57
+ },
58
+ };
59
+ }
60
+ entitlementSet(options = {}) {
61
+ if (!this.effective().ok) {
62
+ return entitlement_1.COMMUNITY_ENTITLEMENT;
63
+ }
64
+ return (0, entitlement_1.projectEntitlementSet)((capabilityClassId) => this.evaluate({
65
+ kind: license_verifier_1.EntitlementKind.CapabilityClass,
66
+ id: capabilityClassId,
67
+ action: license_verifier_1.EntitlementAction.RunExisting,
68
+ }, options).granted);
69
+ }
70
+ editionQuery() {
71
+ const { distributionId } = this.config;
72
+ if (distributionId === null) {
73
+ return null;
74
+ }
75
+ return {
76
+ kind: license_verifier_1.EntitlementKind.Distribution,
77
+ id: distributionId,
78
+ action: license_verifier_1.EntitlementAction.RunExisting,
79
+ };
80
+ }
81
+ editionGate(options = {}) {
82
+ const query = this.editionQuery();
83
+ if (query === null) {
84
+ return { granted: false, refusal: exports.DISTRIBUTION_UNDECLARED_REFUSAL };
85
+ }
86
+ return this.evaluate(query, options);
87
+ }
88
+ biomeInstallGate(biomeId, options = {}) {
89
+ const edition = this.editionGate(options);
90
+ if (!edition.granted) {
91
+ return edition;
92
+ }
93
+ return this.evaluate({
94
+ kind: license_verifier_1.EntitlementKind.Biome,
95
+ id: biomeId,
96
+ action: license_verifier_1.EntitlementAction.Install,
97
+ }, options);
98
+ }
99
+ distributionEntitled(options = {}) {
100
+ return this.editionGate(options).granted;
101
+ }
102
+ posture(options = {}) {
103
+ const effective = this.effective();
104
+ if (!effective.ok) {
105
+ return {
106
+ licensed: false,
107
+ source: effective.source,
108
+ code: effective.code,
109
+ message: effective.message,
110
+ remediation: (0, license_warnings_ts_1.platformLicenseRemediation)(effective.code),
111
+ entitlement: entitlement_1.COMMUNITY_ENTITLEMENT,
112
+ distributionId: this.config.distributionId,
113
+ distributionEntitled: false,
114
+ warnings: [
115
+ {
116
+ code: license_warnings_ts_1.LicenseWarningCode.Unverifiable,
117
+ severity: license_warnings_ts_1.LicenseWarningSeverity.Critical,
118
+ message: `No license could be verified (${effective.code}): ` +
119
+ `${effective.message}. Enterprise features are off and new biome ` +
120
+ 'installs are refused. Existing workloads keep running.',
121
+ },
122
+ ],
123
+ };
124
+ }
125
+ const state = (0, license_verifier_1.resolveLicenseState)(effective.license, this.stateOptions(options));
126
+ this.observe(state.evaluatedAtMs);
127
+ const distributionEntitled = this.distributionEntitled(options);
128
+ const warnings = (0, license_warnings_ts_1.licenseStateWarnings)(state);
129
+ if (this.config.distributionId === null) {
130
+ warnings.push({
131
+ code: license_warnings_ts_1.LicenseWarningCode.DistributionUndeclared,
132
+ severity: license_warnings_ts_1.LicenseWarningSeverity.Warning,
133
+ message: 'This deployment does not declare which distribution it is running ' +
134
+ '(no distribution lock is mounted), so the license cannot be checked ' +
135
+ 'against an edition at all. Mount the distribution lock.',
136
+ });
137
+ }
138
+ else if (!distributionEntitled) {
139
+ warnings.push({
140
+ code: license_warnings_ts_1.LicenseWarningCode.DistributionNotEntitled,
141
+ severity: license_warnings_ts_1.LicenseWarningSeverity.Critical,
142
+ message: `The license does not entitle this installation to run the ` +
143
+ `"${this.config.distributionId}" distribution. Mirroring the images ` +
144
+ 'does not confer the right to run them (decision D6). New biome ' +
145
+ 'installs and upgrades are refused; existing workloads keep running ' +
146
+ 'and no data is touched.',
147
+ });
148
+ }
149
+ const { claims } = effective.license;
150
+ return {
151
+ licensed: true,
152
+ source: effective.source,
153
+ licenseId: claims.licenseId,
154
+ customerId: claims.subject.customerId,
155
+ customerName: claims.subject.customerName,
156
+ tier: claims.tier,
157
+ state,
158
+ entitlement: this.entitlementSet(options),
159
+ distributionId: this.config.distributionId,
160
+ distributionEntitled,
161
+ warnings,
162
+ };
163
+ }
164
+ verifiedLicense() {
165
+ const effective = this.effective();
166
+ return effective.ok ? effective.license : undefined;
167
+ }
168
+ effective() {
169
+ this.verification ??= (0, license_verifier_1.resolveEffectiveLicense)({
170
+ customerLicense: this.config.customerLicense,
171
+ ...(this.config.trustStore !== undefined
172
+ ? { trustStore: this.config.trustStore }
173
+ : {}),
174
+ });
175
+ return this.verification;
176
+ }
177
+ stateOptions(options) {
178
+ return {
179
+ ...(options.now !== undefined ? { now: options.now } : {}),
180
+ ...(this.highestObservedTimeMs !== undefined
181
+ ? { highestObservedTimeMs: this.highestObservedTimeMs }
182
+ : {}),
183
+ };
184
+ }
185
+ observe(evaluatedAtMs) {
186
+ if (this.highestObservedTimeMs === undefined ||
187
+ evaluatedAtMs > this.highestObservedTimeMs) {
188
+ this.highestObservedTimeMs = evaluatedAtMs;
189
+ }
190
+ }
191
+ }
192
+ exports.InstallationLicense = InstallationLicense;
193
+ function worstWarningSeverity(warnings) {
194
+ let worst;
195
+ for (const warning of warnings) {
196
+ if (worst === undefined ||
197
+ SEVERITY_ORDER[warning.severity] > SEVERITY_ORDER[worst]) {
198
+ worst = warning.severity;
199
+ }
200
+ }
201
+ return worst;
202
+ }
203
+ const SEVERITY_ORDER = {
204
+ [license_warnings_ts_1.LicenseWarningSeverity.Info]: 0,
205
+ [license_warnings_ts_1.LicenseWarningSeverity.Warning]: 1,
206
+ [license_warnings_ts_1.LicenseWarningSeverity.Critical]: 2,
207
+ };
208
+ function isUnprovisionedBuildRefusal(refusal) {
209
+ return (refusal.kind === LicenseRefusalKind.Unverifiable &&
210
+ refusal.code === license_verifier_1.LicenseVerificationFailureCode.TrustStoreEmpty);
211
+ }
212
+ //# sourceMappingURL=installation-license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installation-license.js","sourceRoot":"","sources":["../../src/lib/installation-license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ForbiddenException } from '@nestjs/common';
2
+ import { type EntitlementQuery } from '@xemahq/license-verifier';
3
+ import { type LicenseRefusal } from './installation-license.ts';
4
+ export declare enum LicenseEnforcementErrorCode {
5
+ LicenseUnverifiable = "LICENSE_UNVERIFIABLE",
6
+ LicenseNotEntitled = "LICENSE_NOT_ENTITLED",
7
+ DistributionUndeclared = "LICENSE_DISTRIBUTION_UNDECLARED"
8
+ }
9
+ export declare function errorCodeFor(refusal: LicenseRefusal): LicenseEnforcementErrorCode;
10
+ export declare class LicenseRefusedException extends ForbiddenException {
11
+ readonly refusal: LicenseRefusal;
12
+ readonly query?: EntitlementQuery | undefined;
13
+ constructor(refusal: LicenseRefusal, query?: EntitlementQuery | undefined);
14
+ }
15
+ export declare function describeRefusal(refusal: LicenseRefusal, query?: EntitlementQuery): string;
16
+ //# sourceMappingURL=license-refused.exception.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-refused.exception.d.ts","sourceRoot":"","sources":["../../src/lib/license-refused.exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAanC,oBAAY,2BAA2B;IAErC,mBAAmB,yBAAyB;IAE5C,kBAAkB,yBAAyB;IAO3C,sBAAsB,oCAAoC;CAC3D;AAMD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,cAAc,GACtB,2BAA2B,CAa7B;AAUD,qBAAa,uBAAwB,SAAQ,kBAAkB;IAE3D,QAAQ,CAAC,OAAO,EAAE,cAAc;IAMhC,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB;gBANxB,OAAO,EAAE,cAAc,EAMvB,KAAK,CAAC,EAAE,gBAAgB,YAAA;CAapC;AAkCD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,gBAAgB,GACvB,MAAM,CAkER"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LicenseRefusedException = exports.LicenseEnforcementErrorCode = void 0;
4
+ exports.errorCodeFor = errorCodeFor;
5
+ exports.describeRefusal = describeRefusal;
6
+ const common_1 = require("@nestjs/common");
7
+ const license_verifier_1 = require("@xemahq/license-verifier");
8
+ const installation_license_ts_1 = require("./installation-license.js");
9
+ var LicenseEnforcementErrorCode;
10
+ (function (LicenseEnforcementErrorCode) {
11
+ LicenseEnforcementErrorCode["LicenseUnverifiable"] = "LICENSE_UNVERIFIABLE";
12
+ LicenseEnforcementErrorCode["LicenseNotEntitled"] = "LICENSE_NOT_ENTITLED";
13
+ LicenseEnforcementErrorCode["DistributionUndeclared"] = "LICENSE_DISTRIBUTION_UNDECLARED";
14
+ })(LicenseEnforcementErrorCode || (exports.LicenseEnforcementErrorCode = LicenseEnforcementErrorCode = {}));
15
+ function errorCodeFor(refusal) {
16
+ switch (refusal.kind) {
17
+ case installation_license_ts_1.LicenseRefusalKind.Unverifiable:
18
+ return LicenseEnforcementErrorCode.LicenseUnverifiable;
19
+ case installation_license_ts_1.LicenseRefusalKind.NotEntitled:
20
+ return LicenseEnforcementErrorCode.LicenseNotEntitled;
21
+ case installation_license_ts_1.LicenseRefusalKind.DistributionUndeclared:
22
+ return LicenseEnforcementErrorCode.DistributionUndeclared;
23
+ default: {
24
+ const exhaustive = refusal;
25
+ throw new TypeError(`unhandled refusal kind ${String(exhaustive)}`);
26
+ }
27
+ }
28
+ }
29
+ class LicenseRefusedException extends common_1.ForbiddenException {
30
+ refusal;
31
+ query;
32
+ constructor(refusal, query) {
33
+ super({
34
+ code: errorCodeFor(refusal),
35
+ message: describeRefusal(refusal, query),
36
+ ...(query === undefined
37
+ ? {}
38
+ : {
39
+ resource: { kind: query.kind, id: query.id, action: query.action },
40
+ }),
41
+ ...detailFor(refusal),
42
+ });
43
+ this.refusal = refusal;
44
+ this.query = query;
45
+ }
46
+ }
47
+ exports.LicenseRefusedException = LicenseRefusedException;
48
+ function detailFor(refusal) {
49
+ switch (refusal.kind) {
50
+ case installation_license_ts_1.LicenseRefusalKind.Unverifiable:
51
+ return {
52
+ verificationFailure: refusal.code,
53
+ remediation: refusal.remediation,
54
+ };
55
+ case installation_license_ts_1.LicenseRefusalKind.NotEntitled:
56
+ return {
57
+ denialReason: refusal.reason,
58
+ licenseStatus: refusal.state.status,
59
+ lifecycleStage: refusal.state.stage,
60
+ expiresAt: instantOrNull(refusal.state.expiresAtMs),
61
+ graceEndsAt: instantOrNull(refusal.state.graceEndsAtMs),
62
+ };
63
+ case installation_license_ts_1.LicenseRefusalKind.DistributionUndeclared:
64
+ return { remediation: refusal.remediation };
65
+ default: {
66
+ const exhaustive = refusal;
67
+ throw new TypeError(`unhandled refusal kind ${String(exhaustive)}`);
68
+ }
69
+ }
70
+ }
71
+ function describeRefusal(refusal, query) {
72
+ const subject = query === undefined
73
+ ? 'proceed'
74
+ : `${query.action} ${query.kind} "${query.id}"`;
75
+ if (refusal.kind === installation_license_ts_1.LicenseRefusalKind.Unverifiable) {
76
+ return (`Refused to ${subject}: no Xema license could be verified ` +
77
+ `(${refusal.code}). ${refusal.message}. ${refusal.remediation}`);
78
+ }
79
+ if (refusal.kind === installation_license_ts_1.LicenseRefusalKind.DistributionUndeclared) {
80
+ return (`Refused to ${subject}: this deployment does not declare which Xema ` +
81
+ 'distribution it is running, so its license cannot be checked against an ' +
82
+ `edition. ${refusal.remediation}`);
83
+ }
84
+ switch (refusal.reason) {
85
+ case license_verifier_1.EntitlementDenialReason.MalformedQuery:
86
+ return (`Refused to ${subject}: the resource identifier is not well-formed, ` +
87
+ 'so no entitlement could be checked against it. This is a ' +
88
+ 'defect in the caller, not in the license.');
89
+ case license_verifier_1.EntitlementDenialReason.LicenseNotYetValid:
90
+ return (`Refused to ${subject}: the license is dated in the future and is not ` +
91
+ 'yet in force. Either a renewal was applied early, or this machine’s ' +
92
+ 'clock is wrong — check NTP before replacing the license.');
93
+ case license_verifier_1.EntitlementDenialReason.LicenseRevoked:
94
+ return (`Refused to ${subject}: the Xema license for this installation has ` +
95
+ 'been revoked. Contact Xema.');
96
+ case license_verifier_1.EntitlementDenialReason.LicenseSuspended:
97
+ return (`Refused to ${subject}: the Xema license for this installation is ` +
98
+ 'suspended. Existing workloads keep running; nothing new is permitted ' +
99
+ 'until the hold is lifted.');
100
+ case license_verifier_1.EntitlementDenialReason.LicenseRestricted:
101
+ return (`Refused to ${subject}: the Xema license expired on ` +
102
+ `${instantOrNull(refusal.state.expiresAtMs) ?? 'an unknown date'} and ` +
103
+ `its 30-day grace period ended on ` +
104
+ `${instantOrNull(refusal.state.graceEndsAtMs) ?? 'an unknown date'}. ` +
105
+ 'Upgrades, new biome installs and new projects or organizations are ' +
106
+ 'refused. Existing workloads keep running and no data is affected — ' +
107
+ 'apply a renewed license to restore them.');
108
+ case license_verifier_1.EntitlementDenialReason.NoMatchingEntitlement:
109
+ return (`Refused to ${subject}: the Xema license for this installation is in ` +
110
+ 'force but grants nothing that covers it. Ask Xema to extend the ' +
111
+ 'license, then apply the reissued token.');
112
+ default: {
113
+ const exhaustive = refusal.reason;
114
+ throw new TypeError(`unhandled denial reason ${String(exhaustive)}`);
115
+ }
116
+ }
117
+ }
118
+ function instantOrNull(epochMs) {
119
+ return epochMs === null ? null : new Date(epochMs).toISOString();
120
+ }
121
+ //# sourceMappingURL=license-refused.exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-refused.exception.js","sourceRoot":"","sources":["../../src/lib/license-refused.exception.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { LicenseVerificationFailureCode, type LicenseState } from '@xemahq/license-verifier';
2
+ export declare enum LicenseWarningSeverity {
3
+ Info = "info",
4
+ Warning = "warning",
5
+ Critical = "critical"
6
+ }
7
+ export declare enum LicenseWarningCode {
8
+ ExpiringSoon = "license-expiring-soon",
9
+ InGracePeriod = "license-in-grace-period",
10
+ Restricted = "license-restricted",
11
+ Suspended = "license-suspended",
12
+ Revoked = "license-revoked",
13
+ NotYetValid = "license-not-yet-valid",
14
+ ClockRollback = "license-clock-rollback",
15
+ Unverifiable = "license-unverifiable",
16
+ DistributionNotEntitled = "license-distribution-not-entitled",
17
+ DistributionUndeclared = "license-distribution-undeclared"
18
+ }
19
+ export interface LicenseWarning {
20
+ readonly code: LicenseWarningCode;
21
+ readonly severity: LicenseWarningSeverity;
22
+ readonly message: string;
23
+ }
24
+ export declare const LICENSE_EXPIRY_NOTICE_WINDOW_MS: number;
25
+ export declare const LICENSE_CRITICAL_WINDOW_MS: number;
26
+ export declare function licenseStateWarnings(state: LicenseState): LicenseWarning[];
27
+ export declare function platformLicenseRemediation(code: LicenseVerificationFailureCode): string;
28
+ //# sourceMappingURL=license-warnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-warnings.d.ts","sourceRoot":"","sources":["../../src/lib/license-warnings.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,8BAA8B,EAC9B,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAalC,oBAAY,sBAAsB;IAChC,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAGD,oBAAY,kBAAkB;IAE5B,YAAY,0BAA0B;IAEtC,aAAa,4BAA4B;IAEzC,UAAU,uBAAuB;IAEjC,SAAS,sBAAsB;IAE/B,OAAO,oBAAoB;IAE3B,WAAW,0BAA0B;IAErC,aAAa,2BAA2B;IAExC,YAAY,yBAAyB;IAErC,uBAAuB,sCAAsC;IAM7D,sBAAsB,oCAAoC;CAC3D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAE1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AASD,eAAO,MAAM,+BAA+B,QAAkB,CAAC;AAO/D,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AASzD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,cAAc,EAAE,CA+G1E;AAYD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,8BAA8B,GACnC,MAAM,CAgDR"}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LICENSE_CRITICAL_WINDOW_MS = exports.LICENSE_EXPIRY_NOTICE_WINDOW_MS = exports.LicenseWarningCode = exports.LicenseWarningSeverity = void 0;
4
+ exports.licenseStateWarnings = licenseStateWarnings;
5
+ exports.platformLicenseRemediation = platformLicenseRemediation;
6
+ const license_verifier_1 = require("@xemahq/license-verifier");
7
+ var LicenseWarningSeverity;
8
+ (function (LicenseWarningSeverity) {
9
+ LicenseWarningSeverity["Info"] = "info";
10
+ LicenseWarningSeverity["Warning"] = "warning";
11
+ LicenseWarningSeverity["Critical"] = "critical";
12
+ })(LicenseWarningSeverity || (exports.LicenseWarningSeverity = LicenseWarningSeverity = {}));
13
+ var LicenseWarningCode;
14
+ (function (LicenseWarningCode) {
15
+ LicenseWarningCode["ExpiringSoon"] = "license-expiring-soon";
16
+ LicenseWarningCode["InGracePeriod"] = "license-in-grace-period";
17
+ LicenseWarningCode["Restricted"] = "license-restricted";
18
+ LicenseWarningCode["Suspended"] = "license-suspended";
19
+ LicenseWarningCode["Revoked"] = "license-revoked";
20
+ LicenseWarningCode["NotYetValid"] = "license-not-yet-valid";
21
+ LicenseWarningCode["ClockRollback"] = "license-clock-rollback";
22
+ LicenseWarningCode["Unverifiable"] = "license-unverifiable";
23
+ LicenseWarningCode["DistributionNotEntitled"] = "license-distribution-not-entitled";
24
+ LicenseWarningCode["DistributionUndeclared"] = "license-distribution-undeclared";
25
+ })(LicenseWarningCode || (exports.LicenseWarningCode = LicenseWarningCode = {}));
26
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
27
+ exports.LICENSE_EXPIRY_NOTICE_WINDOW_MS = 30 * MS_PER_DAY;
28
+ exports.LICENSE_CRITICAL_WINDOW_MS = 7 * MS_PER_DAY;
29
+ function licenseStateWarnings(state) {
30
+ const warnings = [];
31
+ if (state.clockRollbackDetected) {
32
+ warnings.push({
33
+ code: LicenseWarningCode.ClockRollback,
34
+ severity: LicenseWarningSeverity.Warning,
35
+ message: 'The system clock is behind the latest instant this installation has ' +
36
+ 'observed. License dates are being evaluated against a clock that may ' +
37
+ 'be wrong. Nothing has been denied because of it — check NTP.',
38
+ });
39
+ }
40
+ if (state.notYetValid) {
41
+ warnings.push({
42
+ code: LicenseWarningCode.NotYetValid,
43
+ severity: LicenseWarningSeverity.Critical,
44
+ message: 'The license is dated in the future and is not yet in force, so it ' +
45
+ 'grants nothing. Either a renewal was applied early or this machine’s ' +
46
+ 'clock is wrong.',
47
+ });
48
+ return warnings;
49
+ }
50
+ switch (state.status) {
51
+ case license_verifier_1.LicenseStatus.Active: {
52
+ if (state.expiresAtMs === null) {
53
+ return warnings;
54
+ }
55
+ const remaining = state.expiresAtMs - state.evaluatedAtMs;
56
+ if (remaining > exports.LICENSE_EXPIRY_NOTICE_WINDOW_MS) {
57
+ return warnings;
58
+ }
59
+ warnings.push({
60
+ code: LicenseWarningCode.ExpiringSoon,
61
+ severity: remaining <= exports.LICENSE_CRITICAL_WINDOW_MS
62
+ ? LicenseWarningSeverity.Critical
63
+ : LicenseWarningSeverity.Warning,
64
+ message: `The license expires in ${describeDuration(remaining)} ` +
65
+ `(${formatInstant(state.expiresAtMs)}). Nothing is degraded yet: a ` +
66
+ '30-day grace period follows expiry during which the platform stays ' +
67
+ 'fully functional.',
68
+ });
69
+ return warnings;
70
+ }
71
+ case license_verifier_1.LicenseStatus.Expired: {
72
+ if (state.stage === license_verifier_1.LicenseLifecycleStage.Grace) {
73
+ const remaining = state.graceEndsAtMs === null
74
+ ? null
75
+ : state.graceEndsAtMs - state.evaluatedAtMs;
76
+ warnings.push({
77
+ code: LicenseWarningCode.InGracePeriod,
78
+ severity: remaining !== null && remaining <= exports.LICENSE_CRITICAL_WINDOW_MS
79
+ ? LicenseWarningSeverity.Critical
80
+ : LicenseWarningSeverity.Warning,
81
+ message: `The license expired on ${formatInstant(state.expiresAtMs)} and is ` +
82
+ 'in its grace period — the platform remains FULLY functional. ' +
83
+ (remaining === null
84
+ ? ''
85
+ : `In ${describeDuration(remaining)} `) +
86
+ 'upgrades, new biome installs and new projects or organizations ' +
87
+ 'will be refused. Running workloads are never stopped.',
88
+ });
89
+ return warnings;
90
+ }
91
+ warnings.push({
92
+ code: LicenseWarningCode.Restricted,
93
+ severity: LicenseWarningSeverity.Critical,
94
+ message: `The license expired on ${formatInstant(state.expiresAtMs)} and its ` +
95
+ `grace period ended on ${formatInstant(state.graceEndsAtMs)}. ` +
96
+ 'Upgrades, new biome installs and new projects or organizations are ' +
97
+ 'refused. Existing workloads keep running, no data is touched and no ' +
98
+ 'reads are blocked — apply a renewed license to restore them.',
99
+ });
100
+ return warnings;
101
+ }
102
+ case license_verifier_1.LicenseStatus.Suspended:
103
+ warnings.push({
104
+ code: LicenseWarningCode.Suspended,
105
+ severity: LicenseWarningSeverity.Critical,
106
+ message: 'The license is suspended. Upgrades, new biome installs and new ' +
107
+ 'projects or organizations are refused. Existing workloads keep ' +
108
+ 'running — contact Xema to lift the hold.',
109
+ });
110
+ return warnings;
111
+ case license_verifier_1.LicenseStatus.Revoked:
112
+ warnings.push({
113
+ code: LicenseWarningCode.Revoked,
114
+ severity: LicenseWarningSeverity.Critical,
115
+ message: 'The license has been revoked. It grants nothing, including the ' +
116
+ 'right to run what is already installed. Contact Xema.',
117
+ });
118
+ return warnings;
119
+ default: {
120
+ const exhaustive = state.status;
121
+ throw new TypeError(`unhandled license status ${String(exhaustive)}`);
122
+ }
123
+ }
124
+ }
125
+ function platformLicenseRemediation(code) {
126
+ switch (code) {
127
+ case license_verifier_1.LicenseVerificationFailureCode.TrustStoreEmpty:
128
+ return ('This BUILD carries no license verification keys — its license material ' +
129
+ 'was never provisioned, so it can verify no license at all, including ' +
130
+ 'the open-source one it ships with. This is a defect in the build, not ' +
131
+ 'in the license: deploy a released image, or run the signing ceremony ' +
132
+ 'documented in @xemahq/license-verifier before building one.');
133
+ case license_verifier_1.LicenseVerificationFailureCode.UnknownKeyId:
134
+ return ('The license was signed by a key this build does not trust — it was ' +
135
+ 'issued after this image shipped, or it is not a Xema license. Upgrade ' +
136
+ 'the platform image.');
137
+ case license_verifier_1.LicenseVerificationFailureCode.InvalidSignature:
138
+ return ('The license signature does not verify: the token was altered in ' +
139
+ 'transit or in storage. Re-copy it verbatim into the deployment secret ' +
140
+ 'that supplies XEMA_LICENSE.');
141
+ case license_verifier_1.LicenseVerificationFailureCode.MalformedToken:
142
+ case license_verifier_1.LicenseVerificationFailureCode.MalformedHeader:
143
+ case license_verifier_1.LicenseVerificationFailureCode.MalformedClaims:
144
+ return ('The value supplied as XEMA_LICENSE is not a well-formed Xema license. ' +
145
+ 'Store the whole single-line token with no wrapping, quoting or ' +
146
+ 'truncation — a base64-encoded Secret value must decode to exactly the ' +
147
+ 'token.');
148
+ case license_verifier_1.LicenseVerificationFailureCode.UnsupportedClaimsVersion:
149
+ return ('The license uses a claim format newer than this build understands. ' +
150
+ 'Upgrade the platform image.');
151
+ case license_verifier_1.LicenseVerificationFailureCode.IssuerMismatch:
152
+ return ('The license names an issuer that is not the Xema licensing authority, ' +
153
+ 'so it is refused.');
154
+ default: {
155
+ const exhaustive = code;
156
+ throw new TypeError(`unhandled license verification failure ${String(exhaustive)}`);
157
+ }
158
+ }
159
+ }
160
+ function formatInstant(epochMs) {
161
+ return epochMs === null ? 'an unknown date' : new Date(epochMs).toISOString();
162
+ }
163
+ function describeDuration(ms) {
164
+ if (ms <= 0) {
165
+ return 'less than a day';
166
+ }
167
+ const days = Math.floor(ms / MS_PER_DAY);
168
+ if (days === 0) {
169
+ return 'less than a day';
170
+ }
171
+ return days === 1 ? '1 day' : `${days} days`;
172
+ }
173
+ //# sourceMappingURL=license-warnings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-warnings.js","sourceRoot":"","sources":["../../src/lib/license-warnings.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xemahq/entitlement-client",
3
- "version": "0.1.3",
4
- "description": "NestJS client for the Xema edition/entitlement primitive. Resolves per-org entitlement, applies a client-side deployment ceiling, and fails closed to the community edition on any error.",
3
+ "version": "0.2.1",
4
+ "description": "NestJS enforcement point for Xema entitlement. Resolves the installation license offline via @xemahq/license-verifier, gates biome installation and the running edition against it, and projects it onto the platform Edition + feature-flag axis. Fails closed.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
7
7
  "homepage": "https://xema.dev",
@@ -24,7 +24,8 @@
24
24
  "@nestjs/common": ">=10",
25
25
  "@nestjs/core": ">=10",
26
26
  "reflect-metadata": ">=0.1.12",
27
- "@xemahq/kernel-contracts": ">=0.57.0"
27
+ "@xemahq/kernel-contracts": ">=1.2.0",
28
+ "@xemahq/license-verifier": ">=0.1.0"
28
29
  },
29
30
  "peerDependenciesMeta": {
30
31
  "@nestjs/common": {
@@ -38,7 +39,7 @@
38
39
  }
39
40
  },
40
41
  "dependencies": {
41
- "@xemahq/platform-common": "^0.5.0"
42
+ "@xemahq/platform-common": "^0.7.4"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@nestjs/common": "11.1.13",
@@ -48,7 +49,8 @@
48
49
  "prettier": "3.6.2",
49
50
  "reflect-metadata": "0.2.2",
50
51
  "typescript": "5.9.3",
51
- "@xemahq/kernel-contracts": "^0.57.0"
52
+ "@xemahq/license-verifier": "0.1.3",
53
+ "@xemahq/kernel-contracts": "^8.0.1"
52
54
  },
53
55
  "exports": {
54
56
  ".": {
@@ -65,6 +67,7 @@
65
67
  "clean": "rm -rf dist",
66
68
  "build": "tsc -p tsconfig.json",
67
69
  "format": "prettier --write \"src/**/*.ts\"",
68
- "typecheck": "tsc -p tsconfig.json --noEmit"
70
+ "typecheck": "tsc -p tsconfig.typecheck.json",
71
+ "test": "node --experimental-transform-types --test \"src/lib/*.test.ts\""
69
72
  }
70
73
  }