@xemahq/license-verifier 0.1.0

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.
Files changed (98) hide show
  1. package/README.md +224 -0
  2. package/dist/bin/xema-license-keygen.d.ts +3 -0
  3. package/dist/bin/xema-license-keygen.d.ts.map +1 -0
  4. package/dist/bin/xema-license-keygen.js +63 -0
  5. package/dist/bin/xema-license-keygen.js.map +1 -0
  6. package/dist/bin/xema-license-mint-oss.d.ts +3 -0
  7. package/dist/bin/xema-license-mint-oss.d.ts.map +1 -0
  8. package/dist/bin/xema-license-mint-oss.js +70 -0
  9. package/dist/bin/xema-license-mint-oss.js.map +1 -0
  10. package/dist/embedded/license-material.generated.d.ts +4 -0
  11. package/dist/embedded/license-material.generated.d.ts.map +1 -0
  12. package/dist/embedded/license-material.generated.js +7 -0
  13. package/dist/embedded/license-material.generated.js.map +1 -0
  14. package/dist/index.d.ts +13 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +50 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lib/base64url.d.ts +4 -0
  19. package/dist/lib/base64url.d.ts.map +1 -0
  20. package/dist/lib/base64url.js +31 -0
  21. package/dist/lib/base64url.js.map +1 -0
  22. package/dist/lib/compact-jws.d.ts +16 -0
  23. package/dist/lib/compact-jws.d.ts.map +1 -0
  24. package/dist/lib/compact-jws.js +47 -0
  25. package/dist/lib/compact-jws.js.map +1 -0
  26. package/dist/lib/effective-license.d.ts +28 -0
  27. package/dist/lib/effective-license.d.ts.map +1 -0
  28. package/dist/lib/effective-license.js +39 -0
  29. package/dist/lib/effective-license.js.map +1 -0
  30. package/dist/lib/embedded-license.d.ts +7 -0
  31. package/dist/lib/embedded-license.d.ts.map +1 -0
  32. package/dist/lib/embedded-license.js +26 -0
  33. package/dist/lib/embedded-license.js.map +1 -0
  34. package/dist/lib/evaluate-entitlement.d.ts +28 -0
  35. package/dist/lib/evaluate-entitlement.d.ts.map +1 -0
  36. package/dist/lib/evaluate-entitlement.js +84 -0
  37. package/dist/lib/evaluate-entitlement.js.map +1 -0
  38. package/dist/lib/evaluate-limit.d.ts +18 -0
  39. package/dist/lib/evaluate-limit.d.ts.map +1 -0
  40. package/dist/lib/evaluate-limit.js +49 -0
  41. package/dist/lib/evaluate-limit.js.map +1 -0
  42. package/dist/lib/license-claims.d.ts +29 -0
  43. package/dist/lib/license-claims.d.ts.map +1 -0
  44. package/dist/lib/license-claims.js +3 -0
  45. package/dist/lib/license-claims.js.map +1 -0
  46. package/dist/lib/license-enums.d.ts +47 -0
  47. package/dist/lib/license-enums.d.ts.map +1 -0
  48. package/dist/lib/license-enums.js +58 -0
  49. package/dist/lib/license-enums.js.map +1 -0
  50. package/dist/lib/license-signer.d.ts +16 -0
  51. package/dist/lib/license-signer.d.ts.map +1 -0
  52. package/dist/lib/license-signer.js +35 -0
  53. package/dist/lib/license-signer.js.map +1 -0
  54. package/dist/lib/oss-license.d.ts +3 -0
  55. package/dist/lib/oss-license.d.ts.map +1 -0
  56. package/dist/lib/oss-license.js +27 -0
  57. package/dist/lib/oss-license.js.map +1 -0
  58. package/dist/lib/parse-license-claims.d.ts +8 -0
  59. package/dist/lib/parse-license-claims.d.ts.map +1 -0
  60. package/dist/lib/parse-license-claims.js +0 -0
  61. package/dist/lib/parse-license-claims.js.map +1 -0
  62. package/dist/lib/render-license-material.d.ts +8 -0
  63. package/dist/lib/render-license-material.d.ts.map +1 -0
  64. package/dist/lib/render-license-material.js +55 -0
  65. package/dist/lib/render-license-material.js.map +1 -0
  66. package/dist/lib/resolve-license-state.d.ts +20 -0
  67. package/dist/lib/resolve-license-state.d.ts.map +1 -0
  68. package/dist/lib/resolve-license-state.js +74 -0
  69. package/dist/lib/resolve-license-state.js.map +1 -0
  70. package/dist/lib/rfc3339.d.ts +2 -0
  71. package/dist/lib/rfc3339.d.ts.map +1 -0
  72. package/dist/lib/rfc3339.js +24 -0
  73. package/dist/lib/rfc3339.js.map +1 -0
  74. package/dist/lib/sign-license.d.ts +4 -0
  75. package/dist/lib/sign-license.d.ts.map +1 -0
  76. package/dist/lib/sign-license.js +27 -0
  77. package/dist/lib/sign-license.js.map +1 -0
  78. package/dist/lib/trust-store.d.ts +7 -0
  79. package/dist/lib/trust-store.d.ts.map +1 -0
  80. package/dist/lib/trust-store.js +32 -0
  81. package/dist/lib/trust-store.js.map +1 -0
  82. package/dist/lib/verification-failure.d.ts +17 -0
  83. package/dist/lib/verification-failure.d.ts.map +1 -0
  84. package/dist/lib/verification-failure.js +19 -0
  85. package/dist/lib/verification-failure.js.map +1 -0
  86. package/dist/lib/verified-license.d.ts +10 -0
  87. package/dist/lib/verified-license.d.ts.map +1 -0
  88. package/dist/lib/verified-license.js +8 -0
  89. package/dist/lib/verified-license.js.map +1 -0
  90. package/dist/lib/verify-license.d.ts +13 -0
  91. package/dist/lib/verify-license.d.ts.map +1 -0
  92. package/dist/lib/verify-license.js +98 -0
  93. package/dist/lib/verify-license.js.map +1 -0
  94. package/dist/signing.d.ts +4 -0
  95. package/dist/signing.d.ts.map +1 -0
  96. package/dist/signing.js +10 -0
  97. package/dist/signing.js.map +1 -0
  98. package/package.json +56 -0
