@ledgerhq/revault-sdk 0.12.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 (45) hide show
  1. package/LICENSE.md +202 -0
  2. package/README.md +18 -0
  3. package/lib/bake.cjs +812 -0
  4. package/lib/bake.cjs.map +1 -0
  5. package/lib/bake.d.cts +2659 -0
  6. package/lib/bake.d.ts +2659 -0
  7. package/lib/bake.js +812 -0
  8. package/lib/bake.js.map +1 -0
  9. package/lib/chunk-DPHEFR6E.js +493 -0
  10. package/lib/chunk-DPHEFR6E.js.map +1 -0
  11. package/lib/chunk-QOP5LA3E.cjs +35 -0
  12. package/lib/chunk-QOP5LA3E.cjs.map +1 -0
  13. package/lib/chunk-VCAQTGQE.cjs +493 -0
  14. package/lib/chunk-VCAQTGQE.cjs.map +1 -0
  15. package/lib/chunk-VHZJP75X.js +35 -0
  16. package/lib/chunk-VHZJP75X.js.map +1 -0
  17. package/lib/device.cjs +13 -0
  18. package/lib/device.cjs.map +1 -0
  19. package/lib/device.d.cts +50 -0
  20. package/lib/device.d.ts +50 -0
  21. package/lib/device.js +13 -0
  22. package/lib/device.js.map +1 -0
  23. package/lib/engine.cjs +704 -0
  24. package/lib/engine.cjs.map +1 -0
  25. package/lib/engine.d.cts +18 -0
  26. package/lib/engine.d.ts +18 -0
  27. package/lib/engine.js +704 -0
  28. package/lib/engine.js.map +1 -0
  29. package/lib/index.cjs +1 -0
  30. package/lib/index.cjs.map +1 -0
  31. package/lib/index.d.cts +13 -0
  32. package/lib/index.d.ts +13 -0
  33. package/lib/index.js +1 -0
  34. package/lib/index.js.map +1 -0
  35. package/lib/onboarding.cjs +160 -0
  36. package/lib/onboarding.cjs.map +1 -0
  37. package/lib/onboarding.d.cts +1735 -0
  38. package/lib/onboarding.d.ts +1735 -0
  39. package/lib/onboarding.js +160 -0
  40. package/lib/onboarding.js.map +1 -0
  41. package/lib/types-BYNH6EdK.d.cts +199 -0
  42. package/lib/types-CsvE9Mlb.d.cts +159 -0
  43. package/lib/types-CsvE9Mlb.d.ts +159 -0
  44. package/lib/types-DHZzeq9X.d.ts +199 -0
  45. package/package.json +75 -0
