@permitcore/permitcore 1.0.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.
package/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # PermitCore Node.js SDK
2
+
3
+ Official Node.js/TypeScript client for [PermitCore](https://permitcore.dev) license management.
4
+
5
+ **Requirements:** Node.js 16+, zero runtime dependencies (uses the global `fetch` and Node's
6
+ built-in `crypto` module for offline license token verification).
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install permitcore
14
+ ```
15
+
16
+ ---
17
+
18
+ ## Quick start
19
+
20
+ ```typescript
21
+ import { PermitCoreClient } from 'permitcore';
22
+
23
+ const client = new PermitCoreClient('https://your-instance.com');
24
+ const result = await client.validate('PERMIT-XXXX-XXXX-XXXX-XXXX');
25
+
26
+ if (result.isValid) {
27
+ console.log(`Valid! Product: ${result.productName}`);
28
+ if (PermitCoreClient.hasFeature(result, 'export')) {
29
+ enableExport();
30
+ }
31
+ }
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Validate
37
+
38
+ ```typescript
39
+ const result = await client.validate(licenseKey, '2.3.1'); // version is optional
40
+
41
+ // result.isValid boolean
42
+ // result.productName string | undefined
43
+ // result.remainingActivations number | undefined
44
+ // result.expiresAt string | undefined (ISO 8601)
45
+ // result.features string[] | undefined
46
+ // result.customFields Record<string, string> | undefined
47
+ // result.isTrial boolean | undefined
48
+ // result.trialDaysRemaining number | undefined
49
+ // result.nodeLocked boolean | undefined
50
+ // result.offlineGraceDays number | undefined
51
+ // result.minVersion string | undefined
52
+ // result.maxVersion string | undefined
53
+ // result.message string | undefined
54
+ // result.isOffline boolean | undefined (true when served from local cache)
55
+ ```
56
+
57
+ `validate()` never consumes an activation slot. It falls back to the local disk cache when the
58
+ server is unreachable, as long as the license has `offlineGraceDays` configured. Passing
59
+ `version` lets the server enforce `minVersion`/`maxVersion` restrictions on the license.
60
+
61
+ ---
62
+
63
+ ## Activate
64
+
65
+ ```typescript
66
+ const result = await client.activate(
67
+ licenseKey,
68
+ undefined, // deviceId — auto-generated HWID when omitted
69
+ 'Production Server #1', // deviceName
70
+ '2.3.1', // version (optional)
71
+ );
72
+
73
+ if (!result.isValid) {
74
+ throw new Error(`Activation failed: ${result.message}`);
75
+ }
76
+ ```
77
+
78
+ Call `activate()` **once** per installation. Use `validate()` on every subsequent launch.
79
+
80
+ ---
81
+
82
+ ## Meter (usage events)
83
+
84
+ ```typescript
85
+ // Record a single API call
86
+ const recorded = await client.meter(licenseKey, 'api_call');
87
+
88
+ // Record bulk usage with metadata
89
+ const recorded2 = await client.meter(licenseKey, 'export', 5, { format: 'pdf', pages: 12 });
90
+ ```
91
+
92
+ Returns `true` if the event was recorded on the server, `false` on any failure (network error, or
93
+ the server rejecting the event).
94
+
95
+ ---
96
+
97
+ ## Floating licenses
98
+
99
+ ```typescript
100
+ // Check out a seat at session start
101
+ const session = await client.checkout(licenseKey);
102
+ if (!session.success) {
103
+ throw new Error(`No seats available: ${session.message}`);
104
+ }
105
+
106
+ const token = session.sessionToken!;
107
+
108
+ // Heartbeat every 4-5 minutes to keep the seat alive
109
+ await client.heartbeat(token);
110
+
111
+ // Release the seat when done
112
+ await client.checkin(token);
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Offline license tokens
118
+
119
+ An offline activation token (`pc_offline_v1.<payload>.<signature>`) lets your app verify a
120
+ license with **zero network calls**, using ECDSA P-256 signature verification against your
121
+ tenant's public key (`GET /api/v1/{tenantSlug}/public-key`). Useful for air-gapped or
122
+ intermittently-connected deployments.
123
+
124
+ ```typescript
125
+ // Pure local verification — no network call. Never throws.
126
+ const result = client.verifyOfflineToken(token, publicKeyBase64);
127
+
128
+ if (result.isValid) {
129
+ console.log(`Valid! Product: ${result.productName}`);
130
+ } else {
131
+ console.log(`Invalid: ${result.message}`);
132
+ }
133
+ ```
134
+
135
+ ```typescript
136
+ // Verify + bind to this device + persist locally (call once, e.g. at install time)
137
+ const result = client.activateOffline(token, publicKeyBase64, deviceId);
138
+
139
+ // On every later launch — no token needed, reads the local cache, still no network call
140
+ const result2 = client.validateOffline(deviceId);
141
+ ```
142
+
143
+ ```typescript
144
+ // Optional: ask the server to verify the token AND check its revocation status (requires network)
145
+ const result3 = await client.verifyOfflineOnline(token);
146
+ ```
147
+
148
+ All four methods return an `OfflineTokenResult` — on a valid token, the payload fields
149
+ (`tokenId`, `tenantSlug`, `tenantId`, `licenseId`, `deviceId`, `deviceName`, `productName`,
150
+ `maxActivations`, `issuedAt`, `expiresAt`) are merged in alongside `isValid`/`message`.
151
+ `verifyOfflineToken()` and `validateOffline()` never throw — malformed, tampered, expired, or
152
+ missing input all come back as `isValid: false` with a descriptive `message`.
153
+
154
+ `activateOffline()`'s local cache is stored under the OS temp directory as
155
+ `.permitcore_offline_<hash>` (same convention as the `validate()`/`activate()` cache, keyed by
156
+ device ID instead of license key).
157
+
158
+ ---
159
+
160
+ ## Version enforcement
161
+
162
+ ```typescript
163
+ const result = await client.validate(licenseKey);
164
+
165
+ const myVersion = '2.3.0';
166
+ if (result.minVersion && myVersion < result.minVersion) {
167
+ throw new Error(`Please update to version ${result.minVersion} or newer.`);
168
+ }
169
+ if (result.maxVersion && myVersion > result.maxVersion) {
170
+ throw new Error(`This build (${myVersion}) is not licensed for versions above ${result.maxVersion}.`);
171
+ }
172
+ ```
173
+
174
+ Pass a `version` argument to `validate()`/`activate()` to also have the *server* enforce this —
175
+ otherwise only client-side comparison happens.
176
+
177
+ ---
178
+
179
+ ## Offline grace pattern
180
+
181
+ ```typescript
182
+ const result = await client.validate(licenseKey); // falls back to cache automatically
183
+
184
+ if (!result.isValid) {
185
+ throw new Error(`License invalid: ${result.message}`);
186
+ }
187
+
188
+ if (result.isOffline) {
189
+ // Server unreachable — running on cached result
190
+ showNotice('Running in offline mode. Connect to the internet to refresh your license.');
191
+ }
192
+ ```
193
+
194
+ The cache is stored under the OS temp directory as `.permitcore_cache_<hash>`. It expires after
195
+ `offlineGraceDays` days.
196
+
197
+ ---
198
+
199
+ ## Constructor options
200
+
201
+ ```typescript
202
+ const client = new PermitCoreClient({
203
+ baseUrl: 'https://your-instance.com',
204
+ enableOfflineCache: true, // default — set false to always require network
205
+ timeoutMs: 5000, // HTTP timeout in milliseconds
206
+ });
207
+ ```
208
+
209
+ ---
210
+
211
+ ## LicenseResult reference
212
+
213
+ | Field | Type | Description |
214
+ |---|---|---|
215
+ | `isValid` | `boolean` | True if the license is active and valid |
216
+ | `productName` | `string?` | Product the license belongs to |
217
+ | `remainingActivations` | `number?` | Slots left before MaxActivations is reached |
218
+ | `expiresAt` | `string?` | Expiry date (ISO 8601 UTC), undefined if perpetual |
219
+ | `features` | `string[]?` | Feature flag list, e.g. `['export', 'api']` |
220
+ | `customFields` | `Record<string, string>?` | Arbitrary key/value metadata set on the license |
221
+ | `isTrial` | `boolean?` | True for trial licenses |
222
+ | `trialDaysRemaining` | `number?` | Days until trial expires |
223
+ | `nodeLocked` | `boolean?` | True if bound to a specific device |
224
+ | `offlineGraceDays` | `number?` | How many days the cache is valid |
225
+ | `minVersion` / `maxVersion` | `string?` | Version enforcement bounds |
226
+ | `message` | `string?` | Reason when `isValid = false` |
227
+ | `isOffline` | `boolean?` | True when result came from local cache |
228
+
229
+ `PermitCoreClient.hasFeature(result, feature)` — static, case-insensitive feature check.
@@ -0,0 +1,174 @@
1
+ export interface LicenseResult {
2
+ isValid: boolean;
3
+ productName?: string;
4
+ remainingActivations?: number;
5
+ expiresAt?: string;
6
+ message?: string;
7
+ customFields?: Record<string, string>;
8
+ vendorWarning?: string;
9
+ features?: string[];
10
+ isTrial?: boolean;
11
+ trialDaysRemaining?: number;
12
+ nodeLocked?: boolean;
13
+ offlineGraceDays?: number;
14
+ minVersion?: string;
15
+ maxVersion?: string;
16
+ /**
17
+ * ECDSA-signed `pc_grace_v1` token (non-null only when the license has an offline grace
18
+ * period configured and this call succeeded). The SDK caches this — not the rest of this
19
+ * response — and verifies it locally before trusting a cached result on a later offline
20
+ * call. See `verifyGraceCacheToken`.
21
+ */
22
+ offlineCacheToken?: string | null;
23
+ /** True when served from local cache (server unreachable) */
24
+ isOffline?: boolean;
25
+ }
26
+ export interface MeterResult {
27
+ recorded: boolean;
28
+ message?: string;
29
+ }
30
+ export interface FloatingSession {
31
+ success: boolean;
32
+ sessionToken?: string;
33
+ expiresAt?: string;
34
+ message?: string;
35
+ }
36
+ export interface PermitCoreOptions {
37
+ baseUrl: string;
38
+ /** Enable offline grace period caching. Default: true */
39
+ enableOfflineCache?: boolean;
40
+ /** Request timeout in milliseconds. Default: 5000 */
41
+ timeoutMs?: number;
42
+ }
43
+ /** Decoded payload of a `pc_offline_v1` offline activation token. */
44
+ export interface OfflineTokenPayload {
45
+ version: number;
46
+ tokenId: string;
47
+ tenantSlug: string;
48
+ tenantId: string;
49
+ licenseId: string;
50
+ licenseKeyHash: string;
51
+ deviceId: string;
52
+ deviceName?: string | null;
53
+ productName: string;
54
+ maxActivations: number;
55
+ issuedAt: string;
56
+ expiresAt: string;
57
+ }
58
+ export interface OfflineTokenResult {
59
+ isValid: boolean;
60
+ tokenId?: string;
61
+ tenantSlug?: string;
62
+ tenantId?: string;
63
+ licenseId?: string;
64
+ deviceId?: string;
65
+ deviceName?: string | null;
66
+ productName?: string;
67
+ maxActivations?: number;
68
+ issuedAt?: string;
69
+ expiresAt?: string;
70
+ message?: string;
71
+ }
72
+ /** Decoded payload of a `pc_grace_v1` offline grace-cache token. */
73
+ export interface GraceCachePayload {
74
+ version: number;
75
+ tenantSlug: string;
76
+ kid?: string | null;
77
+ licenseKeyHash: string;
78
+ deviceId?: string | null;
79
+ isValid: boolean;
80
+ productName?: string | null;
81
+ features?: string[] | null;
82
+ remainingActivations?: number | null;
83
+ expiresAt?: string | null;
84
+ issuedAt: string;
85
+ validUntil: string;
86
+ }
87
+ export interface GraceCacheResult {
88
+ isValid: boolean;
89
+ message?: string;
90
+ payload?: GraceCachePayload;
91
+ }
92
+ export declare class PermitCoreClient {
93
+ private readonly baseUrl;
94
+ private readonly opts;
95
+ constructor(baseUrlOrOptions: string | PermitCoreOptions);
96
+ /**
97
+ * Validates a license key. Does NOT consume an activation slot.
98
+ * Falls back to local cache when server is unreachable (offline grace period).
99
+ */
100
+ validate(licenseKey: string, version?: string): Promise<LicenseResult>;
101
+ /**
102
+ * Validates AND activates the key on this device.
103
+ * Call only once per installation.
104
+ * @param deviceId Optional — auto-generated HWID is used when omitted.
105
+ */
106
+ activate(licenseKey: string, deviceId?: string, deviceName?: string, version?: string): Promise<LicenseResult>;
107
+ /**
108
+ * Records a usage event for metered billing.
109
+ * Returns true if the event was recorded on the server, false on any failure
110
+ * (network error, or the server rejecting the event).
111
+ */
112
+ meter(licenseKey: string, eventName: string, quantity?: number, meta?: Record<string, unknown>): Promise<boolean>;
113
+ checkout(licenseKey: string, deviceId?: string, deviceName?: string): Promise<FloatingSession>;
114
+ heartbeat(sessionToken: string): Promise<FloatingSession>;
115
+ checkin(sessionToken: string): Promise<void>;
116
+ /**
117
+ * Verifies a `pc_offline_v1` offline activation token entirely locally — no network I/O.
118
+ * The signed bytes are the UTF-8 bytes of the base64url payload *string* (not the decoded
119
+ * JSON), and the signature is ECDSA P-256/SHA-256 in raw IEEE P1363 format (not ASN.1 DER),
120
+ * matching `OfflineActivationService.Sign` server-side. Never throws — malformed input,
121
+ * a signature mismatch, or an expired token all just produce `{ isValid: false }`.
122
+ */
123
+ verifyOfflineToken(token: string, publicKeyBase64: string): OfflineTokenResult;
124
+ /**
125
+ * Verifies an offline token (see `verifyOfflineToken`), confirms it was issued for
126
+ * `deviceId`, and — on success — persists the verified payload locally so a later
127
+ * `validateOffline()` call can re-check it with zero network calls (e.g. on every app start).
128
+ */
129
+ activateOffline(token: string, publicKeyBase64: string, deviceId: string): OfflineTokenResult;
130
+ /**
131
+ * Re-checks a previously `activateOffline()`-persisted token against the local clock and
132
+ * device id — no network call, no token needed. This is what a long-running app should call
133
+ * on every start once it has already offline-activated once.
134
+ */
135
+ validateOffline(deviceId: string): OfflineTokenResult;
136
+ /**
137
+ * Thin online wrapper around `POST /api/v1/offline/verify` — lets the server additionally
138
+ * check token revocation status, which is impossible to verify purely locally. Not required
139
+ * for offline use; a convenience for apps that have connectivity and want the extra check.
140
+ */
141
+ verifyOfflineOnline(token: string): Promise<OfflineTokenResult>;
142
+ /**
143
+ * Verifies a `pc_grace_v1` offline grace-cache token entirely locally — no network I/O.
144
+ * Exposed publicly so a custom integration (not using the built-in save/load-from-cache
145
+ * flow) can implement its own caching around the same verified primitive. Never throws —
146
+ * malformed input, a signature mismatch, or an expired grace period all just produce
147
+ * `{ isValid: false }`.
148
+ */
149
+ verifyGraceCacheToken(token: string, publicKeyBase64: string): GraceCacheResult;
150
+ /**
151
+ * Returns a stable hardware fingerprint (SHA-256 of machine identifiers).
152
+ */
153
+ static getHardwareId(): string;
154
+ /** Check if a validate/activate result includes a specific feature flag. */
155
+ static hasFeature(result: LicenseResult, feature: string): boolean;
156
+ private fetch;
157
+ /**
158
+ * [S-Grace1] Caches the SIGNED token, not the raw response — the server only issues
159
+ * `offlineCacheToken` when a grace period is configured, so a null/missing token here
160
+ * already means "nothing to cache," same as the old `offlineGraceDays` check. The
161
+ * unverified `tenantSlug` is read out of the token purely to pick which tenant's
162
+ * public key to fetch (see `extractUnverifiedTenantSlug`); nothing is trusted or
163
+ * persisted until `verifyGraceCacheToken` confirms the signature against that key.
164
+ */
165
+ private saveToCache;
166
+ /**
167
+ * No network call here — verification uses only the public key persisted alongside the
168
+ * token at save time. This is the entire point: a hand-edited cache file (or one copied
169
+ * to another machine) fails ECDSA verification instead of silently working.
170
+ */
171
+ private loadFromCache;
172
+ }
173
+ export default PermitCoreClient;
174
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,440 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PermitCoreClient = void 0;
37
+ const crypto = __importStar(require("crypto"));
38
+ const fs = __importStar(require("fs"));
39
+ const os = __importStar(require("os"));
40
+ const path = __importStar(require("path"));
41
+ // ── Client ─────────────────────────────────────────────────────────────────
42
+ class PermitCoreClient {
43
+ constructor(baseUrlOrOptions) {
44
+ if (typeof baseUrlOrOptions === 'string') {
45
+ this.opts = { baseUrl: baseUrlOrOptions, enableOfflineCache: true, timeoutMs: 5000 };
46
+ }
47
+ else {
48
+ this.opts = { enableOfflineCache: true, timeoutMs: 5000, ...baseUrlOrOptions };
49
+ }
50
+ this.baseUrl = this.opts.baseUrl.replace(/\/$/, '');
51
+ }
52
+ // ── Validate ─────────────────────────────────────────────────────────
53
+ /**
54
+ * Validates a license key. Does NOT consume an activation slot.
55
+ * Falls back to local cache when server is unreachable (offline grace period).
56
+ */
57
+ async validate(licenseKey, version) {
58
+ try {
59
+ const res = await this.fetch(`${this.baseUrl}/api/v1/validate`, {
60
+ method: 'POST',
61
+ headers: { 'Content-Type': 'application/json' },
62
+ body: JSON.stringify({ licenseKey, ...(version ? { version } : {}) }),
63
+ });
64
+ if (res.isValid)
65
+ await this.saveToCache(licenseKey, res);
66
+ return res;
67
+ }
68
+ catch (err) {
69
+ const cached = this.loadFromCache(licenseKey);
70
+ if (cached)
71
+ return cached;
72
+ return { isValid: false, message: 'Cannot reach license server.', isOffline: true };
73
+ }
74
+ }
75
+ // ── Activate ─────────────────────────────────────────────────────────
76
+ /**
77
+ * Validates AND activates the key on this device.
78
+ * Call only once per installation.
79
+ * @param deviceId Optional — auto-generated HWID is used when omitted.
80
+ */
81
+ async activate(licenseKey, deviceId, deviceName, version) {
82
+ const hwid = deviceId ?? PermitCoreClient.getHardwareId();
83
+ try {
84
+ // [S-Nonce] Fetch a single-use nonce first (replay-attack protection)
85
+ const { nonce } = await this.fetch(`${this.baseUrl}/api/v1/nonce`);
86
+ const res = await this.fetch(`${this.baseUrl}/api/v1/activate`, {
87
+ method: 'POST',
88
+ headers: { 'Content-Type': 'application/json' },
89
+ body: JSON.stringify({ licenseKey, deviceId: hwid, deviceName, version, nonce }),
90
+ });
91
+ if (res.isValid)
92
+ await this.saveToCache(licenseKey, res);
93
+ return res;
94
+ }
95
+ catch {
96
+ // [S-Continuity] If this device already activated successfully before (e.g. an app
97
+ // that re-runs activate() on every launch, or a reinstall that kept the cache file),
98
+ // fall back to that cached result instead of failing outright.
99
+ const cached = this.loadFromCache(licenseKey);
100
+ if (cached)
101
+ return cached;
102
+ return { isValid: false, message: 'Cannot reach license server.', isOffline: true };
103
+ }
104
+ }
105
+ // ── Meter ────────────────────────────────────────────────────────────
106
+ /**
107
+ * Records a usage event for metered billing.
108
+ * Returns true if the event was recorded on the server, false on any failure
109
+ * (network error, or the server rejecting the event).
110
+ */
111
+ async meter(licenseKey, eventName, quantity = 1, meta) {
112
+ try {
113
+ const res = await this.fetch(`${this.baseUrl}/api/v1/meter`, {
114
+ method: 'POST',
115
+ headers: { 'Content-Type': 'application/json' },
116
+ body: JSON.stringify({ licenseKey, eventName, quantity, ...(meta ? { meta } : {}) }),
117
+ });
118
+ return res.recorded ?? false;
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ // ── Floating ─────────────────────────────────────────────────────────
125
+ async checkout(licenseKey, deviceId, deviceName) {
126
+ const hwid = deviceId ?? PermitCoreClient.getHardwareId();
127
+ return this.fetch(`${this.baseUrl}/api/v1/float/checkout`, {
128
+ method: 'POST',
129
+ headers: { 'Content-Type': 'application/json' },
130
+ body: JSON.stringify({ licenseKey, deviceId: hwid, deviceName }),
131
+ });
132
+ }
133
+ // [S-Float] Session token in the POST body — never the URL path — matches
134
+ // FloatingController.Heartbeat's FloatingTokenRequest exactly.
135
+ async heartbeat(sessionToken) {
136
+ return this.fetch(`${this.baseUrl}/api/v1/float/heartbeat`, {
137
+ method: 'POST',
138
+ headers: { 'Content-Type': 'application/json' },
139
+ body: JSON.stringify({ sessionToken }),
140
+ });
141
+ }
142
+ // [S-Float] Session token in the POST body — never the URL path — matches
143
+ // FloatingController.Checkin's FloatingTokenRequest exactly (also: it's a POST, not DELETE).
144
+ async checkin(sessionToken) {
145
+ await this.fetch(`${this.baseUrl}/api/v1/float/checkin`, {
146
+ method: 'POST',
147
+ headers: { 'Content-Type': 'application/json' },
148
+ body: JSON.stringify({ sessionToken }),
149
+ });
150
+ }
151
+ // ── Offline activation tokens ───────────────────────────────────────
152
+ /**
153
+ * Verifies a `pc_offline_v1` offline activation token entirely locally — no network I/O.
154
+ * The signed bytes are the UTF-8 bytes of the base64url payload *string* (not the decoded
155
+ * JSON), and the signature is ECDSA P-256/SHA-256 in raw IEEE P1363 format (not ASN.1 DER),
156
+ * matching `OfflineActivationService.Sign` server-side. Never throws — malformed input,
157
+ * a signature mismatch, or an expired token all just produce `{ isValid: false }`.
158
+ */
159
+ verifyOfflineToken(token, publicKeyBase64) {
160
+ try {
161
+ const parts = token.split('.');
162
+ if (parts.length !== 3 || parts[0] !== 'pc_offline_v1') {
163
+ return { isValid: false, message: 'Malformed offline token.' };
164
+ }
165
+ const payloadBytes = Buffer.from(parts[1], 'utf8');
166
+ const signature = Buffer.from(parts[2], 'base64url');
167
+ const publicKey = crypto.createPublicKey({
168
+ key: Buffer.from(publicKeyBase64, 'base64'),
169
+ format: 'der',
170
+ type: 'spki',
171
+ });
172
+ const signatureOk = crypto.verify('sha256', payloadBytes, { key: publicKey, dsaEncoding: 'ieee-p1363' }, signature);
173
+ if (!signatureOk)
174
+ return { isValid: false, message: 'Offline token signature is invalid.' };
175
+ const json = Buffer.from(parts[1], 'base64url').toString('utf8');
176
+ const payload = JSON.parse(json);
177
+ if (new Date(payload.expiresAt).getTime() < Date.now()) {
178
+ return { isValid: false, message: 'Offline token has expired.' };
179
+ }
180
+ return {
181
+ isValid: true,
182
+ tokenId: payload.tokenId,
183
+ tenantSlug: payload.tenantSlug,
184
+ tenantId: payload.tenantId,
185
+ licenseId: payload.licenseId,
186
+ deviceId: payload.deviceId,
187
+ deviceName: payload.deviceName,
188
+ productName: payload.productName,
189
+ maxActivations: payload.maxActivations,
190
+ issuedAt: payload.issuedAt,
191
+ expiresAt: payload.expiresAt,
192
+ message: 'Offline token is valid.',
193
+ };
194
+ }
195
+ catch {
196
+ return { isValid: false, message: 'Failed to verify offline token.' };
197
+ }
198
+ }
199
+ /**
200
+ * Verifies an offline token (see `verifyOfflineToken`), confirms it was issued for
201
+ * `deviceId`, and — on success — persists the verified payload locally so a later
202
+ * `validateOffline()` call can re-check it with zero network calls (e.g. on every app start).
203
+ */
204
+ activateOffline(token, publicKeyBase64, deviceId) {
205
+ const result = this.verifyOfflineToken(token, publicKeyBase64);
206
+ if (!result.isValid)
207
+ return result;
208
+ if (!result.deviceId || result.deviceId.toLowerCase() !== deviceId.toLowerCase()) {
209
+ return { isValid: false, message: 'Offline token was issued for a different device.' };
210
+ }
211
+ if (this.opts.enableOfflineCache) {
212
+ try {
213
+ fs.writeFileSync(getOfflineActivationPath(deviceId), JSON.stringify(result));
214
+ }
215
+ catch { /* non-critical */ }
216
+ }
217
+ return result;
218
+ }
219
+ /**
220
+ * Re-checks a previously `activateOffline()`-persisted token against the local clock and
221
+ * device id — no network call, no token needed. This is what a long-running app should call
222
+ * on every start once it has already offline-activated once.
223
+ */
224
+ validateOffline(deviceId) {
225
+ try {
226
+ const raw = fs.readFileSync(getOfflineActivationPath(deviceId), 'utf8');
227
+ const cached = JSON.parse(raw);
228
+ if (!cached.deviceId || cached.deviceId.toLowerCase() !== deviceId.toLowerCase()) {
229
+ return { isValid: false, message: 'No offline activation found for this device.' };
230
+ }
231
+ if (!cached.expiresAt || new Date(cached.expiresAt).getTime() < Date.now()) {
232
+ return { isValid: false, message: 'Offline activation has expired.' };
233
+ }
234
+ return { ...cached, isValid: true };
235
+ }
236
+ catch {
237
+ return { isValid: false, message: 'No offline activation found for this device.' };
238
+ }
239
+ }
240
+ /**
241
+ * Thin online wrapper around `POST /api/v1/offline/verify` — lets the server additionally
242
+ * check token revocation status, which is impossible to verify purely locally. Not required
243
+ * for offline use; a convenience for apps that have connectivity and want the extra check.
244
+ */
245
+ async verifyOfflineOnline(token) {
246
+ try {
247
+ const res = await this.fetch(`${this.baseUrl}/api/v1/offline/verify`, {
248
+ method: 'POST',
249
+ headers: { 'Content-Type': 'application/json' },
250
+ body: JSON.stringify({ token }),
251
+ });
252
+ return res;
253
+ }
254
+ catch {
255
+ return { isValid: false, message: 'Cannot reach license server.' };
256
+ }
257
+ }
258
+ // ── Grace-cache token verification (pc_grace_v1, ECDSA P-256 / IEEE P1363) ──────────
259
+ // [S-Grace1] Same crypto convention as verifyOfflineToken above (raw IEEE P1363 signature
260
+ // over the UTF-8 bytes of the base64url payload *string*), different prefix and payload
261
+ // shape. Matches OfflineActivationService.VerifyGraceCache server-side byte-for-byte.
262
+ /**
263
+ * Verifies a `pc_grace_v1` offline grace-cache token entirely locally — no network I/O.
264
+ * Exposed publicly so a custom integration (not using the built-in save/load-from-cache
265
+ * flow) can implement its own caching around the same verified primitive. Never throws —
266
+ * malformed input, a signature mismatch, or an expired grace period all just produce
267
+ * `{ isValid: false }`.
268
+ */
269
+ verifyGraceCacheToken(token, publicKeyBase64) {
270
+ try {
271
+ const parts = token.split('.');
272
+ if (parts.length !== 3 || parts[0] !== 'pc_grace_v1') {
273
+ return { isValid: false, message: 'Malformed grace cache token.' };
274
+ }
275
+ const payloadBytes = Buffer.from(parts[1], 'utf8');
276
+ const signature = Buffer.from(parts[2], 'base64url');
277
+ const publicKey = crypto.createPublicKey({
278
+ key: Buffer.from(publicKeyBase64, 'base64'),
279
+ format: 'der',
280
+ type: 'spki',
281
+ });
282
+ const signatureOk = crypto.verify('sha256', payloadBytes, { key: publicKey, dsaEncoding: 'ieee-p1363' }, signature);
283
+ if (!signatureOk)
284
+ return { isValid: false, message: 'Grace cache token signature is invalid.' };
285
+ const json = Buffer.from(parts[1], 'base64url').toString('utf8');
286
+ const payload = JSON.parse(json);
287
+ if (new Date(payload.validUntil).getTime() < Date.now()) {
288
+ return { isValid: false, message: 'Grace period has expired.', payload };
289
+ }
290
+ return { isValid: true, message: 'Valid.', payload };
291
+ }
292
+ catch {
293
+ return { isValid: false, message: 'Invalid or corrupt grace cache token.' };
294
+ }
295
+ }
296
+ // ── HWID ─────────────────────────────────────────────────────────────
297
+ /**
298
+ * Returns a stable hardware fingerprint (SHA-256 of machine identifiers).
299
+ */
300
+ static getHardwareId() {
301
+ const components = [
302
+ os.hostname(),
303
+ os.platform(),
304
+ os.arch(),
305
+ String(os.cpus().length),
306
+ getOrCreateSeedFile(),
307
+ ].filter(Boolean);
308
+ return crypto
309
+ .createHash('sha256')
310
+ .update(components.join('|'))
311
+ .digest('hex');
312
+ }
313
+ // ── Feature helpers ───────────────────────────────────────────────────
314
+ /** Check if a validate/activate result includes a specific feature flag. */
315
+ static hasFeature(result, feature) {
316
+ return result.features?.some(f => f.toLowerCase() === feature.toLowerCase()) ?? false;
317
+ }
318
+ // ── Internal ──────────────────────────────────────────────────────────
319
+ async fetch(url, init) {
320
+ const controller = new AbortController();
321
+ const timer = setTimeout(() => controller.abort(), this.opts.timeoutMs);
322
+ try {
323
+ const res = await globalThis.fetch(url, {
324
+ ...init,
325
+ signal: controller.signal,
326
+ headers: { 'User-Agent': 'PermitCore-Node/1.0', ...(init?.headers ?? {}) },
327
+ });
328
+ if (!res.ok && res.status >= 500)
329
+ throw new Error(`HTTP ${res.status}`);
330
+ // checkin() gets a 204 No Content on success — res.json() would throw on the empty body.
331
+ if (res.status === 204)
332
+ return undefined;
333
+ const text = await res.text();
334
+ return (text ? JSON.parse(text) : undefined);
335
+ }
336
+ finally {
337
+ clearTimeout(timer);
338
+ }
339
+ }
340
+ /**
341
+ * [S-Grace1] Caches the SIGNED token, not the raw response — the server only issues
342
+ * `offlineCacheToken` when a grace period is configured, so a null/missing token here
343
+ * already means "nothing to cache," same as the old `offlineGraceDays` check. The
344
+ * unverified `tenantSlug` is read out of the token purely to pick which tenant's
345
+ * public key to fetch (see `extractUnverifiedTenantSlug`); nothing is trusted or
346
+ * persisted until `verifyGraceCacheToken` confirms the signature against that key.
347
+ */
348
+ async saveToCache(licenseKey, result) {
349
+ if (!this.opts.enableOfflineCache || !result.offlineCacheToken)
350
+ return;
351
+ try {
352
+ const tenantSlug = extractUnverifiedTenantSlug(result.offlineCacheToken);
353
+ if (!tenantSlug)
354
+ return;
355
+ const pubKeyResp = await this.fetch(`${this.baseUrl}/api/v1/${encodeURIComponent(tenantSlug)}/public-key`);
356
+ if (!pubKeyResp?.publicKey)
357
+ return;
358
+ // Verify before persisting anything — never cache a token this SDK can't itself
359
+ // verify later; that would just recreate the old "trust an opaque file" problem.
360
+ const check = this.verifyGraceCacheToken(result.offlineCacheToken, pubKeyResp.publicKey);
361
+ if (!check.isValid)
362
+ return;
363
+ const entry = { token: result.offlineCacheToken, publicKey: pubKeyResp.publicKey };
364
+ fs.writeFileSync(getCachePath(licenseKey), JSON.stringify(entry));
365
+ }
366
+ catch { /* cache failure must never block normal flow */ }
367
+ }
368
+ /**
369
+ * No network call here — verification uses only the public key persisted alongside the
370
+ * token at save time. This is the entire point: a hand-edited cache file (or one copied
371
+ * to another machine) fails ECDSA verification instead of silently working.
372
+ */
373
+ loadFromCache(licenseKey) {
374
+ if (!this.opts.enableOfflineCache)
375
+ return null;
376
+ try {
377
+ const data = fs.readFileSync(getCachePath(licenseKey), 'utf8');
378
+ const entry = JSON.parse(data);
379
+ if (!entry?.token || !entry?.publicKey)
380
+ return null;
381
+ const check = this.verifyGraceCacheToken(entry.token, entry.publicKey);
382
+ if (!check.isValid || !check.payload)
383
+ return null;
384
+ const p = check.payload;
385
+ return {
386
+ isValid: p.isValid,
387
+ productName: p.productName ?? undefined,
388
+ remainingActivations: p.remainingActivations ?? undefined,
389
+ expiresAt: p.expiresAt ?? undefined,
390
+ features: p.features ?? undefined,
391
+ isOffline: true,
392
+ message: `Offline mode — valid until ${p.validUntil} (cryptographically verified)`,
393
+ };
394
+ }
395
+ catch {
396
+ return null;
397
+ }
398
+ }
399
+ }
400
+ exports.PermitCoreClient = PermitCoreClient;
401
+ // ── Helpers ────────────────────────────────────────────────────────────────
402
+ function getCachePath(licenseKey) {
403
+ const hash = crypto.createHash('sha256').update(licenseKey).digest('hex').slice(0, 16);
404
+ return path.join(os.tmpdir(), `.permitcore_cache_${hash}`);
405
+ }
406
+ function getOfflineActivationPath(deviceId) {
407
+ const hash = crypto.createHash('sha256').update(deviceId).digest('hex').slice(0, 16);
408
+ return path.join(os.tmpdir(), `.permitcore_offline_${hash}`);
409
+ }
410
+ // Reads only the `tenantSlug` field out of a pc_grace_v1 token's payload, WITHOUT verifying
411
+ // the signature — safe to do because it's only used to pick which tenant's public-key
412
+ // endpoint to fetch. The subsequent verifyGraceCacheToken call is what actually establishes
413
+ // trust before anything gets persisted to disk.
414
+ function extractUnverifiedTenantSlug(token) {
415
+ try {
416
+ const parts = token.split('.');
417
+ if (parts.length !== 3 || parts[0] !== 'pc_grace_v1')
418
+ return null;
419
+ const json = Buffer.from(parts[1], 'base64url').toString('utf8');
420
+ const payload = JSON.parse(json);
421
+ return payload.tenantSlug ?? null;
422
+ }
423
+ catch {
424
+ return null;
425
+ }
426
+ }
427
+ function getOrCreateSeedFile() {
428
+ const seedPath = path.join(os.homedir(), '.permitcore_seed');
429
+ try {
430
+ if (!fs.existsSync(seedPath))
431
+ fs.writeFileSync(seedPath, crypto.randomUUID());
432
+ return fs.readFileSync(seedPath, 'utf8').trim();
433
+ }
434
+ catch {
435
+ return '';
436
+ }
437
+ }
438
+ // ── Default export ─────────────────────────────────────────────────────────
439
+ exports.default = PermitCoreClient;
440
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@permitcore/permitcore",
3
+ "version": "1.0.0",
4
+ "description": "Official Node.js SDK for PermitCore license management",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "npm run build && node --test test/*.test.js",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "license",
18
+ "licensing",
19
+ "sdk",
20
+ "permitcore",
21
+ "activation"
22
+ ],
23
+ "author": "PermitCore",
24
+ "license": "MIT",
25
+ "homepage": "https://permitcore.dev",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/permitCore-spec/PermitCore",
29
+ "directory": "SDKs/node"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^26.1.2",
33
+ "typescript": "^7.0.2"
34
+ },
35
+ "engines": {
36
+ "node": ">=16"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }