@moonbase.sh/licensing 2.0.1 → 3.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.
- package/FINGERPRINT_SPEC.md +647 -0
- package/README.md +143 -6
- package/dist/index.cjs +599 -66
- package/dist/index.d.cts +367 -14
- package/dist/index.d.ts +367 -14
- package/dist/index.js +581 -67
- package/fingerprint-vectors.json +948 -0
- package/package.json +8 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,329 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reference implementation of the Moonbase device fingerprint spec (v2). The
|
|
6
|
+
* authoritative, language-neutral definition lives in FINGERPRINT_SPEC.md, and
|
|
7
|
+
* the machine-readable conformance suite in fingerprint-vectors.json. Any SDK
|
|
8
|
+
* that conforms computes the same id on a given machine. Keep all three in
|
|
9
|
+
* lockstep; when they disagree, the vectors decide.
|
|
10
|
+
*
|
|
11
|
+
* A device id is a stamped SHA-256 of a deterministic "material" string built
|
|
12
|
+
* from stable native hardware identifiers:
|
|
13
|
+
*
|
|
14
|
+
* mbd2_<lowercase-hex sha256 of the material>
|
|
15
|
+
*
|
|
16
|
+
* Material layout (lines joined with "\n", NO trailing newline):
|
|
17
|
+
*
|
|
18
|
+
* moonbase:fingerprint:v2
|
|
19
|
+
* platform=<tag>
|
|
20
|
+
* <name>=<value>
|
|
21
|
+
* ...
|
|
22
|
+
*
|
|
23
|
+
* Every value is canonicalized (NFC, non-printable-ASCII dropped, capped,
|
|
24
|
+
* space-trimmed); empty values are skipped; duplicate parameter names are
|
|
25
|
+
* rejected; and a material that does not identify the individual machine — no
|
|
26
|
+
* parameters at all, or only model-level ones — is an error rather than a digest,
|
|
27
|
+
* so a machine or a whole product line can never share one id.
|
|
28
|
+
*/
|
|
29
|
+
declare const FINGERPRINT_PREFIX = "moonbase:fingerprint:v2";
|
|
30
|
+
/** Spec version. Always equal to the digit in {@link FINGERPRINT_PREFIX} and in the stamp. */
|
|
31
|
+
declare const FINGERPRINT_VERSION = 2;
|
|
32
|
+
/** Longest permitted canonical value, in characters. */
|
|
33
|
+
declare const MAX_VALUE_LENGTH = 128;
|
|
34
|
+
/**
|
|
35
|
+
* What the material was built from. `identity` is the real hardware fingerprint;
|
|
36
|
+
* `deviceName` is the opt-in, deliberately weaker host-name fallback; `scoped` is
|
|
37
|
+
* an id that is stable only within one app scope (iOS/Android, where the platform
|
|
38
|
+
* exposes nothing an unrelated app can read). Each is stamped distinctly so a
|
|
39
|
+
* server can tell them apart.
|
|
40
|
+
*/
|
|
41
|
+
type DeviceIdSource = 'identity' | 'deviceName' | 'scoped';
|
|
42
|
+
/** The tags this version defines, as a detached frozen map (see {@link IDENTIFYING_PARAM_NAMES}). */
|
|
43
|
+
declare const DEVICE_ID_SOURCE_TAGS: Readonly<Record<DeviceIdSource, string>>;
|
|
44
|
+
type PlatformTag = 'mac' | 'ios' | 'windows' | 'android' | 'linux' | 'bsd' | 'unknown';
|
|
45
|
+
/**
|
|
46
|
+
* The source a successful identity read earns on this platform.
|
|
47
|
+
*
|
|
48
|
+
* Scoped platforms expose no identifier an unrelated app can read, so anything
|
|
49
|
+
* built from their parameters is scoped to the app and must be stamped `mbd2s_`.
|
|
50
|
+
* Stamping it `mbd2_` would tell a server the id is a hardware fingerprint
|
|
51
|
+
* comparable across every app on the device, which is exactly what it is not:
|
|
52
|
+
* the server would then be entitled to correlate ids the spec forbids
|
|
53
|
+
* correlating, and a diagnostic would offer remedies that cannot apply.
|
|
54
|
+
*
|
|
55
|
+
* Derived from the platform rather than chosen by the caller, so a host that
|
|
56
|
+
* bridges `identifierForVendor` or `androidId` through a custom
|
|
57
|
+
* {@link DeviceIdentityReader} cannot accidentally mislabel it.
|
|
58
|
+
*/
|
|
59
|
+
declare function identitySource(platform: PlatformTag): DeviceIdSource;
|
|
60
|
+
type FingerprintParam = readonly [name: string, value: string];
|
|
61
|
+
interface DeviceIdentity {
|
|
62
|
+
/** Ordered identity params. Empty values are dropped by the material builder. */
|
|
63
|
+
params: FingerprintParam[];
|
|
64
|
+
/** Human-readable device name. Never part of the default material. */
|
|
65
|
+
deviceName: string;
|
|
66
|
+
}
|
|
67
|
+
/** Reads raw device identity for the current platform. Injectable for testing. */
|
|
68
|
+
interface DeviceIdentityReader {
|
|
69
|
+
read: () => DeviceIdentity;
|
|
70
|
+
}
|
|
71
|
+
/** A device id stamp broken into its parts (see {@link parseDeviceIdStamp}). */
|
|
72
|
+
interface DeviceIdStamp {
|
|
73
|
+
/** Fingerprint spec version that produced the digest. */
|
|
74
|
+
version: number;
|
|
75
|
+
/** The literal source tag: `''`, `'n'`, `'s'`, or one a newer SDK introduced. */
|
|
76
|
+
sourceTag: string;
|
|
77
|
+
/** What {@link sourceTag} means, or `null` when this SDK does not define that tag. */
|
|
78
|
+
source: DeviceIdSource | null;
|
|
79
|
+
/** The 64-char lowercase-hex SHA-256. */
|
|
80
|
+
digest: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Canonicalize a raw value read from the system (see FINGERPRINT_SPEC.md,
|
|
84
|
+
* "Canonicalizing values"): NFC-normalize, drop every character outside
|
|
85
|
+
* printable ASCII, cap the length, then trim spaces from both ends.
|
|
86
|
+
*
|
|
87
|
+
* Dropping non-printables is what makes the algorithm implementable
|
|
88
|
+
* byte-identically in any language: it removes the newline-injection ambiguity
|
|
89
|
+
* from the material grammar, and it makes the decoding choice for raw firmware
|
|
90
|
+
* strings (latin1 vs. UTF-8 vs. raw bytes) immaterial, since every byte those
|
|
91
|
+
* decodings disagree about is discarded either way.
|
|
92
|
+
*/
|
|
93
|
+
declare function canonicalizeValue(value: string): string;
|
|
94
|
+
/**
|
|
95
|
+
* Map a Node.js `process.platform` value onto a canonical platform tag, or pass
|
|
96
|
+
* through a value that is already one.
|
|
97
|
+
*
|
|
98
|
+
* The passthrough is what makes the mobile platforms reachable at all. Node does
|
|
99
|
+
* not run on iOS, so `process.platform` is never `'ios'` and no amount of mapping
|
|
100
|
+
* can produce that tag — yet a host embedding Node can bridge
|
|
101
|
+
* `identifierForVendor` from platform API. Without this, such a host has no way
|
|
102
|
+
* to say which platform it is on: the value would fall through to `'unknown'`,
|
|
103
|
+
* and the material would carry `platform=unknown`, so the digest would not match
|
|
104
|
+
* what a conforming iOS SDK computes on the same device, and the id would be
|
|
105
|
+
* stamped `mbd2_` rather than `mbd2s_`. Both wrong, and both silent.
|
|
106
|
+
*
|
|
107
|
+
* `'android'` and `'linux'` belong to both vocabularies and map to themselves, so
|
|
108
|
+
* the two spellings cannot disagree.
|
|
109
|
+
*/
|
|
110
|
+
declare function platformTag(platform?: NodeJS.Platform | PlatformTag): PlatformTag;
|
|
111
|
+
/**
|
|
112
|
+
* The identifying parameter names, as a detached frozen list.
|
|
113
|
+
*
|
|
114
|
+
* Deliberately not the `Set` this module checks against. `ReadonlySet` is erased
|
|
115
|
+
* at compile time, so exporting the live set would let any JavaScript consumer —
|
|
116
|
+
* or any dependency — call `.add('sysVendor')` and turn model-level values into
|
|
117
|
+
* accepted identity for the whole process, silently undoing the collision
|
|
118
|
+
* protection below.
|
|
119
|
+
*/
|
|
120
|
+
declare const IDENTIFYING_PARAM_NAMES: readonly string[];
|
|
121
|
+
/**
|
|
122
|
+
* Canonicalize every value and drop the ones that end up empty, plus any
|
|
123
|
+
* identifying parameter holding an unprogrammed placeholder. Order is preserved.
|
|
124
|
+
* Exported so a caller can see which parameters actually contributed without
|
|
125
|
+
* rebuilding the material.
|
|
126
|
+
*
|
|
127
|
+
* @throws when two surviving parameters share a name — the material grammar has
|
|
128
|
+
* no way to express that, so it is a collection bug rather than a machine state.
|
|
129
|
+
*/
|
|
130
|
+
declare function canonicalizeParams(params: ReadonlyArray<FingerprintParam>): FingerprintParam[];
|
|
131
|
+
/**
|
|
132
|
+
* Assemble the canonical fingerprint material string. Pure and deterministic —
|
|
133
|
+
* exported so consumers can verify cross-SDK parity against the shipped vectors.
|
|
134
|
+
*
|
|
135
|
+
* @throws {InsufficientDeviceIdentityError} when no parameter survives canonicalization, or when
|
|
136
|
+
* none of the survivors identifies the individual machine.
|
|
137
|
+
*/
|
|
138
|
+
declare function buildFingerprintMaterial(platform: PlatformTag, params: ReadonlyArray<FingerprintParam>): string;
|
|
139
|
+
/** Hash fingerprint material into a bare digest: 64-char lowercase hex SHA-256. */
|
|
140
|
+
declare function fingerprintDigest(material: string): string;
|
|
141
|
+
/** Prefix a digest with its version and source, producing the wire-form device id. */
|
|
142
|
+
declare function stampDeviceId(digest: string, source?: DeviceIdSource): string;
|
|
143
|
+
/** Hash material and stamp it: the full device id as sent to Moonbase and stored in `sig`. */
|
|
144
|
+
declare function fingerprintDeviceId(material: string, source?: DeviceIdSource): string;
|
|
145
|
+
/**
|
|
146
|
+
* Split a stamped device id into its parts, or `null` if it is not a Moonbase
|
|
147
|
+
* stamp at all (a legacy id, or one from a custom resolver). Lets a validator tell
|
|
148
|
+
* "this license belongs to another machine" apart from "this license was bound
|
|
149
|
+
* by an older fingerprint version".
|
|
150
|
+
*
|
|
151
|
+
* An id whose *tag* is unrecognised still parses, with `source` null: it came from
|
|
152
|
+
* a newer SDK, and reporting it as unparseable would be worse than saying so.
|
|
153
|
+
*/
|
|
154
|
+
declare function parseDeviceIdStamp(deviceId: string): DeviceIdStamp | null;
|
|
155
|
+
/** Extract `IOPlatformUUID` from `ioreg` output: hyphens stripped, uppercased (spec: macOS `ioPlatformUuid`). */
|
|
156
|
+
declare function parseIoregPlatformUuid(ioregOutput: string): string;
|
|
157
|
+
/**
|
|
158
|
+
* Pick the first source holding a real machine id, or `''`.
|
|
159
|
+
*
|
|
160
|
+
* Each candidate is *validated*, not merely checked for being non-empty:
|
|
161
|
+
* `machine-id(5)` defines the file as exactly 32 lowercase hex digits, and
|
|
162
|
+
* legitimately holds the literal marker `uninitialized` in an initrd or a golden
|
|
163
|
+
* image awaiting first boot. Every machine deployed from such an image reads that
|
|
164
|
+
* same marker, so accepting it would hand them all one device id — and would also
|
|
165
|
+
* stop the fall-through to a D-Bus id that may be perfectly valid.
|
|
166
|
+
*/
|
|
167
|
+
declare function selectMachineId(...sources: string[]): string;
|
|
168
|
+
/**
|
|
169
|
+
* Extract the ordered identity params from a raw SMBIOS structure table: the
|
|
170
|
+
* **first** type-1 (System) and **first** type-2 (Baseboard) structures only.
|
|
171
|
+
*
|
|
172
|
+
* Type 4 (Processor) is deliberately not collected — its values are model-class
|
|
173
|
+
* rather than per-machine, and the number of type-4 structures tracks the CPU
|
|
174
|
+
* socket / vCPU count, so collecting them would change the device id whenever a
|
|
175
|
+
* VM is resized.
|
|
176
|
+
*/
|
|
177
|
+
declare function parseSmbiosParams(smbiosData: Buffer): FingerprintParam[];
|
|
178
|
+
/** The real, platform-dispatching identity reader used by {@link MoonbaseDeviceIdResolver}. */
|
|
179
|
+
declare function defaultDeviceIdentityReader(platform?: NodeJS.Platform | PlatformTag): DeviceIdentityReader;
|
|
180
|
+
|
|
3
181
|
interface IDeviceIdResolver {
|
|
182
|
+
resolveDeviceName: () => Promise<string>;
|
|
183
|
+
resolveDeviceId: () => Promise<string>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* A device id plus the provenance needed to reason about it — safe to log, show
|
|
187
|
+
* in an about box, or attach to a support ticket.
|
|
188
|
+
*
|
|
189
|
+
* Parameter *names* only, deliberately. Their values are hardware serial numbers,
|
|
190
|
+
* and a hash of one is no safer to publish: an unsalted digest is a stable global
|
|
191
|
+
* correlator for the machine, and low-entropy values like host names or
|
|
192
|
+
* sequential serials fall to a dictionary. `machine-id(5)` is explicit that the
|
|
193
|
+
* Linux machine id is confidential and must only ever be exposed through an
|
|
194
|
+
* application-specific *keyed* hash. Which parameters contributed is the useful
|
|
195
|
+
* diagnostic anyway; what they read is not.
|
|
196
|
+
*/
|
|
197
|
+
interface DeviceIdDescription {
|
|
198
|
+
deviceId: string;
|
|
199
|
+
/** Fingerprint spec version that produced it. */
|
|
200
|
+
version: number;
|
|
201
|
+
platform: PlatformTag;
|
|
202
|
+
source: DeviceIdSource;
|
|
203
|
+
/** Names of the identity parameters that went into the material, in order. */
|
|
204
|
+
paramNames: string[];
|
|
205
|
+
}
|
|
206
|
+
/** A resolver that can explain how it arrived at its device id. */
|
|
207
|
+
interface IDescribableDeviceIdResolver extends IDeviceIdResolver {
|
|
208
|
+
describeDevice: () => Promise<DeviceIdDescription>;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* A resolver that also recognises device ids this machine used to have.
|
|
212
|
+
*
|
|
213
|
+
* Deliberately separate from {@link IDeviceIdResolver.resolveDeviceId}, which
|
|
214
|
+
* stays single-valued: what a device binds on activation and what a validator
|
|
215
|
+
* accepts are different questions, and conflating them is what forces the
|
|
216
|
+
* all-or-nothing migration choice.
|
|
217
|
+
*/
|
|
218
|
+
interface IMigratingDeviceIdResolver extends IDeviceIdResolver {
|
|
219
|
+
acceptsDeviceId: (deviceId: string) => Promise<boolean>;
|
|
220
|
+
}
|
|
221
|
+
interface MoonbaseDeviceIdResolverOptions {
|
|
222
|
+
/** Overrides the identity source. Primarily for testing. */
|
|
223
|
+
reader?: DeviceIdentityReader;
|
|
224
|
+
/**
|
|
225
|
+
* Overrides the detected platform. Accepts a Node.js `process.platform` value
|
|
226
|
+
* or a canonical {@link PlatformTag}.
|
|
227
|
+
*
|
|
228
|
+
* The tag spelling exists for hosts that bridge a platform Node does not run
|
|
229
|
+
* on: pass `'ios'` together with a {@link reader} that supplies
|
|
230
|
+
* `identifierForVendor`. Without it the platform would resolve to `'unknown'`,
|
|
231
|
+
* which changes the material and so the device id.
|
|
232
|
+
*/
|
|
233
|
+
platform?: NodeJS.Platform | PlatformTag;
|
|
234
|
+
/**
|
|
235
|
+
* What to do when no hardware identity is readable. `'none'` (the default)
|
|
236
|
+
* throws {@link InsufficientDeviceIdentityError}; `'deviceName'` falls back to
|
|
237
|
+
* hashing the host name, producing a deliberately weaker id stamped `mbd2n_`.
|
|
238
|
+
*
|
|
239
|
+
* The fallback is opt-in because a host name is user-renameable, frequently
|
|
240
|
+
* duplicated across imaged machines, and regenerated on every container start.
|
|
241
|
+
*
|
|
242
|
+
* It is **ignored on iOS and Android**, which throw regardless: there the host
|
|
243
|
+
* name is identical on every device, so the fallback would give a whole install
|
|
244
|
+
* base one id rather than merely a weak one.
|
|
245
|
+
*/
|
|
246
|
+
fallback?: 'none' | 'deviceName';
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Default resolver. Implements the Moonbase device fingerprint spec (v2; see
|
|
250
|
+
* FINGERPRINT_SPEC.md), building the `moonbase:fingerprint:v2` material from
|
|
251
|
+
* native hardware identifiers (SMBIOS on Windows, `IOPlatformUUID` on macOS,
|
|
252
|
+
* `machine-id` + DMI on Linux) and stamping its SHA-256 as `mbd2_<hex>`. Every
|
|
253
|
+
* Moonbase SDK that implements the spec produces the same id on a given machine.
|
|
254
|
+
*
|
|
255
|
+
* The result is memoized: reading identity can mean spawning a subprocess, and
|
|
256
|
+
* both activation and every validation ask for it.
|
|
257
|
+
*/
|
|
258
|
+
declare class MoonbaseDeviceIdResolver implements IDescribableDeviceIdResolver {
|
|
259
|
+
private readonly reader;
|
|
260
|
+
private readonly platform;
|
|
261
|
+
private readonly fallback;
|
|
262
|
+
private identity?;
|
|
263
|
+
private described?;
|
|
264
|
+
constructor(options?: MoonbaseDeviceIdResolverOptions);
|
|
265
|
+
resolveDeviceName(): Promise<string>;
|
|
266
|
+
resolveDeviceId(): Promise<string>;
|
|
267
|
+
/**
|
|
268
|
+
* A fresh copy each call. The device binding is what activation sends and what
|
|
269
|
+
* validation compares, so handing out the resolver's own object would let a
|
|
270
|
+
* consumer that edits a diagnostic — or logs it through something that
|
|
271
|
+
* normalizes in place — silently change the id every later call returns.
|
|
272
|
+
*/
|
|
273
|
+
describeDevice(): Promise<DeviceIdDescription>;
|
|
274
|
+
private compute;
|
|
275
|
+
/**
|
|
276
|
+
* Read identity at most once. Both halves of an activation request ask for it —
|
|
277
|
+
* the name and then the id — and a read can mean spawning `ioreg` or
|
|
278
|
+
* PowerShell, so reading per call would double the cost of every request and
|
|
279
|
+
* let the name and the id come from two different reads of the machine.
|
|
280
|
+
*/
|
|
281
|
+
private readIdentity;
|
|
282
|
+
private computeDescription;
|
|
283
|
+
private describe;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Binds the current fingerprint but keeps recognising ids this device was bound
|
|
287
|
+
* to before — the migration path off an older algorithm without a flag day.
|
|
288
|
+
*
|
|
289
|
+
* `resolveDeviceId` always returns the *current* resolver's id, so every new
|
|
290
|
+
* activation binds the current algorithm; the historical resolvers are consulted
|
|
291
|
+
* only when a validator is deciding whether to accept an already-issued license.
|
|
292
|
+
* A fleet therefore migrates as licenses are naturally re-activated, instead of
|
|
293
|
+
* every device re-activating at once — which would burn a second activation seat
|
|
294
|
+
* per device and reset device-scoped trials.
|
|
295
|
+
*
|
|
296
|
+
* ```ts
|
|
297
|
+
* new MigratingDeviceIdResolver(new MoonbaseDeviceIdResolver(), new LegacyDeviceIdResolver())
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* Historical ids are computed lazily — only on a mismatch — and then memoized,
|
|
301
|
+
* so the cost is never paid on the happy path. A historical resolver that throws
|
|
302
|
+
* is simply skipped.
|
|
303
|
+
*
|
|
304
|
+
* Every accepted id is recomputed from the machine's own hardware on each call.
|
|
305
|
+
* Nothing is read from disk, so widening what a validator accepts does not widen
|
|
306
|
+
* what an attacker can assert.
|
|
307
|
+
*/
|
|
308
|
+
declare class MigratingDeviceIdResolver implements IMigratingDeviceIdResolver {
|
|
309
|
+
private readonly current;
|
|
310
|
+
private readonly previous;
|
|
311
|
+
private previousIds?;
|
|
312
|
+
/** Forwarded so the current resolver stays describable through this wrapper. */
|
|
313
|
+
describeDevice?: () => Promise<DeviceIdDescription>;
|
|
314
|
+
constructor(current: IDeviceIdResolver, ...previous: IDeviceIdResolver[]);
|
|
4
315
|
resolveDeviceName(): Promise<string>;
|
|
5
316
|
resolveDeviceId(): Promise<string>;
|
|
317
|
+
acceptsDeviceId(deviceId: string): Promise<boolean>;
|
|
6
318
|
}
|
|
7
|
-
|
|
319
|
+
/**
|
|
320
|
+
* @deprecated The previous default resolver. Its device id is a base64 SHA-256 of
|
|
321
|
+
* normalized `systeminformation` fields and does **not** implement the
|
|
322
|
+
* `moonbase:fingerprint:v2` spec (FINGERPRINT_SPEC.md). Kept so deployments can keep
|
|
323
|
+
* validating licenses that were bound under the old id during migration; prefer
|
|
324
|
+
* {@link MoonbaseDeviceIdResolver}.
|
|
325
|
+
*/
|
|
326
|
+
declare class LegacyDeviceIdResolver implements IDeviceIdResolver {
|
|
8
327
|
resolveDeviceName(): Promise<string>;
|
|
9
328
|
resolveDeviceId(): Promise<string>;
|
|
10
329
|
}
|
|
@@ -175,7 +494,7 @@ interface ILicenseClient {
|
|
|
175
494
|
*
|
|
176
495
|
* @returns Details about the requested activation with url to open in the browser
|
|
177
496
|
*/
|
|
178
|
-
requestActivation()
|
|
497
|
+
requestActivation: () => Promise<ActivationRequestResponse>;
|
|
179
498
|
/**
|
|
180
499
|
* Takes in a activation request created through {@link requestActivation}
|
|
181
500
|
* and checks if the request has been fulfilled yet.
|
|
@@ -185,7 +504,7 @@ interface ILicenseClient {
|
|
|
185
504
|
* @param request The activation request to poll
|
|
186
505
|
* @returns A license if the request has been fulfilled, else null
|
|
187
506
|
*/
|
|
188
|
-
getRequestedActivation(request: ActivationRequestResponse)
|
|
507
|
+
getRequestedActivation: (request: ActivationRequestResponse) => Promise<License | null>;
|
|
189
508
|
/**
|
|
190
509
|
* Requests a trial license for the product.
|
|
191
510
|
* This can only be done once per product per device, and skips
|
|
@@ -194,7 +513,7 @@ interface ILicenseClient {
|
|
|
194
513
|
*
|
|
195
514
|
* @returns The allocated trial license, throws if the trial license cannot be allocated (e.g. user already had a trial) or if the request failed
|
|
196
515
|
*/
|
|
197
|
-
requestTrial()
|
|
516
|
+
requestTrial: () => Promise<License>;
|
|
198
517
|
/**
|
|
199
518
|
* Checks if the given license is still valid, not revoked
|
|
200
519
|
* and returns an updated license if still active.
|
|
@@ -205,7 +524,7 @@ interface ILicenseClient {
|
|
|
205
524
|
* @param license The license to validate
|
|
206
525
|
* @returns An updated license
|
|
207
526
|
*/
|
|
208
|
-
validateLicense(license: License)
|
|
527
|
+
validateLicense: (license: License) => Promise<License>;
|
|
209
528
|
/**
|
|
210
529
|
* Contrary to {@linkvalidateLicense }, this method takes
|
|
211
530
|
* in raw bytes of the license, which can be useful if you're
|
|
@@ -214,14 +533,14 @@ interface ILicenseClient {
|
|
|
214
533
|
* @param license The license to validate
|
|
215
534
|
* @returns An updated license
|
|
216
535
|
*/
|
|
217
|
-
validateRawLicense(rawLicense: Buffer)
|
|
536
|
+
validateRawLicense: (rawLicense: Buffer) => Promise<License>;
|
|
218
537
|
/**
|
|
219
538
|
* Given a license, this method will try to revoke the license activation,
|
|
220
539
|
* freeing up a seat for other devices to activate the license.
|
|
221
540
|
* This will not work for offline-activated devices.
|
|
222
541
|
* @param license The license to revoke
|
|
223
542
|
*/
|
|
224
|
-
revokeLicense(license: License)
|
|
543
|
+
revokeLicense: (license: License) => Promise<void>;
|
|
225
544
|
}
|
|
226
545
|
declare class LicenseClient implements ILicenseClient {
|
|
227
546
|
private readonly configuration;
|
|
@@ -239,9 +558,9 @@ declare class LicenseClient implements ILicenseClient {
|
|
|
239
558
|
}
|
|
240
559
|
|
|
241
560
|
interface ILicenseStore {
|
|
242
|
-
loadLocalLicense()
|
|
243
|
-
storeLocalLicense(license: License)
|
|
244
|
-
deleteLocalLicense()
|
|
561
|
+
loadLocalLicense: () => Promise<License | null>;
|
|
562
|
+
storeLocalLicense: (license: License) => Promise<void>;
|
|
563
|
+
deleteLocalLicense: () => Promise<void>;
|
|
245
564
|
}
|
|
246
565
|
declare class InMemoryLicenseStore implements ILicenseStore {
|
|
247
566
|
private license?;
|
|
@@ -262,13 +581,19 @@ declare class FileLicenseStore implements ILicenseStore {
|
|
|
262
581
|
}
|
|
263
582
|
|
|
264
583
|
interface ILicenseValidator {
|
|
265
|
-
validateLicense(token: string)
|
|
584
|
+
validateLicense: (token: string) => Promise<License>;
|
|
266
585
|
}
|
|
267
586
|
declare class LicenseValidator implements ILicenseValidator {
|
|
268
587
|
private readonly configuration;
|
|
269
588
|
private readonly deviceIdResolver;
|
|
270
589
|
constructor(configuration: MoonbaseConfiguration, deviceIdResolver: IDeviceIdResolver);
|
|
271
590
|
validateLicense(token: string): Promise<License>;
|
|
591
|
+
/**
|
|
592
|
+
* Give a {@link IMigratingDeviceIdResolver} the chance to vouch for a device id
|
|
593
|
+
* this machine used to have. Only consulted after the fast path fails, so
|
|
594
|
+
* apps that have not opted into a migration pay nothing.
|
|
595
|
+
*/
|
|
596
|
+
private acceptsHistoricalDeviceId;
|
|
272
597
|
private parseLicenseToken;
|
|
273
598
|
}
|
|
274
599
|
|
|
@@ -279,7 +604,11 @@ declare enum ErrorType {
|
|
|
279
604
|
LicenseInvalid = "LicenseInvalid",
|
|
280
605
|
LicenseRevoked = "LicenseRevoked",
|
|
281
606
|
LicenseActivationRevoked = "LicenseActivationRevoked",
|
|
282
|
-
LicenseExpired = "LicenseExpired"
|
|
607
|
+
LicenseExpired = "LicenseExpired",
|
|
608
|
+
/** The license is valid but bound to a different device, or to an older fingerprint version. */
|
|
609
|
+
LicenseDeviceMismatch = "LicenseDeviceMismatch",
|
|
610
|
+
/** No stable hardware identifier could be read, so no device id can be computed. */
|
|
611
|
+
DeviceIdentityUnavailable = "DeviceIdentityUnavailable"
|
|
283
612
|
}
|
|
284
613
|
declare class MoonbaseError extends Error {
|
|
285
614
|
readonly title: string;
|
|
@@ -288,6 +617,30 @@ declare class MoonbaseError extends Error {
|
|
|
288
617
|
readonly inner?: Error | undefined;
|
|
289
618
|
constructor(title: string, detail: string | undefined, type?: ErrorType | undefined, inner?: Error | undefined);
|
|
290
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* Thrown when the device fingerprint has nothing machine-specific to hash —
|
|
622
|
+
* either no parameter could be read at all, or the only ones that could are
|
|
623
|
+
* model-level (vendor, product and board names, shared by every unit of a
|
|
624
|
+
* product line).
|
|
625
|
+
*
|
|
626
|
+
* The spec deliberately makes both an error rather than hashing what is there:
|
|
627
|
+
* either would hand a whole class of machines the *same* device id, and a license
|
|
628
|
+
* bound to it would validate on all of them.
|
|
629
|
+
*
|
|
630
|
+
* Reachable on platforms with no identity parameters this package can read (BSD
|
|
631
|
+
* and anything unknown, which the spec leaves undefined, plus Android, whose
|
|
632
|
+
* `androidId` needs Android-framework API a Node.js process cannot call); when
|
|
633
|
+
* every source fails — a sandboxed process that cannot spawn `ioreg`, a container
|
|
634
|
+
* with no DMI, a blocked PowerShell; and on machines whose per-device identifiers
|
|
635
|
+
* are simply absent, such as a Linux install with no `machine-id` or a VM whose
|
|
636
|
+
* SMBIOS carries an unset UUID and a blank baseboard serial. Enable the host-name
|
|
637
|
+
* fallback (`new MoonbaseDeviceIdResolver({ fallback: 'deviceName' })`) to accept
|
|
638
|
+
* a deliberately weaker id on those machines.
|
|
639
|
+
*/
|
|
640
|
+
declare class InsufficientDeviceIdentityError extends MoonbaseError {
|
|
641
|
+
readonly platform: string;
|
|
642
|
+
constructor(platform: string, reason?: string);
|
|
643
|
+
}
|
|
291
644
|
|
|
292
645
|
interface MoonbaseConfiguration {
|
|
293
646
|
endpoint: string;
|
|
@@ -318,7 +671,7 @@ interface MoonbaseConfiguration {
|
|
|
318
671
|
*/
|
|
319
672
|
appVersion?: string;
|
|
320
673
|
licenseStore?: ILicenseStore;
|
|
321
|
-
|
|
674
|
+
deviceIdResolver?: IDeviceIdResolver;
|
|
322
675
|
}
|
|
323
676
|
declare class MoonbaseLicensing {
|
|
324
677
|
private readonly configuration;
|
|
@@ -331,4 +684,4 @@ declare class MoonbaseLicensing {
|
|
|
331
684
|
readRawLicense(license: Buffer): Promise<License>;
|
|
332
685
|
}
|
|
333
686
|
|
|
334
|
-
export { ActivationMethod, type ActivationRequestResponse,
|
|
687
|
+
export { ActivationMethod, type ActivationRequestResponse, DEVICE_ID_SOURCE_TAGS, type DeviceIdDescription, type DeviceIdSource, type DeviceIdStamp, type DeviceIdentity, type DeviceIdentityReader, type DeviceToken, ErrorType, FINGERPRINT_PREFIX, FINGERPRINT_VERSION, FileLicenseStore, type FingerprintParam, IDENTIFYING_PARAM_NAMES, type IDescribableDeviceIdResolver, type IDeviceIdResolver, type ILicenseClient, type ILicenseStore, type ILicenseValidator, type IMigratingDeviceIdResolver, InMemoryLicenseStore, InsufficientDeviceIdentityError, LegacyDeviceIdResolver, type License, LicenseClient, LicenseValidator, MAX_VALUE_LENGTH, type Metadata, MigratingDeviceIdResolver, type MoonbaseConfiguration, MoonbaseDeviceIdResolver, type MoonbaseDeviceIdResolverOptions, MoonbaseError, MoonbaseLicensing, type Platform, type PlatformTag, type Product, type User, buildFingerprintMaterial, canonicalizeParams, canonicalizeValue, defaultDeviceIdentityReader, fingerprintDeviceId, fingerprintDigest, identitySource, parseDeviceIdStamp, parseIoregPlatformUuid, parseSmbiosParams, platformTag, selectMachineId, stampDeviceId };
|