package/lib/engine.js ADDED
@@ -0,0 +1,704 @@
1
+ import {
2
+ fetchAll
3
+ } from "./chunk-VHZJP75X.js";
4
+ import {
5
+ APPID_VAULT_ADMINISTRATOR,
6
+ PAGINATED_STATUS,
7
+ PATHS,
8
+ SCRIPT_IDS,
9
+ STATUS_LENGTH,
10
+ STREAMING_NEXT_ACTION,
11
+ STREAMING_RESPONSE,
12
+ STR_ROLES,
13
+ createApiDevice,
14
+ isTransportStatusError,
15
+ withDevicePolling
16
+ } from "./chunk-DPHEFR6E.js";
17
+
18
+ // src/engine/index.ts
19
+ import invariant2 from "invariant";
20
+
21
+ // src/device/real-device.ts
22
+ import { DisconnectedDevice, LockedDeviceError } from "@ledgerhq/errors";
23
+ import invariant from "invariant";
24
+ import { from, lastValueFrom } from "rxjs";
25
+ var MAX_CHUNK_LENGTH = 250;
26
+ var FIXME_NOT_IMPLEMENTED = (fnName) => async () => {
27
+ throw new Error(`Not implemented: ${fnName}`);
28
+ };
29
+ var getPathFromPathString = (pathString) => {
30
+ const parts = pathString.split("'/").map((part) => parseInt(part, 10));
31
+ return parts.map((part) => (part | 2147483648) >>> 0);
32
+ };
33
+ var splitChunks = (chunk, buffer) => {
34
+ const chunks = [];
35
+ for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {
36
+ chunks.push(buffer.slice(i, i + size));
37
+ }
38
+ return chunks;
39
+ };
40
+ var removeStatus = (result) => result.slice(0, result.length - STATUS_LENGTH);
41
+ var sendByChunk = async (transport, command, data, chunkSize = MAX_CHUNK_LENGTH) => {
42
+ const chunks = splitChunks(chunkSize, data);
43
+ let response = Buffer.from([]);
44
+ for (let i = 0; i < chunks.length; i++) {
45
+ const chunk = chunks[i];
46
+ const apdu = [...command];
47
+ apdu[2] = i && 128;
48
+ response = await transport.send(apdu[0], apdu[1], apdu[2], apdu[3], chunk, [
49
+ 36864,
50
+ ...PAGINATED_STATUS
51
+ ]);
52
+ }
53
+ return response;
54
+ };
55
+ var buildAttestation = (params) => {
56
+ const sigBuffer = Buffer.from(params.handshakeAttestation.signature, "base64");
57
+ const sigLengthBuffer = Buffer.alloc(1);
58
+ sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);
59
+ const certBuffer = Buffer.from(params.handshakeAttestation.certificate, "base64");
60
+ const certLengthBuffer = Buffer.alloc(1);
61
+ certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);
62
+ const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, "base64");
63
+ const certChainData = Buffer.concat([
64
+ sigLengthBuffer,
65
+ sigBuffer,
66
+ pubBuffer,
67
+ certLengthBuffer,
68
+ certBuffer
69
+ ]);
70
+ const cliMsgBuffer = Buffer.from(params.handshake, "hex");
71
+ const cliMsgLengthBuffer = Buffer.alloc(1);
72
+ cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);
73
+ const pidBuffer = Buffer.from(params.partitionId, "hex");
74
+ const pidLengthBuffer = Buffer.alloc(1);
75
+ pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);
76
+ const certChainDataLengthBuff = Buffer.alloc(2);
77
+ certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);
78
+ const data = Buffer.concat([
79
+ cliMsgLengthBuffer,
80
+ cliMsgBuffer,
81
+ certChainDataLengthBuff,
82
+ certChainData,
83
+ pidLengthBuffer,
84
+ pidBuffer
85
+ ]);
86
+ const totalLengthBuffer = Buffer.alloc(2);
87
+ totalLengthBuffer.writeUInt16BE(data.length, 0);
88
+ const toSend = Buffer.concat([totalLengthBuffer, data]);
89
+ return toSend;
90
+ };
91
+ var genericRetryOnError = (err) => {
92
+ if (err instanceof LockedDeviceError) return true;
93
+ if (isTransportStatusError(err) && err.statusCode === 27913) return true;
94
+ if (err instanceof DisconnectedDevice) return true;
95
+ return false;
96
+ };
97
+ function createRealDevice(options, logger) {
98
+ const { transportId } = options;
99
+ async function run(job, retryOnError = genericRetryOnError) {
100
+ return lastValueFrom(
101
+ withDevicePolling(transportId)((transport) => from(job(transport)), retryOnError)
102
+ );
103
+ }
104
+ const noRetry = () => false;
105
+ const poll = async () => {
106
+ await run(
107
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
108
+ async (_transport) => {
109
+ },
110
+ () => true
111
+ );
112
+ try {
113
+ await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });
114
+ return { isAppOpened: true };
115
+ } catch (err) {
116
+ if (isTransportStatusError(err) && genericRetryOnError(err)) {
117
+ return { isAppOpened: false };
118
+ }
119
+ throw err;
120
+ }
121
+ };
122
+ const pollApp = async (appName) => {
123
+ const res = await run(
124
+ (transport) => transport.send(224, 216, 0, 0, Buffer.from(appName, "utf8"))
125
+ );
126
+ await new Promise((r) => setTimeout(r, 1e3));
127
+ return res.toString("hex");
128
+ };
129
+ const getPublicKey = async (pathString, { secp256k1, retryOnError }) => {
130
+ logger.info(`[device] getPublicKey (${pathString})`);
131
+ const path = getPathFromPathString(pathString);
132
+ const data = Buffer.concat([
133
+ Buffer.from([path.length]),
134
+ ...path.map((derivation) => {
135
+ const buf = Buffer.alloc(4);
136
+ buf.writeUInt32BE(derivation, 0);
137
+ return buf;
138
+ })
139
+ ]);
140
+ const curve = secp256k1 ? 1 : 2;
141
+ const response = await run(
142
+ (transport) => transport.send(224, 64, curve, 0, data),
143
+ retryOnError ?? genericRetryOnError
144
+ );
145
+ const pubKeyLength = response.readInt8(0);
146
+ const pubKey = response.slice(1, pubKeyLength + 1).toString("hex").toUpperCase();
147
+ const signature = response.slice(pubKeyLength + 1, response.length - STATUS_LENGTH).toString("base64");
148
+ return { pubKey, signature };
149
+ };
150
+ const device = {
151
+ authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {
152
+ logger.info(`[device] Authenticate`);
153
+ invariant(role !== "READ_ONLY_API_KEY", "Invalid role for authenticate: READ_ONLY_API_KEY");
154
+ const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, "hex");
155
+ const nameBuffer = Buffer.from(name);
156
+ const workspaceBuffer = Buffer.from(workspaceName);
157
+ const keyHandleData = Buffer.concat([
158
+ Buffer.from(STR_ROLES[role], "hex"),
159
+ Buffer.from([nameBuffer.length]),
160
+ nameBuffer,
161
+ Buffer.from([workspaceBuffer.length]),
162
+ workspaceBuffer
163
+ ]);
164
+ const keyHandleDataLength = Buffer.alloc(2);
165
+ keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);
166
+ const data = Buffer.concat([
167
+ Buffer.from(challenge, "base64"),
168
+ applicationBuffer,
169
+ Buffer.from([keyHandle.length]),
170
+ Buffer.from(keyHandle, "hex"),
171
+ keyHandleDataLength,
172
+ keyHandleData
173
+ ]);
174
+ const authentication = await run(
175
+ (transport) => sendByChunk(transport, [224, 2, 0, 0], data)
176
+ );
177
+ return removeStatus(authentication).toString("hex");
178
+ },
179
+ finalizePairingHandshake: FIXME_NOT_IMPLEMENTED("finalizePairingHandshake"),
180
+ generateSeedFragment: FIXME_NOT_IMPLEMENTED("generateSeedFragment"),
181
+ generateWrappingKeyFragment: FIXME_NOT_IMPLEMENTED("generateWrappingKeyFragment"),
182
+ getAttestation: FIXME_NOT_IMPLEMENTED("getAttestation"),
183
+ getConfidentialityKey: async () => {
184
+ logger.info(`[device] getConfidentialityKey`);
185
+ const bufWithStatus = await run((transport) => transport.send(224, 77, 0, 0));
186
+ const buf = removeStatus(bufWithStatus);
187
+ const keyLength = buf[0];
188
+ const key = buf.slice(1, 1 + keyLength);
189
+ const sig = buf.slice(1 + keyLength + 1);
190
+ return {
191
+ confidentialityKeyCurve25519: key.toString("hex"),
192
+ confidentialityKeySignature: sig.toString("hex")
193
+ };
194
+ },
195
+ getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),
196
+ getDeviceUserId: FIXME_NOT_IMPLEMENTED("getDeviceUserId"),
197
+ getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),
198
+ getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),
199
+ hasPairing: async () => {
200
+ logger.info(`[device] hasPairing`);
201
+ const apdu = [224, 81, 0, 0, 181];
202
+ const res = await run((transport) => transport.exchange(Buffer.from(apdu)));
203
+ const hex = Buffer.from(res).toString("hex");
204
+ return hex !== "6f45" && hex !== "6a87";
205
+ },
206
+ initPairingHandshake: FIXME_NOT_IMPLEMENTED("initPairingHandshake"),
207
+ openSession: FIXME_NOT_IMPLEMENTED("openSession"),
208
+ register: FIXME_NOT_IMPLEMENTED("register"),
209
+ registerData: FIXME_NOT_IMPLEMENTED("registerData"),
210
+ setPairing: async ({ pairing }) => {
211
+ logger.info(`[device] setPairing`);
212
+ const psdPayload = Buffer.from(pairing.blob, "base64");
213
+ const length = Buffer.alloc(2);
214
+ length.writeUInt16BE(psdPayload.length, 0);
215
+ const final = Buffer.concat([length, psdPayload]);
216
+ await run((transport) => sendByChunk(transport, [224, 78, 0, 0], final));
217
+ },
218
+ startKKPatternAsResponder: FIXME_NOT_IMPLEMENTED("startKKPatternAsResponder"),
219
+ startKPatternAsResponder: async (params) => {
220
+ logger.info(`[device] startKPatternAsResponder`);
221
+ const data = buildAttestation(params);
222
+ await run(
223
+ (transport) => sendByChunk(transport, [224, 73, 0, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data)
224
+ );
225
+ },
226
+ validateVaultOperation: async (params) => {
227
+ logger.info(`[device] validateVaultOperation`);
228
+ const path = getPathFromPathString(PATHS.VALIDATION);
229
+ const paths = Buffer.concat([
230
+ Buffer.from([path.length]),
231
+ ...path.map((derivation) => {
232
+ const buf = Buffer.alloc(4);
233
+ buf.writeUInt32BE(derivation, 0);
234
+ return buf;
235
+ })
236
+ ]);
237
+ let nextActionId = 1;
238
+ let finalResponse;
239
+ while (!finalResponse) {
240
+ const screen = Buffer.from(params.actions[nextActionId - 1], "base64");
241
+ const length = Buffer.alloc(2);
242
+ length.writeUInt16BE(screen.length, 0);
243
+ const data = Buffer.concat([paths, length, screen]);
244
+ const response = await run(
245
+ (transport) => sendByChunk(transport, [224, 69, 0, 0], data)
246
+ );
247
+ const responseType = response.readInt8(0);
248
+ let responseStatus = response.readUInt16BE(response.length - 2);
249
+ if (responseType === STREAMING_NEXT_ACTION) {
250
+ nextActionId = response.readUIntBE(1, 2);
251
+ } else if (responseType === STREAMING_RESPONSE) {
252
+ finalResponse = response.slice(3, response.length - 2);
253
+ while (responseStatus !== 36864) {
254
+ const resp = await run((transport) => transport.send(0, 192, 0, 0));
255
+ responseStatus = resp.readUInt16BE(resp.length - 2);
256
+ finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);
257
+ }
258
+ } else {
259
+ throw Error(`${responseType}`);
260
+ }
261
+ }
262
+ return finalResponse.toString("base64");
263
+ },
264
+ sendAPDU: async (apduCommand) => {
265
+ const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, "hex")));
266
+ return Buffer.from(res).toString("hex");
267
+ },
268
+ poll,
269
+ pollApp
270
+ };
271
+ return device;
272
+ }
273
+
274
+ // src/trpc.ts
275
+ import { createTRPCClient, httpBatchLink } from "@trpc/client";
276
+ import superjson from "superjson";
277
+ var createClient = (options) => {
278
+ const trpc = createTRPCClient({
279
+ links: [
280
+ httpBatchLink({
281
+ url: `${options.baseUrl}/trpc`,
282
+ transformer: superjson,
283
+ headers() {
284
+ return {
285
+ ...options.debugAuthToken ? { "x-revault-debug-auth-token": options.debugAuthToken } : {},
286
+ ...options.rootAuthToken ? { "x-revault-root-auth-token": options.rootAuthToken } : {},
287
+ ...options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}
288
+ };
289
+ }
290
+ })
291
+ ]
292
+ });
293
+ return trpc;
294
+ };
295
+
296
+ // src/engine/index.ts
297
+ async function genericRegister({
298
+ device,
299
+ name,
300
+ role,
301
+ getChallenge,
302
+ submitChallenge
303
+ }) {
304
+ const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([
305
+ device.getAttestation(),
306
+ device.getU2FPubKey(),
307
+ device.getConfidentialityPubKey()
308
+ ]);
309
+ const ephemeralPubKey = await device.initPairingHandshake();
310
+ const deviceData = {
311
+ name,
312
+ pubKey: u2fPubKey.pubKey,
313
+ psdModel: "STAX",
314
+ confidentialityKey: confidentialityKey.pubKey,
315
+ psdEphemeralKey: ephemeralPubKey.pubKey,
316
+ psdEphemeralKeyAttestation: {
317
+ ...attestation.attestation,
318
+ signature: ephemeralPubKey.signature
319
+ }
320
+ };
321
+ const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });
322
+ const pairingPayload = await device.finalizePairingHandshake({
323
+ handshake: challenge.handshake,
324
+ ciphertext: challenge.ciphertext
325
+ });
326
+ const register = await device.register({
327
+ challenge: challenge.challenge,
328
+ u2fRegisterData: challenge.u2fRegisterData,
329
+ name,
330
+ role
331
+ });
332
+ const validationPubKey = await device.getValidationPubKey();
333
+ const registerData = await device.registerData({ challenge: challenge.challenge });
334
+ const attestationOffset = 67 + register.u2fRegister.readInt8(66);
335
+ const u2fRegister = Buffer.concat([
336
+ register.u2fRegister.slice(0, attestationOffset),
337
+ Buffer.from([attestation.buffer.length]),
338
+ attestation.buffer,
339
+ register.u2fRegister.slice(attestationOffset)
340
+ ]).toString("hex");
341
+ const challengeResponse = {
342
+ registerData,
343
+ certificate: {
344
+ ...attestation.attestation,
345
+ signature: validationPubKey.signature
346
+ },
347
+ u2fRegister,
348
+ u2fKeyHandle: register.keyHandle.toString("hex"),
349
+ validationKey: validationPubKey.pubKey,
350
+ pairingPayload
351
+ };
352
+ return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });
353
+ }
354
+ function createEngine(options, logger) {
355
+ const clientOptions = {
356
+ baseUrl: options.baseUrl
357
+ };
358
+ const client = createClient(clientOptions);
359
+ const apiDevice = createApiDevice(options, logger);
360
+ const base = {
361
+ client,
362
+ createClient: (overrides) => createClient({ ...clientOptions, ...overrides })
363
+ };
364
+ const withDeviceIndex = function(deviceIndex) {
365
+ const device = apiDevice.with(deviceIndex);
366
+ const withPsd = { device };
367
+ return decorateEngine({ ...this, ...withPsd });
368
+ };
369
+ const withTransportId = function(transportId) {
370
+ const device = createRealDevice({ transportId }, logger);
371
+ const withPsd = { device };
372
+ return decorateEngine({ ...this, ...withPsd });
373
+ };
374
+ const withApiUser = function() {
375
+ const withApiUser2 = { __isApiUser: true };
376
+ return decorateEngine({ ...this, ...withApiUser2 });
377
+ };
378
+ const withWorkspace = function(workspaceName) {
379
+ const withWorkspace2 = { __workspaceName: workspaceName };
380
+ return decorateEngine({ ...this, ...withWorkspace2 });
381
+ };
382
+ const withOnboarding = function(onboardingId) {
383
+ const withOnboarding2 = { __onboardingId: onboardingId };
384
+ return decorateEngine({ ...this, ...withOnboarding2 });
385
+ };
386
+ function decorateEngine(engine) {
387
+ function decorate(decorator) {
388
+ Object.assign(engine, decorator(engine));
389
+ }
390
+ if (engine.device) {
391
+ decorate(
392
+ (engine2) => ({
393
+ getWorkspaces: async () => {
394
+ const { device, client: client2 } = engine2;
395
+ const { pubKey } = await device.getU2FPubKey();
396
+ const { workspaceNames } = await client2.auth.psd.findWorkspaceNames.query({ pubKey });
397
+ return workspaceNames;
398
+ }
399
+ })
400
+ );
401
+ }
402
+ if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {
403
+ decorate((engine2) => {
404
+ const { __workspaceName } = engine2;
405
+ return {
406
+ withPsdToken: function(token) {
407
+ const withPsdAuth = { __psdToken: token };
408
+ const psdAuth = `${__workspaceName}:${token}`;
409
+ const client2 = engine2.createClient({ psdAuth });
410
+ return decorateEngine({ ...this, client: client2, ...withPsdAuth });
411
+ }
412
+ };
413
+ });
414
+ }
415
+ if (engine.device && engine.__onboardingId) {
416
+ decorate((engine2) => {
417
+ const { device, client: client2, __onboardingId } = engine2;
418
+ async function enforcePairing() {
419
+ if (await device.hasPairing()) return;
420
+ const [{ pubKey }, confidentialityKey] = await Promise.all([
421
+ device.getU2FPubKey(),
422
+ device.getConfidentialityKey()
423
+ ]);
424
+ const pairing = await client2.onboarding.pairDevicePartition.mutate({
425
+ pubKey,
426
+ onboardingId: __onboardingId,
427
+ data: {
428
+ confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
429
+ confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
430
+ }
431
+ });
432
+ await device.setPairing({ pairing });
433
+ }
434
+ return {
435
+ claimDevice: async (params) => {
436
+ const { role, deviceName } = params;
437
+ const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([
438
+ device.getU2FPubKey(),
439
+ device.getConfidentialityPubKey()
440
+ ]);
441
+ await client2.onboarding.claimDevice.mutate({
442
+ onboardingId: __onboardingId,
443
+ claim: { role, pubKey, deviceName, confidentialityKey }
444
+ });
445
+ },
446
+ collectWrappingKeyFragment: async (wrappingKey) => {
447
+ const [{ pubKey }, confidentialityKey] = await Promise.all([
448
+ device.getU2FPubKey(),
449
+ device.getConfidentialityPubKey()
450
+ ]);
451
+ await device.openSession({
452
+ secureChannel: {
453
+ pubKey: wrappingKey.ephemeralPubKey,
454
+ certificate: wrappingKey.ephemeralCertificate
455
+ }
456
+ });
457
+ const { attestation } = await device.getAttestation();
458
+ const blob = await device.generateWrappingKeyFragment();
459
+ await client2.onboarding.submitWrappingKeyFragment.mutate({
460
+ pubKey,
461
+ onboardingId: __onboardingId,
462
+ fragment: {
463
+ blob,
464
+ ephemeralPubKey: confidentialityKey.pubKey,
465
+ ephemeralCertificate: {
466
+ ...attestation,
467
+ signature: confidentialityKey.signature
468
+ }
469
+ }
470
+ });
471
+ },
472
+ registerDevice: async (params) => {
473
+ const { role, name } = params;
474
+ const getChallengeMutation = role === "ADMIN" ? client2.onboarding.generateMasterAdminRegistrationChallenge : client2.onboarding.generateSharedOwnerRegistrationChallenge;
475
+ const submitChallengeMutation = role === "ADMIN" ? client2.onboarding.submitMasterAdminRegistration : client2.onboarding.submitSharedOwnerRegistration;
476
+ await genericRegister({
477
+ device,
478
+ name,
479
+ role,
480
+ getChallenge: ({ pubKey, deviceData }) => getChallengeMutation.mutate({
481
+ onboardingId: __onboardingId,
482
+ pubKey,
483
+ deviceData
484
+ }),
485
+ submitChallenge: ({ pubKey, challengeResponse }) => submitChallengeMutation.mutate({
486
+ onboardingId: engine2.__onboardingId,
487
+ pubKey,
488
+ // FIXME this should be renamed to `challengeResponse` on backend side
489
+ response: challengeResponse
490
+ })
491
+ });
492
+ },
493
+ reviewSharedOwner: async (challenge) => {
494
+ await enforcePairing();
495
+ const { pubKey } = await device.getU2FPubKey();
496
+ await device.startKPatternAsResponder({
497
+ handshake: challenge.handshake,
498
+ handshakeAttestation: challenge.handshakeAttestation,
499
+ partitionId: challenge.partitionId
500
+ });
501
+ const signature = await device.validateVaultOperation({
502
+ actions: challenge.wActions
503
+ });
504
+ await client2.onboarding.submitReviewByMasterAdminSignature.mutate({
505
+ onboardingId: __onboardingId,
506
+ pubKey,
507
+ signature
508
+ });
509
+ },
510
+ collectSeedFragment: async (challenge) => {
511
+ await enforcePairing();
512
+ const [{ pubKey }, { attestation }] = await Promise.all([
513
+ device.getU2FPubKey(),
514
+ device.getAttestation()
515
+ ]);
516
+ await device.startKPatternAsResponder({
517
+ handshake: challenge.handshake,
518
+ handshakeAttestation: challenge.handshakeAttestation,
519
+ partitionId: challenge.partitionId
520
+ });
521
+ const challengeResponse = await device.validateVaultOperation({
522
+ actions: challenge.wActions
523
+ });
524
+ const kkPattern = await device.startKKPatternAsResponder({
525
+ partitionId: challenge.partitionId,
526
+ handshake: challenge.kkHandshake,
527
+ handshakeAttestation: challenge.kkHandshakeAttestation
528
+ });
529
+ const approverBlob = await device.generateSeedFragment();
530
+ await client2.onboarding.submitSeedFragment.mutate({
531
+ onboardingId: __onboardingId,
532
+ pubKey,
533
+ seedFragment: {
534
+ challengeResponse,
535
+ approverBlob,
536
+ handshake: kkPattern.handshake,
537
+ handshakeAttestation: {
538
+ ...attestation,
539
+ signature: kkPattern.signature
540
+ }
541
+ }
542
+ });
543
+ }
544
+ };
545
+ });
546
+ }
547
+ if (engine.device && engine.__workspaceName && !engine.__psdToken) {
548
+ decorate(
549
+ (engine2) => {
550
+ const { device, client: client2, __workspaceName } = engine2;
551
+ return {
552
+ login: async function(opts) {
553
+ const { pubKey } = await device.getU2FPubKey();
554
+ const challenge = await client2.auth.psd.generateChallenge.mutate({
555
+ pubKey,
556
+ workspaceName: __workspaceName
557
+ });
558
+ opts?.onScreenDisplayed?.();
559
+ const authentication = await device.authenticate({
560
+ challenge,
561
+ workspaceName: __workspaceName
562
+ });
563
+ const authPayload = {
564
+ workspaceName: __workspaceName,
565
+ pubKey,
566
+ authentication,
567
+ validityDurationSecs: opts?.validityDurationSecs
568
+ };
569
+ const { token } = await client2.auth.psd.authenticate.mutate({ ...authPayload });
570
+ const withPsdAuth = {
571
+ __psdToken: token
572
+ };
573
+ const psdAuth = `${engine2.__workspaceName}:${token}`;
574
+ const __authClient = engine2.createClient({ psdAuth });
575
+ return decorateEngine({ ...this, client: __authClient, ...withPsdAuth });
576
+ },
577
+ register: (params) => {
578
+ const { requestId, role, name } = params;
579
+ return genericRegister({
580
+ device,
581
+ name,
582
+ role,
583
+ getChallenge: async ({ deviceData }) => {
584
+ const req = await client2.requests.generateRegistrationChallenge.mutate({
585
+ id: params.requestId,
586
+ workspaceName: __workspaceName,
587
+ deviceData
588
+ });
589
+ const registration = req.data.registration;
590
+ invariant2(
591
+ registration.subState === "PENDING",
592
+ "Expected sub state to be PENDING"
593
+ );
594
+ return registration.challenge;
595
+ },
596
+ submitChallenge: ({ challengeResponse }) => client2.requests.confirmRegistrationChallenge.mutate({
597
+ workspaceName: __workspaceName,
598
+ id: requestId,
599
+ challengeResponse
600
+ })
601
+ });
602
+ }
603
+ };
604
+ }
605
+ );
606
+ }
607
+ if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {
608
+ decorate(
609
+ (engine2) => {
610
+ const { client: client2, __workspaceName } = engine2;
611
+ return {
612
+ login: async function(credentials) {
613
+ const res = await client2.auth.authenticate.mutate({
614
+ apiKeyId: credentials.apiKeyId,
615
+ apiKeySecret: credentials.apiKeySecret,
616
+ workspace: __workspaceName
617
+ });
618
+ const withApiAuth = {
619
+ __apiAuth: res
620
+ };
621
+ const __authClient = engine2.createClient({ apiAccessToken: res.accessToken });
622
+ return decorateEngine({ ...this, client: __authClient, ...withApiAuth });
623
+ }
624
+ };
625
+ }
626
+ );
627
+ }
628
+ if (engine.device && engine.__workspaceName && engine.__psdToken) {
629
+ decorate((engine2) => {
630
+ const { client: client2, device } = engine2;
631
+ async function enforcePairing() {
632
+ if (await device.hasPairing()) return;
633
+ const confidentialityKey = await device.getConfidentialityKey();
634
+ const pairing = await client2.debug.pairDevicePartition.mutate({
635
+ confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
636
+ confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
637
+ });
638
+ await device.setPairing({ pairing });
639
+ }
640
+ return {
641
+ approve: async (request, params) => {
642
+ const { challenge } = await client2.requests.getChallenge.query({ id: request.id });
643
+ invariant2(challenge.challengeType === "PSD", "Challenge type must be PSD");
644
+ await enforcePairing();
645
+ await device.startKPatternAsResponder({
646
+ handshake: challenge.handshake,
647
+ handshakeAttestation: challenge.handshakeAttestation,
648
+ partitionId: challenge.partitionId
649
+ });
650
+ params?.onScreenDisplayed?.();
651
+ const signature = await device.validateVaultOperation({
652
+ actions: challenge.wActions
653
+ });
654
+ return client2.requests.approve.mutate({
655
+ id: request.id,
656
+ data: { challengeType: "PSD", signature }
657
+ });
658
+ },
659
+ reject: (request) => {
660
+ return client2.requests.reject.mutate({ id: request.id, data: null });
661
+ }
662
+ };
663
+ });
664
+ }
665
+ if (engine.__workspaceName && engine.__apiAuth) {
666
+ decorate((engine2) => {
667
+ const { client: client2 } = engine2;
668
+ return {
669
+ getChallenge: async (request) => {
670
+ const { challenge } = await client2.requests.getChallenge.query({ id: request.id });
671
+ invariant2(challenge.challengeType === "API", "Challenge type must be API");
672
+ return challenge.payload;
673
+ },
674
+ approve: (request, signature) => {
675
+ return client2.requests.approve.mutate({
676
+ id: request.id,
677
+ data: { challengeType: "API", signature }
678
+ });
679
+ },
680
+ reject: (request, signature) => {
681
+ return client2.requests.reject.mutate({
682
+ id: request.id,
683
+ data: { challengeType: "API", signature }
684
+ });
685
+ }
686
+ };
687
+ });
688
+ }
689
+ return engine;
690
+ }
691
+ return {
692
+ ...base,
693
+ withDeviceIndex,
694
+ withTransportId,
695
+ withApiUser,
696
+ withWorkspace,
697
+ withOnboarding
698
+ };
699
+ }
700
+ export {
701
+ createEngine,
702
+ fetchAll
703
+ };
704
+ //# sourceMappingURL=engine.js.map