@@ -0,0 +1,8 @@
1
+ export interface LicenseMaterial {
2
+ readonly publicKeyPems: readonly string[];
3
+ readonly ossLicense: string;
4
+ readonly provisioned: boolean;
5
+ readonly provenance: string;
6
+ }
7
+ export declare function renderLicenseMaterial(material: LicenseMaterial): string;
8
+ //# sourceMappingURL=render-license-material.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-license-material.d.ts","sourceRoot":"","sources":["../../src/lib/render-license-material.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAE9B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAE1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAE9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AA0BD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAyBvE"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderLicenseMaterial = renderLicenseMaterial;
4
+ const PROVISIONED_HEADER = `// GENERATED FILE — do not edit by hand.
5
+ //
6
+ // Written by the license signing ceremony (\`xema-license-mint-oss\`). It holds
7
+ // PUBLIC material only: the Ed25519 verification keys this build trusts, and
8
+ // the non-secret open-source license signed with the corresponding private
9
+ // key. The private key is held outside this repository and never appears here.`;
10
+ const PLACEHOLDER_HEADER = `// GENERATED FILE — do not edit by hand.
11
+ //
12
+ // ⚠️ PLACEHOLDER — THIS BUILD'S LICENSE MATERIAL HAS NOT BEEN PROVISIONED.
13
+ //
14
+ // The trust store below is EMPTY and the open-source license below is NOT
15
+ // SIGNED. Every verification against this material FAILS CLOSED:
16
+ // \`verifyLicense\` returns \`TrustStoreEmpty\`, and no license — including this
17
+ // one — is ever accepted.
18
+ //
19
+ // That is deliberate. The alternative, a token that verifies without a real
20
+ // signature, would mean the licensing plane accepts forgeries in exactly the
21
+ // builds nobody remembered to provision; a placeholder that refuses is loud
22
+ // and safe, a placeholder that passes is silent and fatal.
23
+ //
24
+ // Replace it by running the signing ceremony documented in the package
25
+ // README (\`xema-license-mint-oss --key <path outside this repo>\`).`;
26
+ function renderLicenseMaterial(material) {
27
+ const header = material.provisioned ? PROVISIONED_HEADER : PLACEHOLDER_HEADER;
28
+ const keys = material.publicKeyPems.length === 0
29
+ ? '[]'
30
+ : `[\n${material.publicKeyPems
31
+ .map((pem) => ` ${singleQuoted(pem)},\n`)
32
+ .join('')}]`;
33
+ return `${header}
34
+ //
35
+ // ${material.provenance}
36
+
37
+ /** Whether a real signing ceremony produced this material. */
38
+ export const LICENSE_MATERIAL_PROVISIONED = ${material.provisioned};
39
+
40
+ /** Ed25519 PUBLIC verification keys this build trusts, in PEM form. */
41
+ export const EMBEDDED_LICENSE_PUBLIC_KEYS: readonly string[] = ${keys};
42
+
43
+ /** The compiled-in open-source license (decision D1), as a compact JWS. */
44
+ export const EMBEDDED_OSS_LICENSE =
45
+ ${singleQuoted(material.ossLicense)};
46
+ `;
47
+ }
48
+ function singleQuoted(value) {
49
+ const escaped = JSON.stringify(value)
50
+ .slice(1, -1)
51
+ .replaceAll('\\"', '"')
52
+ .replaceAll("'", "\\'");
53
+ return `'${escaped}'`;
54
+ }
55
+ //# sourceMappingURL=render-license-material.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-license-material.js","sourceRoot":"","sources":["../../src/lib/render-license-material.ts"],"names":[],"mappings":";;AA6CA,sDAyBC;AAjDD,MAAM,kBAAkB,GAAG;;;;;gFAKqD,CAAC;AAEjF,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;sEAe2C,CAAC;AAEvE,SAAgB,qBAAqB,CAAC,QAAyB;IAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAI9E,MAAM,IAAI,GACR,QAAQ,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;QACjC,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,MAAM,QAAQ,CAAC,aAAa;aACzB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;aACzC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;IACrB,OAAO,GAAG,MAAM;;KAEb,QAAQ,CAAC,UAAU;;;8CAGsB,QAAQ,CAAC,WAAW;;;iEAGD,IAAI;;;;IAIjE,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;CACpC,CAAC;AACF,CAAC;AAOD,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SAClC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACZ,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC;SACtB,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,OAAO,IAAI,OAAO,GAAG,CAAC;AACxB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { LicenseLifecycleStage, LicenseStatus } from './license-enums.ts';
2
+ import type { VerifiedLicense } from './verified-license.ts';
3
+ export declare const DEFAULT_CLOCK_SKEW_TOLERANCE_MS = 60000;
4
+ export declare const MAX_CLOCK_SKEW_TOLERANCE_MS: number;
5
+ export interface ResolveLicenseStateOptions {
6
+ readonly now?: number;
7
+ readonly clockSkewToleranceMs?: number;
8
+ readonly highestObservedTimeMs?: number;
9
+ }
10
+ export interface LicenseState {
11
+ readonly status: LicenseStatus;
12
+ readonly stage: LicenseLifecycleStage;
13
+ readonly notYetValid: boolean;
14
+ readonly expiresAtMs: number | null;
15
+ readonly graceEndsAtMs: number | null;
16
+ readonly clockRollbackDetected: boolean;
17
+ readonly evaluatedAtMs: number;
18
+ }
19
+ export declare function resolveLicenseState(license: VerifiedLicense, options?: ResolveLicenseStateOptions): LicenseState;
20
+ //# sourceMappingURL=resolve-license-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-license-state.d.ts","sourceRoot":"","sources":["../../src/lib/resolve-license-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,EACrB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQ7D,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAOtD,eAAO,MAAM,2BAA2B,QAAa,CAAC;AAEtD,MAAM,WAAW,0BAA0B;IAEzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAMvC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAM3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAE/B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IAMtC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAQtC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAUD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,0BAA+B,GACvC,YAAY,CA2Dd"}
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_CLOCK_SKEW_TOLERANCE_MS = exports.DEFAULT_CLOCK_SKEW_TOLERANCE_MS = void 0;
4
+ exports.resolveLicenseState = resolveLicenseState;
5
+ const license_enums_ts_1 = require("./license-enums.js");
6
+ const rfc3339_ts_1 = require("./rfc3339.js");
7
+ exports.DEFAULT_CLOCK_SKEW_TOLERANCE_MS = 60_000;
8
+ exports.MAX_CLOCK_SKEW_TOLERANCE_MS = 5 * 60_000;
9
+ function resolveLicenseState(license, options = {}) {
10
+ const now = options.now ?? Date.now();
11
+ if (!Number.isFinite(now)) {
12
+ throw new TypeError('resolveLicenseState requires a finite `now`');
13
+ }
14
+ const skew = options.clockSkewToleranceMs ?? exports.DEFAULT_CLOCK_SKEW_TOLERANCE_MS;
15
+ if (!Number.isFinite(skew) ||
16
+ skew < 0 ||
17
+ skew > exports.MAX_CLOCK_SKEW_TOLERANCE_MS) {
18
+ throw new RangeError(`clockSkewToleranceMs must be within 0..${exports.MAX_CLOCK_SKEW_TOLERANCE_MS}, received ${skew}`);
19
+ }
20
+ const { claims } = license;
21
+ const issuedAtMs = (0, rfc3339_ts_1.parseRfc3339Utc)(claims.issuedAt);
22
+ if (issuedAtMs === null) {
23
+ throw new TypeError('a verified license carried an unparseable issuedAt');
24
+ }
25
+ let expiresAtMs = null;
26
+ if (claims.expiresAt !== null) {
27
+ expiresAtMs = (0, rfc3339_ts_1.parseRfc3339Utc)(claims.expiresAt);
28
+ if (expiresAtMs === null) {
29
+ throw new TypeError('a verified license carried an unparseable expiresAt');
30
+ }
31
+ }
32
+ const notYetValid = now + skew < issuedAtMs;
33
+ const graceEndsAtMs = expiresAtMs === null ? null : expiresAtMs + license_enums_ts_1.LICENSE_GRACE_PERIOD_MS;
34
+ const temporalStage = resolveTemporalStage(now, skew, expiresAtMs, graceEndsAtMs);
35
+ const status = resolveEffectiveStatus(claims.status, temporalStage);
36
+ const stage = notYetValid
37
+ ? license_enums_ts_1.LicenseLifecycleStage.Restricted
38
+ : restrictForStatus(temporalStage, claims.status);
39
+ return {
40
+ status,
41
+ stage,
42
+ notYetValid,
43
+ expiresAtMs,
44
+ graceEndsAtMs,
45
+ clockRollbackDetected: options.highestObservedTimeMs !== undefined &&
46
+ now < options.highestObservedTimeMs,
47
+ evaluatedAtMs: now,
48
+ };
49
+ }
50
+ function resolveTemporalStage(now, skew, expiresAtMs, graceEndsAtMs) {
51
+ if (expiresAtMs === null || graceEndsAtMs === null) {
52
+ return license_enums_ts_1.LicenseLifecycleStage.Valid;
53
+ }
54
+ if (now - skew <= expiresAtMs) {
55
+ return license_enums_ts_1.LicenseLifecycleStage.Valid;
56
+ }
57
+ if (now - skew <= graceEndsAtMs) {
58
+ return license_enums_ts_1.LicenseLifecycleStage.Grace;
59
+ }
60
+ return license_enums_ts_1.LicenseLifecycleStage.Restricted;
61
+ }
62
+ function resolveEffectiveStatus(claimed, temporalStage) {
63
+ if (claimed === license_enums_ts_1.LicenseStatus.Active &&
64
+ temporalStage !== license_enums_ts_1.LicenseLifecycleStage.Valid) {
65
+ return license_enums_ts_1.LicenseStatus.Expired;
66
+ }
67
+ return claimed;
68
+ }
69
+ function restrictForStatus(temporalStage, claimed) {
70
+ return claimed === license_enums_ts_1.LicenseStatus.Active
71
+ ? temporalStage
72
+ : license_enums_ts_1.LicenseLifecycleStage.Restricted;
73
+ }
74
+ //# sourceMappingURL=resolve-license-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-license-state.js","sourceRoot":"","sources":["../../src/lib/resolve-license-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function parseRfc3339Utc(value: string): number | null;
2
+ //# sourceMappingURL=rfc3339.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rfc3339.d.ts","sourceRoot":"","sources":["../../src/lib/rfc3339.ts"],"names":[],"mappings":"AAuBA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB5D"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRfc3339Utc = parseRfc3339Utc;
4
+ const RFC3339_UTC_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})T(?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})(?:\.\d{1,3})?Z$/;
5
+ function parseRfc3339Utc(value) {
6
+ const match = RFC3339_UTC_PATTERN.exec(value);
7
+ if (match?.groups === undefined) {
8
+ return null;
9
+ }
10
+ const parsed = Date.parse(value);
11
+ if (!Number.isFinite(parsed)) {
12
+ return null;
13
+ }
14
+ const date = new Date(parsed);
15
+ const { year, month, day, hour, minute, second } = match.groups;
16
+ const agrees = date.getUTCFullYear() === Number(year) &&
17
+ date.getUTCMonth() + 1 === Number(month) &&
18
+ date.getUTCDate() === Number(day) &&
19
+ date.getUTCHours() === Number(hour) &&
20
+ date.getUTCMinutes() === Number(minute) &&
21
+ date.getUTCSeconds() === Number(second);
22
+ return agrees ? parsed : null;
23
+ }
24
+ //# sourceMappingURL=rfc3339.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rfc3339.js","sourceRoot":"","sources":["../../src/lib/rfc3339.ts"],"names":[],"mappings":";;AAuBA,0CAsBC;AAnCD,MAAM,mBAAmB,GACvB,gHAAgH,CAAC;AAYnH,SAAgB,eAAe,CAAC,KAAa;IAC3C,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAGxD,CAAC;IACF,MAAM,MAAM,GACV,IAAI,CAAC,cAAc,EAAE,KAAK,MAAM,CAAC,IAAI,CAAC;QACtC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,UAAU,EAAE,KAAK,MAAM,CAAC,GAAG,CAAC;QACjC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,IAAI,CAAC;QACnC,IAAI,CAAC,aAAa,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,aAAa,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LicenseClaims } from './license-claims.ts';
2
+ import type { LicenseSigner } from './license-signer.ts';
3
+ export declare function signLicense(claims: LicenseClaims, signer: LicenseSigner): Promise<string>;
4
+ //# sourceMappingURL=sign-license.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-license.d.ts","sourceRoot":"","sources":["../../src/lib/sign-license.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,qBAAqB,CAAC;AAK3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAiBzD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CA4BjB"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signLicense = signLicense;
4
+ const compact_jws_ts_1 = require("./compact-jws.js");
5
+ const license_enums_ts_1 = require("./license-enums.js");
6
+ const parse_license_claims_ts_1 = require("./parse-license-claims.js");
7
+ async function signLicense(claims, signer) {
8
+ if (signer.algorithm !== license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA) {
9
+ throw new TypeError(`a Xema license must be signed with ${license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA}, signer offers ${signer.algorithm}`);
10
+ }
11
+ if (typeof signer.keyId !== 'string' || signer.keyId.length === 0) {
12
+ throw new TypeError('a license signer must expose a non-empty keyId');
13
+ }
14
+ const parsed = (0, parse_license_claims_ts_1.parseLicenseClaims)(JSON.parse(JSON.stringify(claims)));
15
+ if (!parsed.ok) {
16
+ throw new TypeError(`refusing to sign malformed license claims: ${parsed.message}`);
17
+ }
18
+ const header = {
19
+ alg: license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA,
20
+ kid: signer.keyId,
21
+ typ: license_enums_ts_1.LICENSE_JWS_TYPE,
22
+ };
23
+ const segments = (0, compact_jws_ts_1.encodeJwsSegments)(JSON.stringify(header), JSON.stringify(parsed.claims));
24
+ const signature = await signer.sign(segments.signingInput);
25
+ return (0, compact_jws_ts_1.assembleCompactJws)(segments, signature);
26
+ }
27
+ //# sourceMappingURL=sign-license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-license.js","sourceRoot":"","sources":["../../src/lib/sign-license.ts"],"names":[],"mappings":";;AAuBA,kCA+BC;AAtDD,qDAAyE;AAEzE,yDAG4B;AAE5B,uEAA+D;AAgBxD,KAAK,UAAU,WAAW,CAC/B,MAAqB,EACrB,MAAqB;IAErB,IAAI,MAAM,CAAC,SAAS,KAAK,4CAAyB,CAAC,KAAK,EAAE,CAAC;QACzD,MAAM,IAAI,SAAS,CACjB,sCAAsC,4CAAyB,CAAC,KAAK,mBAAmB,MAAM,CAAC,SAAS,EAAE,CAC3G,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,4CAAkB,EAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,8CAA8C,MAAM,CAAC,OAAO,EAAE,CAC/D,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAqB;QAC/B,GAAG,EAAE,4CAAyB,CAAC,KAAK;QACpC,GAAG,EAAE,MAAM,CAAC,KAAK;QACjB,GAAG,EAAE,mCAAgB;KACtB,CAAC;IACF,MAAM,QAAQ,GAAG,IAAA,kCAAiB,EAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EACtB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAC9B,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC3D,OAAO,IAAA,mCAAkB,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type KeyObject } from 'node:crypto';
2
+ export declare function computeLicenseKeyId(publicKeyPem: string): string;
3
+ export interface LicenseTrustStore {
4
+ readonly keys: ReadonlyMap<string, KeyObject>;
5
+ }
6
+ export declare function createLicenseTrustStore(publicKeyPems: readonly string[]): LicenseTrustStore;
7
+ //# sourceMappingURL=trust-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-store.d.ts","sourceRoot":"","sources":["../../src/lib/trust-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAsB1E,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAOhE;AAqBD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAC/C;AAeD,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,iBAAiB,CAcnB"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeLicenseKeyId = computeLicenseKeyId;
4
+ exports.createLicenseTrustStore = createLicenseTrustStore;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const base64url_ts_1 = require("./base64url.js");
7
+ const REQUIRED_KEY_TYPE = 'ed25519';
8
+ function computeLicenseKeyId(publicKeyPem) {
9
+ const key = (0, node_crypto_1.createPublicKey)({ key: publicKeyPem, format: 'pem' });
10
+ assertEd25519(key);
11
+ const spki = key.export({ format: 'der', type: 'spki' });
12
+ return (0, base64url_ts_1.encodeBase64Url)(new Uint8Array((0, node_crypto_1.createHash)('sha256').update(spki).digest()));
13
+ }
14
+ function assertEd25519(key) {
15
+ if (key.asymmetricKeyType !== REQUIRED_KEY_TYPE) {
16
+ throw new TypeError(`a Xema license key must be ${REQUIRED_KEY_TYPE}, received ${String(key.asymmetricKeyType)}`);
17
+ }
18
+ }
19
+ function createLicenseTrustStore(publicKeyPems) {
20
+ const keys = new Map();
21
+ for (const pem of publicKeyPems) {
22
+ const key = (0, node_crypto_1.createPublicKey)({ key: pem, format: 'pem' });
23
+ assertEd25519(key);
24
+ const keyId = computeLicenseKeyId(pem);
25
+ if (keys.has(keyId)) {
26
+ throw new Error(`duplicate license verification key ${keyId} in the trust store`);
27
+ }
28
+ keys.set(keyId, key);
29
+ }
30
+ return { keys };
31
+ }
32
+ //# sourceMappingURL=trust-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-store.js","sourceRoot":"","sources":["../../src/lib/trust-store.ts"],"names":[],"mappings":";;AAsBA,kDAOC;AAsCD,0DAgBC;AAnFD,6CAA0E;AAE1E,iDAAiD;AAMjD,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAcpC,SAAgB,mBAAmB,CAAC,YAAoB;IACtD,MAAM,GAAG,GAAG,IAAA,6BAAe,EAAC,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,IAAA,8BAAe,EACpB,IAAI,UAAU,CAAC,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAC3D,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,GAAc;IACnC,IAAI,GAAG,CAAC,iBAAiB,KAAK,iBAAiB,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CACjB,8BAA8B,iBAAiB,cAAc,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AA8BD,SAAgB,uBAAuB,CACrC,aAAgC;IAEhC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,IAAA,6BAAe,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,aAAa,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,sCAAsC,KAAK,qBAAqB,CACjE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare enum LicenseVerificationFailureCode {
2
+ MalformedToken = "malformed-token",
3
+ MalformedHeader = "malformed-header",
4
+ TrustStoreEmpty = "trust-store-empty",
5
+ UnknownKeyId = "unknown-key-id",
6
+ InvalidSignature = "invalid-signature",
7
+ MalformedClaims = "malformed-claims",
8
+ UnsupportedClaimsVersion = "unsupported-claims-version",
9
+ IssuerMismatch = "issuer-mismatch"
10
+ }
11
+ export interface LicenseVerificationFailure {
12
+ readonly ok: false;
13
+ readonly code: LicenseVerificationFailureCode;
14
+ readonly message: string;
15
+ }
16
+ export declare function verificationFailure(code: LicenseVerificationFailureCode, message: string): LicenseVerificationFailure;
17
+ //# sourceMappingURL=verification-failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-failure.d.ts","sourceRoot":"","sources":["../../src/lib/verification-failure.ts"],"names":[],"mappings":"AASA,oBAAY,8BAA8B;IAExC,cAAc,oBAAoB;IAElC,eAAe,qBAAqB;IAEpC,eAAe,sBAAsB;IAErC,YAAY,mBAAmB;IAE/B,gBAAgB,sBAAsB;IAEtC,eAAe,qBAAqB;IAEpC,wBAAwB,+BAA+B;IAEvD,cAAc,oBAAoB;CACnC;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAE9C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,8BAA8B,EACpC,OAAO,EAAE,MAAM,GACd,0BAA0B,CAE5B"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LicenseVerificationFailureCode = void 0;
4
+ exports.verificationFailure = verificationFailure;
5
+ var LicenseVerificationFailureCode;
6
+ (function (LicenseVerificationFailureCode) {
7
+ LicenseVerificationFailureCode["MalformedToken"] = "malformed-token";
8
+ LicenseVerificationFailureCode["MalformedHeader"] = "malformed-header";
9
+ LicenseVerificationFailureCode["TrustStoreEmpty"] = "trust-store-empty";
10
+ LicenseVerificationFailureCode["UnknownKeyId"] = "unknown-key-id";
11
+ LicenseVerificationFailureCode["InvalidSignature"] = "invalid-signature";
12
+ LicenseVerificationFailureCode["MalformedClaims"] = "malformed-claims";
13
+ LicenseVerificationFailureCode["UnsupportedClaimsVersion"] = "unsupported-claims-version";
14
+ LicenseVerificationFailureCode["IssuerMismatch"] = "issuer-mismatch";
15
+ })(LicenseVerificationFailureCode || (exports.LicenseVerificationFailureCode = LicenseVerificationFailureCode = {}));
16
+ function verificationFailure(code, message) {
17
+ return { ok: false, code, message };
18
+ }
19
+ //# sourceMappingURL=verification-failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-failure.js","sourceRoot":"","sources":["../../src/lib/verification-failure.ts"],"names":[],"mappings":";;;AAmCA,kDAKC;AA/BD,IAAY,8BAiBX;AAjBD,WAAY,8BAA8B;IAExC,oEAAkC,CAAA;IAElC,sEAAoC,CAAA;IAEpC,uEAAqC,CAAA;IAErC,iEAA+B,CAAA;IAE/B,wEAAsC,CAAA;IAEtC,sEAAoC,CAAA;IAEpC,yFAAuD,CAAA;IAEvD,oEAAkC,CAAA;AACpC,CAAC,EAjBW,8BAA8B,8CAA9B,8BAA8B,QAiBzC;AASD,SAAgB,mBAAmB,CACjC,IAAoC,EACpC,OAAe;IAEf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { LicenseClaims } from './license-claims.ts';
2
+ declare const VERIFIED_LICENSE_BRAND: unique symbol;
3
+ export interface VerifiedLicense {
4
+ readonly [VERIFIED_LICENSE_BRAND]: true;
5
+ readonly claims: LicenseClaims;
6
+ readonly keyId: string;
7
+ }
8
+ export declare function createVerifiedLicense(claims: LicenseClaims, keyId: string): VerifiedLicense;
9
+ export {};
10
+ //# sourceMappingURL=verified-license.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verified-license.d.ts","sourceRoot":"","sources":["../../src/lib/verified-license.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAczD,QAAA,MAAM,sBAAsB,EAAE,OAAO,MAAuC,CAAC;AAW7E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAE/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,GACZ,eAAe,CAEjB"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createVerifiedLicense = createVerifiedLicense;
4
+ const VERIFIED_LICENSE_BRAND = Symbol('xema.verifiedLicense');
5
+ function createVerifiedLicense(claims, keyId) {
6
+ return { [VERIFIED_LICENSE_BRAND]: true, claims, keyId };
7
+ }
8
+ //# sourceMappingURL=verified-license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verified-license.js","sourceRoot":"","sources":["../../src/lib/verified-license.ts"],"names":[],"mappings":";;AAgCA,sDAKC;AAvBD,MAAM,sBAAsB,GAAkB,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAkB7E,SAAgB,qBAAqB,CACnC,MAAqB,EACrB,KAAa;IAEb,OAAO,EAAE,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { LicenseTrustStore } from './trust-store.ts';
2
+ import { type LicenseVerificationFailure } from './verification-failure.ts';
3
+ import { type VerifiedLicense } from './verified-license.ts';
4
+ export interface VerifyLicenseOptions {
5
+ readonly trustStore: LicenseTrustStore;
6
+ readonly expectedIssuer?: string;
7
+ }
8
+ export type LicenseVerificationSuccess = {
9
+ readonly ok: true;
10
+ } & VerifiedLicense;
11
+ export type LicenseVerificationResult = LicenseVerificationSuccess | LicenseVerificationFailure;
12
+ export declare function verifyLicense(token: string, options: VerifyLicenseOptions): LicenseVerificationResult;
13
+ //# sourceMappingURL=verify-license.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-license.d.ts","sourceRoot":"","sources":["../../src/lib/verify-license.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAK/B,MAAM,WAAW,oBAAoB;IAMnC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAMvC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,GAAG,eAAe,CAAC;AAEpB,MAAM,MAAM,yBAAyB,GACjC,0BAA0B,GAC1B,0BAA0B,CAAC;AAgB/B,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,oBAAoB,GAC5B,yBAAyB,CAqF3B"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyLicense = verifyLicense;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const base64url_ts_1 = require("./base64url.js");
6
+ const compact_jws_ts_1 = require("./compact-jws.js");
7
+ const license_enums_ts_1 = require("./license-enums.js");
8
+ const parse_license_claims_ts_1 = require("./parse-license-claims.js");
9
+ const verification_failure_ts_1 = require("./verification-failure.js");
10
+ const verified_license_ts_1 = require("./verified-license.js");
11
+ const HEADER_KEYS = ['alg', 'kid', 'typ'];
12
+ const MAX_KEY_ID_LENGTH = 128;
13
+ function verifyLicense(token, options) {
14
+ if (typeof token !== 'string') {
15
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.MalformedToken, 'a license token must be a string');
16
+ }
17
+ const segments = (0, compact_jws_ts_1.splitCompactJws)(token.trim());
18
+ if (segments === null) {
19
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.MalformedToken, 'a license token must be a compact JWS of three non-empty base64url segments');
20
+ }
21
+ const header = parseHeader(segments.encodedHeader);
22
+ if ('code' in header) {
23
+ return header;
24
+ }
25
+ if (options.trustStore.keys.size === 0) {
26
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.TrustStoreEmpty, 'this build carries no license verification keys; its license material was never provisioned');
27
+ }
28
+ const key = options.trustStore.keys.get(header.kid);
29
+ if (key === undefined) {
30
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.UnknownKeyId, `no trusted license verification key with id ${header.kid}`);
31
+ }
32
+ const signatureIsValid = (0, node_crypto_1.verify)(null, segments.signingInput, key, segments.signature);
33
+ if (!signatureIsValid) {
34
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.InvalidSignature, `the license signature does not verify under key ${header.kid}`);
35
+ }
36
+ const payloadText = (0, base64url_ts_1.decodeBase64UrlText)(segments.encodedPayload);
37
+ if (payloadText === null) {
38
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.MalformedClaims, 'the license payload is not valid UTF-8');
39
+ }
40
+ let payload;
41
+ try {
42
+ payload = JSON.parse(payloadText);
43
+ }
44
+ catch {
45
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.MalformedClaims, 'the license payload is not valid JSON');
46
+ }
47
+ const parsed = (0, parse_license_claims_ts_1.parseLicenseClaims)(payload);
48
+ if (!parsed.ok) {
49
+ return parsed;
50
+ }
51
+ const expectedIssuer = options.expectedIssuer ?? license_enums_ts_1.XEMA_LICENSE_ISSUER;
52
+ if (parsed.claims.issuer !== expectedIssuer) {
53
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.IssuerMismatch, `the license names issuer ${parsed.claims.issuer}, expected ${expectedIssuer}`);
54
+ }
55
+ return { ok: true, ...(0, verified_license_ts_1.createVerifiedLicense)(parsed.claims, header.kid) };
56
+ }
57
+ function parseHeader(encodedHeader) {
58
+ const text = (0, base64url_ts_1.decodeBase64UrlText)(encodedHeader);
59
+ if (text === null) {
60
+ return malformedHeader('the protected header is not valid UTF-8');
61
+ }
62
+ let value;
63
+ try {
64
+ value = JSON.parse(text);
65
+ }
66
+ catch {
67
+ return malformedHeader('the protected header is not valid JSON');
68
+ }
69
+ if (typeof value !== 'object' ||
70
+ value === null ||
71
+ Array.isArray(value) ||
72
+ Object.getPrototypeOf(value) !== Object.prototype) {
73
+ return malformedHeader('the protected header must be a JSON object');
74
+ }
75
+ const object = value;
76
+ for (const key of Object.keys(object)) {
77
+ if (!HEADER_KEYS.includes(key)) {
78
+ return malformedHeader(`unknown header parameter "${key}"`);
79
+ }
80
+ }
81
+ if (object['alg'] !== license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA) {
82
+ return malformedHeader(`unsupported signature algorithm ${JSON.stringify(object['alg'])}; a Xema license is ${license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA}`);
83
+ }
84
+ if (object['typ'] !== license_enums_ts_1.LICENSE_JWS_TYPE) {
85
+ return malformedHeader(`unsupported token type ${JSON.stringify(object['typ'])}; a Xema license is ${license_enums_ts_1.LICENSE_JWS_TYPE}`);
86
+ }
87
+ const kid = object['kid'];
88
+ if (typeof kid !== 'string' ||
89
+ kid.length === 0 ||
90
+ kid.length > MAX_KEY_ID_LENGTH) {
91
+ return malformedHeader(`the header must carry a kid of 1..${MAX_KEY_ID_LENGTH} characters`);
92
+ }
93
+ return { alg: license_enums_ts_1.LicenseSignatureAlgorithm.EdDSA, kid, typ: license_enums_ts_1.LICENSE_JWS_TYPE };
94
+ }
95
+ function malformedHeader(message) {
96
+ return (0, verification_failure_ts_1.verificationFailure)(verification_failure_ts_1.LicenseVerificationFailureCode.MalformedHeader, message);
97
+ }
98
+ //# sourceMappingURL=verify-license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-license.js","sourceRoot":"","sources":["../../src/lib/verify-license.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { LocalKeyLicenseSigner, type LicenseSigner, } from './lib/license-signer.ts';
2
+ export { signLicense } from './lib/sign-license.ts';
3
+ export { renderLicenseMaterial, type LicenseMaterial, } from './lib/render-license-material.ts';
4
+ //# sourceMappingURL=signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,qBAAqB,EACrB,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderLicenseMaterial = exports.signLicense = exports.LocalKeyLicenseSigner = void 0;
4
+ var license_signer_ts_1 = require("./lib/license-signer.js");
5
+ Object.defineProperty(exports, "LocalKeyLicenseSigner", { enumerable: true, get: function () { return license_signer_ts_1.LocalKeyLicenseSigner; } });
6
+ var sign_license_ts_1 = require("./lib/sign-license.js");
7
+ Object.defineProperty(exports, "signLicense", { enumerable: true, get: function () { return sign_license_ts_1.signLicense; } });
8
+ var render_license_material_ts_1 = require("./lib/render-license-material.js");
9
+ Object.defineProperty(exports, "renderLicenseMaterial", { enumerable: true, get: function () { return render_license_material_ts_1.renderLicenseMaterial; } });
10
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signing.js","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":";;;AAiBA,6DAGiC;AAF/B,0HAAA,qBAAqB,OAAA;AAGvB,yDAAoD;AAA3C,8GAAA,WAAW,OAAA;AACpB,+EAG0C;AAFxC,mIAAA,qBAAqB,OAAA"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@xemahq/license-verifier",
3
+ "version": "0.1.0",
4
+ "description": "Offline verification of a Xema license — Ed25519 JWS against an embedded public key, lifecycle resolution and entitlement evaluation. Zero dependencies, Node built-ins only, so it runs in the CLI from a bare checkout and in the air-gap installer on a disconnected box.",
5
+ "license": "Apache-2.0",
6
+ "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
7
+ "homepage": "https://xema.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/xema-dev/xema-kernel-contracts.git",
11
+ "directory": "packages/kernel/license-verifier"
12
+ },
13
+ "bugs": "https://github.com/xema-dev/xema-kernel-contracts/issues",
14
+ "publishConfig": {
15
+ "registry": "https://registry.npmjs.org/",
16
+ "access": "public"
17
+ },
18
+ "main": "dist/index.js",
19
+ "types": "dist/index.d.ts",
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "devDependencies": {
24
+ "@types/node": "25.2.3",
25
+ "prettier": "3.6.2",
26
+ "typescript": "5.9.3",
27
+ "@xemahq/license-contracts": "0.1.0"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "xema-source": "./src/index.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./signing": {
36
+ "types": "./dist/signing.d.ts",
37
+ "xema-source": "./src/signing.ts",
38
+ "default": "./dist/signing.js"
39
+ },
40
+ "./dist/lib/*": {
41
+ "types": "./dist/lib/*.d.ts",
42
+ "default": "./dist/lib/*.js"
43
+ }
44
+ },
45
+ "bin": {
46
+ "xema-license-keygen": "dist/bin/xema-license-keygen.js",
47
+ "xema-license-mint-oss": "dist/bin/xema-license-mint-oss.js"
48
+ },
49
+ "scripts": {
50
+ "clean": "rm -rf dist",
51
+ "build": "tsc -p tsconfig.json",
52
+ "format": "prettier --write \"src/**/*.ts\"",
53
+ "typecheck": "tsc -p tsconfig.typecheck.json",
54
+ "test": "node --experimental-transform-types --test \"src/lib/*.test.ts\""
55
+ }
56
+ }