@ledgerhq/revault-sdk 0.28.11 → 0.28.14

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 (47) hide show
  1. package/lib/bake.cjs +3 -3
  2. package/lib/bake.cjs.map +1 -1
  3. package/lib/bake.d.cts +2 -2
  4. package/lib/bake.d.ts +2 -2
  5. package/lib/bake.js +3 -3
  6. package/lib/bake.js.map +1 -1
  7. package/lib/{crypto-BTN8FS8v.cjs → crypto-CKLQSwr3.cjs} +48 -12
  8. package/lib/crypto-CKLQSwr3.cjs.map +1 -0
  9. package/lib/{crypto-BcqzGi2f.js → crypto-hrnmToQa.js} +48 -11
  10. package/lib/crypto-hrnmToQa.js.map +1 -0
  11. package/lib/crypto.cjs +1 -1
  12. package/lib/crypto.js +1 -1
  13. package/lib/{device-DQyYUWPl.js → device-BnO26Hlr.js} +90 -34
  14. package/lib/device-BnO26Hlr.js.map +1 -0
  15. package/lib/{device-DQ32fSI-.cjs → device-CvgFoib2.cjs} +113 -33
  16. package/lib/device-CvgFoib2.cjs.map +1 -0
  17. package/lib/device.cjs +3 -1
  18. package/lib/device.d.cts +2 -2
  19. package/lib/device.d.ts +2 -2
  20. package/lib/device.js +2 -2
  21. package/lib/engine.cjs +93 -53
  22. package/lib/engine.cjs.map +1 -1
  23. package/lib/engine.d.cts +2 -2
  24. package/lib/engine.d.ts +2 -2
  25. package/lib/engine.js +94 -54
  26. package/lib/engine.js.map +1 -1
  27. package/lib/{index-xlQiIxlX.d.ts → index-16zV3onR.d.ts} +1 -1
  28. package/lib/{index-B3IUJM2r.d.cts → index-BAb2WCcL.d.cts} +25 -14
  29. package/lib/{index-Doiqe3tk.d.cts → index-CliA8Mh-.d.cts} +1 -1
  30. package/lib/{index-B1WQdM71.d.ts → index-DQgupTPR.d.ts} +25 -14
  31. package/lib/index.cjs +1 -1
  32. package/lib/index.cjs.map +1 -1
  33. package/lib/index.js +1 -1
  34. package/lib/index.js.map +1 -1
  35. package/lib/onboarding.cjs +6 -2
  36. package/lib/onboarding.cjs.map +1 -1
  37. package/lib/onboarding.d.cts +2 -2
  38. package/lib/onboarding.d.ts +2 -2
  39. package/lib/onboarding.js +6 -2
  40. package/lib/onboarding.js.map +1 -1
  41. package/lib/{types-DzZQZPXO.d.cts → types-bfqkmpgo.d.cts} +2 -1
  42. package/lib/{types-DqjcDy4H.d.ts → types-tRODcWIL.d.ts} +2 -1
  43. package/package.json +4 -5
  44. package/lib/crypto-BTN8FS8v.cjs.map +0 -1
  45. package/lib/crypto-BcqzGi2f.js.map +0 -1
  46. package/lib/device-DQ32fSI-.cjs.map +0 -1
  47. package/lib/device-DQyYUWPl.js.map +0 -1
@@ -2,6 +2,17 @@ import { t as Logger } from "./logger-DHtgWA66.js";
2
2
  import { HsmCertificate, PsdAuthChallengeResponse, PsdPairingData, PubKey, RefreshPskData } from "@ledgerhq/revault-api";
3
3
  import Transport from "@ledgerhq/hw-transport";
4
4
  import { Observable } from "rxjs";
5
+ //#region src/device/abort.d.ts
6
+ /** Error returned when the application aborts a device operation. */
7
+ declare class DeviceOperationAbortedError extends Error {
8
+ constructor();
9
+ }
10
+ type DeviceOperationOptions = {
11
+ /** Stops this operation when the application no longer owns the interaction. */
12
+ signal?: AbortSignal;
13
+ };
14
+ declare const isDeviceOperationAbortedError: (error: unknown) => error is DeviceOperationAbortedError;
15
+ //#endregion
5
16
  //#region src/device/types.d.ts
6
17
  /**
7
18
  * Tri-state result of {@link Device.hasPairing}. Replaces the legacy boolean so callers can
@@ -36,7 +47,7 @@ type Device = {
36
47
  /**
37
48
  * Get device attestation
38
49
  */
39
- getAttestation: () => Promise<{
50
+ getAttestation: (opts?: DeviceOperationOptions) => Promise<{
40
51
  attestation: {
41
52
  codeHash: string;
42
53
  attestationPub: string;
@@ -47,7 +58,7 @@ type Device = {
47
58
  /**
48
59
  * Get device confidentiality key
49
60
  */
50
- getConfidentialityKey: () => Promise<{
61
+ getConfidentialityKey: (opts?: DeviceOperationOptions) => Promise<{
51
62
  confidentialityKeyCurve25519: string;
52
63
  confidentialityKeySignature: string;
53
64
  }>;
@@ -85,11 +96,11 @@ type Device = {
85
96
  * sub-chain only (skip the full pairing flow).
86
97
  * - `"NO_PAIRING"` — no pairing at all; run the full pairing chain followed by a refresh.
87
98
  */
88
- hasPairing: () => Promise<PairingStatus>;
99
+ hasPairing: (opts?: DeviceOperationOptions) => Promise<PairingStatus>;
89
100
  /**
90
101
  * Initialize pairing handshake
91
102
  */
92
- initPairingHandshake: () => Promise<{
103
+ initPairingHandshake: (opts?: DeviceOperationOptions) => Promise<{
93
104
  pubKey: string;
94
105
  signature: string;
95
106
  }>;
@@ -127,7 +138,7 @@ type Device = {
127
138
  */
128
139
  setPairing: (opts: {
129
140
  pairing: PsdPairingData;
130
- }) => Promise<void>;
141
+ } & DeviceOperationOptions) => Promise<void>;
131
142
  /**
132
143
  * Sign the PSK-refresh authentication challenge (`SIGN_REFRESH_PSK_AUTH`, INS `0x55`).
133
144
  *
@@ -143,7 +154,7 @@ type Device = {
143
154
  */
144
155
  signRefreshPskAuth: (opts: {
145
156
  ephemeralKey: string;
146
- }) => Promise<string>;
157
+ } & DeviceOperationOptions) => Promise<string>;
147
158
  /**
148
159
  * Finalize a PSK refresh (`FINALIZE_PSK_REFRESH`, INS `0x53`).
149
160
  *
@@ -151,7 +162,7 @@ type Device = {
151
162
  * stores the re-delivered (static) PSK in NVM. Throws when the device already holds a different
152
163
  * PSK for the partition (`SW_PSK_MISMATCH`, `0x6067`).
153
164
  */
154
- finalizePskRefresh: (opts: RefreshPskData) => Promise<void>;
165
+ finalizePskRefresh: (opts: RefreshPskData & DeviceOperationOptions) => Promise<void>;
155
166
  /**
156
167
  * Start KK pattern (related to noise channel)
157
168
  */
@@ -170,20 +181,20 @@ type Device = {
170
181
  handshake: string;
171
182
  handshakeAttestation: HsmCertificate;
172
183
  partitionId: string;
173
- }) => Promise<void>;
184
+ } & DeviceOperationOptions) => Promise<void>;
174
185
  /**
175
186
  * Start a PSK session (Secure channel)
176
187
  */
177
188
  startPskSession(opts: {
178
189
  nonce: string;
179
190
  partitionId: string;
180
- }): Promise<void>;
191
+ } & DeviceOperationOptions): Promise<void>;
181
192
  /**
182
193
  * Approve with device
183
194
  */
184
195
  validateVaultOperation: (opts: {
185
196
  actions: string[];
186
- }) => Promise<string>;
197
+ } & DeviceOperationOptions) => Promise<string>;
187
198
  /**
188
199
  * Send arbitrary APDU
189
200
  * apduCommand in HEX string format
@@ -193,21 +204,21 @@ type Device = {
193
204
  * Get app version
194
205
  *
195
206
  */
196
- getVersion: () => Promise<string>;
207
+ getVersion: (opts?: DeviceOperationOptions) => Promise<string>;
197
208
  /**
198
209
  * Poll device until it's plugged-on
199
210
  *
200
211
  */
201
212
  poll: (opts?: {
202
213
  retryOnError?: (err: Error) => boolean;
203
- }) => Promise<{
214
+ } & DeviceOperationOptions) => Promise<{
204
215
  isAppOpened: boolean;
205
216
  }>;
206
217
  /**
207
218
  * Returned when app is opened
208
219
  * appName in string format
209
220
  */
210
- pollApp: (name: string) => Promise<string>;
221
+ pollApp: (name: string, opts?: DeviceOperationOptions) => Promise<string>;
211
222
  };
212
223
  //#endregion
213
224
  //#region src/device/api-device.d.ts
@@ -278,4 +289,4 @@ declare const isLockedDeviceError: (error: unknown) => boolean;
278
289
  declare const isPskMissingError: (error: unknown) => boolean;
279
290
  declare const isPskMismatchError: (error: unknown) => boolean;
280
291
  //#endregion
281
- export { isPskMissingError as a, ApiDevice as c, PairingStatus as d, isPskMismatchError as i, createApiDevice as l, isDeviceCancelError as n, isTransportStatusError as o, isLockedDeviceError as r, registerTransportModule as s, isCantOpenDeviceError as t, Device as u };
292
+ export { isPskMissingError as a, ApiDevice as c, PairingStatus as d, DeviceOperationAbortedError as f, isPskMismatchError as i, createApiDevice as l, isDeviceOperationAbortedError as m, isDeviceCancelError as n, isTransportStatusError as o, DeviceOperationOptions as p, isLockedDeviceError as r, registerTransportModule as s, isCantOpenDeviceError as t, Device as u };
package/lib/index.cjs CHANGED
@@ -16,9 +16,9 @@ async function waitForRequestChallengesReady(client, request) {
16
16
  (0, invariant.default)(request.inflight !== void 0, "Request in INITIAL state should be inflight");
17
17
  const deadline = Date.now() + POLL_TIMEOUT_MS;
18
18
  while (Date.now() < deadline) {
19
- await wait(POLL_INTERVAL_MS);
20
19
  const updated = await client.requests.findById.query({ id: request.id });
21
20
  if (updated.state !== "INITIAL") return updated;
21
+ await wait(POLL_INTERVAL_MS);
22
22
  }
23
23
  throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);
24
24
  }
package/lib/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n await wait(POLL_INTERVAL_MS);\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;;;;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,CAAA,GAAA,UAAA,QAAA,CAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,KAAK,gBAAgB;EAC3B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;CAEX;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n await wait(POLL_INTERVAL_MS);\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;;;;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,CAAA,GAAA,UAAA,QAAA,CAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;EAET,MAAM,KAAK,gBAAgB;CAC7B;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
package/lib/index.js CHANGED
@@ -13,9 +13,9 @@ async function waitForRequestChallengesReady(client, request) {
13
13
  invariant(request.inflight !== void 0, "Request in INITIAL state should be inflight");
14
14
  const deadline = Date.now() + POLL_TIMEOUT_MS;
15
15
  while (Date.now() < deadline) {
16
- await wait(POLL_INTERVAL_MS);
17
16
  const updated = await client.requests.findById.query({ id: request.id });
18
17
  if (updated.state !== "INITIAL") return updated;
18
+ await wait(POLL_INTERVAL_MS);
19
19
  }
20
20
  throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);
21
21
  }
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n await wait(POLL_INTERVAL_MS);\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,UAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,KAAK,gBAAgB;EAC3B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;CAEX;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/escape-hatch.ts"],"sourcesContent":["import type { VaultRequestResponse } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport type { RevaultApiTRPCClient } from \"./trpc\";\n\nconst POLL_INTERVAL_MS = 250;\nconst POLL_TIMEOUT_MS = 60_000;\n\nconst wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Busy-polls until a request leaves the INITIAL state (i.e. challenges are generated).\n *\n * **Escape hatch** — prefer server-sent events or webhooks where available.\n */\nexport async function waitForRequestChallengesReady(\n client: RevaultApiTRPCClient,\n request: VaultRequestResponse,\n): Promise<VaultRequestResponse> {\n if (request.state !== \"INITIAL\") {\n return request;\n }\n\n invariant(request.inflight !== undefined, \"Request in INITIAL state should be inflight\");\n\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n\n while (Date.now() < deadline) {\n const updated = await client.requests.findById.query({ id: request.id });\n if (updated.state !== \"INITIAL\") {\n return updated;\n }\n await wait(POLL_INTERVAL_MS);\n }\n\n throw new Error(`Timed out waiting for request ${request.id} challenges to be ready`);\n}\n"],"mappings":";;AAKA,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,MAAM,QAAQ,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;;;;;;AAO5F,eAAsB,8BACpB,QACA,SAC+B;CAC/B,IAAI,QAAQ,UAAU,WACpB,OAAO;CAGT,UAAU,QAAQ,aAAa,KAAA,GAAW,6CAA6C;CAEvF,MAAM,WAAW,KAAK,IAAI,IAAI;CAE9B,OAAO,KAAK,IAAI,IAAI,UAAU;EAC5B,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS,MAAM,EAAE,IAAI,QAAQ,GAAG,CAAC;EACvE,IAAI,QAAQ,UAAU,WACpB,OAAO;EAET,MAAM,KAAK,gBAAgB;CAC7B;CAEA,MAAM,IAAI,MAAM,iCAAiC,QAAQ,GAAG,wBAAwB;AACtF"}
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-y5ARvAq5.cjs");
3
- const require_crypto = require("./crypto-BTN8FS8v.cjs");
3
+ const require_crypto = require("./crypto-CKLQSwr3.cjs");
4
4
  let invariant = require("invariant");
5
5
  invariant = require_rolldown_runtime.__toESM(invariant, 1);
6
6
  let ts_pattern = require("ts-pattern");
@@ -226,7 +226,11 @@ const STEPS = {
226
226
  /**
227
227
  * Workspace initialization
228
228
  */
229
- PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
229
+ PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {
230
+ const result = await engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id });
231
+ logger.info("Workspace initialized");
232
+ return result;
233
+ }
230
234
  };
231
235
  async function onboard(opts, logger) {
232
236
  const { engine, debugAuthToken, signerSeed, untilStep } = opts;
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.cjs","names":["match","getMasterSeed"],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>\n engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id }),\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"onboarding.cjs","names":["match","getMasterSeed"],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {\n const result = await engine.client.onboarding.initializeWorkspace.mutate({\n onboardingId: state.id,\n });\n logger.info(\"Workspace initialized\");\n return result;\n },\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { t as Logger } from "./logger-DHtgWA66.cjs";
2
- import { d as Engine, y as WithOnboarding } from "./types-DzZQZPXO.cjs";
2
+ import { d as Engine, y as WithOnboarding } from "./types-bfqkmpgo.cjs";
3
3
  import { OnboardingFullStateResponse, OnboardingStep } from "@ledgerhq/revault-api";
4
4
  //#region src/onboarding.d.ts
5
5
  declare const STEPS: {
@@ -1097,7 +1097,7 @@ declare const STEPS: {
1097
1097
  state: OnboardingFullStateResponse;
1098
1098
  debugAuthToken?: string;
1099
1099
  signerSeed?: string;
1100
- }) => Promise<{
1100
+ }, logger: Logger) => Promise<{
1101
1101
  id: string;
1102
1102
  workspaceName: string;
1103
1103
  hsmHostingMode: "HOSTED" | "ON_PREM";
@@ -1,5 +1,5 @@
1
1
  import { t as Logger } from "./logger-DHtgWA66.js";
2
- import { d as Engine, y as WithOnboarding } from "./types-DqjcDy4H.js";
2
+ import { d as Engine, y as WithOnboarding } from "./types-tRODcWIL.js";
3
3
  import { OnboardingFullStateResponse, OnboardingStep } from "@ledgerhq/revault-api";
4
4
  //#region src/onboarding.d.ts
5
5
  declare const STEPS: {
@@ -1097,7 +1097,7 @@ declare const STEPS: {
1097
1097
  state: OnboardingFullStateResponse;
1098
1098
  debugAuthToken?: string;
1099
1099
  signerSeed?: string;
1100
- }) => Promise<{
1100
+ }, logger: Logger) => Promise<{
1101
1101
  id: string;
1102
1102
  workspaceName: string;
1103
1103
  hsmHostingMode: "HOSTED" | "ON_PREM";
package/lib/onboarding.js CHANGED
@@ -1,4 +1,4 @@
1
- import { i as getMasterSeed } from "./crypto-BcqzGi2f.js";
1
+ import { i as getMasterSeed } from "./crypto-hrnmToQa.js";
2
2
  import invariant from "invariant";
3
3
  import { match } from "ts-pattern";
4
4
  //#region src/onboarding.ts
@@ -223,7 +223,11 @@ const STEPS = {
223
223
  /**
224
224
  * Workspace initialization
225
225
  */
226
- PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
226
+ PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {
227
+ const result = await engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id });
228
+ logger.info("Workspace initialized");
229
+ return result;
230
+ }
227
231
  };
228
232
  async function onboard(opts, logger) {
229
233
  const { engine, debugAuthToken, signerSeed, untilStep } = opts;
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.js","names":[],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) =>\n engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id }),\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"onboarding.js","names":[],"sources":["../src/onboarding.ts"],"sourcesContent":["import type {\n ClaimedRole,\n HsmHostingMode,\n OnboardingFullStateResponse,\n OnboardingStep,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { getMasterSeed } from \"@/crypto\";\nimport type { Logger } from \"@/logger\";\n\nimport type { Engine, WithOnboarding } from \"./engine/types\";\n\ntype StepAction = (\n options: {\n engine: Engine<WithOnboarding>;\n state: OnboardingFullStateResponse;\n debugAuthToken?: string;\n signerSeed?: string;\n },\n logger: Logger,\n) => Promise<OnboardingFullStateResponse>;\n\nconst roleLabels: Record<ClaimedRole, string> = {\n WRAPPING_KEY_OWNER: \"Wrapping Key\",\n MASTER_ADMIN: \"Admin\",\n SHARED_OWNER: \"Shared Owner\",\n};\n\nconst devices: { index: number; role: ClaimedRole; name: string }[] = [\n { index: 1, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 1` },\n { index: 2, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 2` },\n { index: 3, role: \"WRAPPING_KEY_OWNER\", name: `${roleLabels.WRAPPING_KEY_OWNER} 3` },\n { index: 4, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 1` },\n { index: 5, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 2` },\n { index: 6, role: \"MASTER_ADMIN\", name: `${roleLabels.MASTER_ADMIN} 3` },\n { index: 7, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 1` },\n { index: 8, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 2` },\n { index: 9, role: \"SHARED_OWNER\", name: `${roleLabels.SHARED_OWNER} 3` },\n];\n\nconst deviceNameToIndex = (name: string): number => {\n const index = devices.find((d) => d.name === name)?.index;\n invariant(index !== undefined, `Unknown device ${name}`);\n return index;\n};\n\nconst checkHsmHostingMode = (\n state: OnboardingFullStateResponse,\n expectedMode: HsmHostingMode,\n): void => {\n /* v8 ignore next -- @preserve */\n if (state.hsmHostingMode !== expectedMode) {\n throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);\n }\n};\n\n/* v8 ignore next -- @preserve */\nconst checkExternalSigners = (\n state: OnboardingFullStateResponse,\n debugAuthToken: string | undefined,\n): void => {\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () => null)\n .with(\"ON_PREM\", () => (debugAuthToken ? null : \"On-premises HSM requires a debug auth token\"))\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nexport const STEPS = {\n /**\n * Devices claiming\n */\n PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {\n const promises: Promise<void>[] = [];\n for (const device of devices) {\n if (state.hsmHostingMode === \"ON_PREM\" && device.role === \"SHARED_OWNER\") {\n continue;\n }\n if (state.skipWrappingKey && device.role === \"WRAPPING_KEY_OWNER\") {\n continue;\n }\n /* v8 ignore else -- @preserve */\n if (\n state.claimedDevices.find(\n /* v8 ignore next -- @preserve */\n (c) => c.deviceName === device.name,\n ) === undefined\n ) {\n const promise = engine\n .withDeviceIndex(device.index)\n .claimDevice({ role: device.role, deviceName: device.name })\n .then(() => logger.info(`Claimed ${device.name}`));\n promises.push(promise);\n }\n }\n await Promise.all(promises);\n return engine.client.onboarding.commitDeviceClaims.mutate({ onboardingId: state.id });\n },\n\n /**\n * Wrapping Key provisioning\n */\n PENDING_WRAPPING_KEY_PROVISIONING: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startWrappingKeyProvisioning.mutate({ onboardingId });\n const wrappingKey = state.wrappingKey!;\n const toCollect = state.claimedDevices\n .filter((claimed) => {\n if (claimed.role !== \"WRAPPING_KEY_OWNER\") return false;\n const inFragment = !!state.wrappingKey?.fragments.find(\n /* v8 ignore next -- @preserve */\n (f) => f.pubKey === claimed.pubKey,\n );\n return !inFragment;\n })\n .map((c) => {\n const index = deviceNameToIndex(c.deviceName);\n return index;\n });\n await Promise.all(\n toCollect.map((index) =>\n engine\n .withDeviceIndex(index)\n .collectWrappingKeyFragment(wrappingKey)\n .then(() => logger.info(`Collected Wrapping Key ${index}`)),\n ),\n );\n return engine.client.onboarding.commitWrappingKey.mutate({ onboardingId });\n },\n\n /**\n * Init Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION_INIT: async ({ engine, state }) =>\n engine.client.onboarding.startMasterAdminsRegistration.mutate({ onboardingId: state.id }),\n\n /**\n * Master Admins registration\n */\n PENDING_MASTER_ADMINS_REGISTRATION: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"MASTER_ADMIN\") return false;\n const hasRegistered = !!state.masterAdmins.find(\n /* v8 ignore next -- @preserve */\n (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"ADMIN\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.createMasterAdminGroup.mutate({ onboardingId });\n },\n\n /**\n * Init Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION_INIT: async ({ engine, state }) => {\n checkHsmHostingMode(state, \"HOSTED\");\n return engine.client.onboarding.startSharedOwnersRegistration.mutate({\n onboardingId: state.id,\n });\n },\n\n /**\n * Shared Owners registration\n */\n PENDING_SHARED_OWNERS_REGISTRATION: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n const toRegister = state.claimedDevices.filter((claimed) => {\n if (claimed.role !== \"SHARED_OWNER\") return false;\n const hasRegistered = !!state.sharedOwners.find(\n /* v8 ignore next -- @preserve */ (a) => a.pubKey === claimed.pubKey,\n );\n return !hasRegistered;\n });\n await Promise.all(\n toRegister.map(async ({ deviceName: name }) => {\n const index = deviceNameToIndex(name);\n await engine.withDeviceIndex(index).registerDevice({ role: \"SHARED_OWNER\", name });\n logger.info(`Registered ${name}`);\n }),\n );\n return engine.client.onboarding.commitSharedOwnersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Review by master admins\n */\n PENDING_REVIEW_BY_MASTER_ADMINS: async ({ state, engine }, logger) => {\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startReviewByMasterAdmins.mutate({ onboardingId });\n const toCollect = state.masterAdmins.filter((admin) => !admin.review?.signature);\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.review?.challenge;\n await engine.withDeviceIndex(index).reviewSharedOwner(challenge!);\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });\n },\n\n PENDING_EXTERNAL_SIGNERS_REGISTRATION: async (\n { state, engine, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n if (debugAuthToken) {\n const debugClient = engine.createClient({ debugAuthToken });\n const seed =\n signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString(\"base64\");\n await debugClient.debug.insertExternalSignerSeed.mutate({\n workspaceName: state.workspaceName,\n seed,\n });\n logger.info(\"Inserted external signer seed\");\n }\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n });\n const toCollect = state.masterAdmins.filter(\n (admin) => !admin.reviewOfExternalSigners?.signature,\n );\n await Promise.all(\n toCollect.map(async (admin) => {\n const index = deviceNameToIndex(admin.name);\n const challenge = admin.reviewOfExternalSigners?.challenge;\n await engine.withDeviceIndex(index).reviewExternalSigners(challenge!); // same as review for shared owner, but with different challenge\n logger.info(`Approved with ${admin.name}`);\n }),\n );\n return engine.client.onboarding.commitExternalSignersRegistration.mutate({ onboardingId });\n },\n\n /**\n * Seed provisioning\n */\n PENDING_SEED_PROVISIONING: async ({ state, engine }, logger) => {\n checkHsmHostingMode(state, \"HOSTED\");\n const { id: onboardingId } = state;\n state = await engine.client.onboarding.startSeedProvisioning.mutate({ onboardingId });\n const toCollect = state.sharedOwners.filter((so) => !so.review?.seedFragment);\n await Promise.all(\n toCollect.map(async (so) => {\n const index = deviceNameToIndex(so.name);\n const challenge = so.review?.seedChallenge;\n await engine.withDeviceIndex(index).collectSeedFragment(challenge!);\n logger.info(`Collected fragment for ${so.name}`);\n }),\n );\n return engine.client.onboarding.commitSeedProvisioning.mutate({ onboardingId });\n },\n\n /**\n * Workspace initialization\n */\n PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }, logger) => {\n const result = await engine.client.onboarding.initializeWorkspace.mutate({\n onboardingId: state.id,\n });\n logger.info(\"Workspace initialized\");\n return result;\n },\n} as const satisfies Record<Exclude<OnboardingStep, \"COMPLETED\">, StepAction>;\n\nexport async function onboard(\n opts: {\n engine: Engine<WithOnboarding>;\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, debugAuthToken, signerSeed, untilStep } = opts;\n\n const { __onboardingId } = engine;\n logger.info(`Joining onboarding ${__onboardingId}`);\n let state = await engine.client.onboarding.getOnboarding.query({\n onboardingId: __onboardingId,\n });\n\n checkExternalSigners(state, debugAuthToken);\n\n while (state.step !== \"COMPLETED\") {\n if (untilStep && state.step === untilStep) {\n logger.info(\"Skipping the rest of the onboarding\");\n break;\n }\n const step = STEPS[state.step];\n logger.info(step.name);\n state = await step({ engine, state, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { u as Device } from "./index-B3IUJM2r.cjs";
1
+ import { u as Device } from "./index-BAb2WCcL.cjs";
2
2
  import { i as TRPCClientOptions, r as RouterOutputs, t as RevaultApiTRPCClient } from "./trpc-BCwyqVKi.cjs";
3
3
  import { ApiChallenge, ClaimedRole, OnboardingSeedChallenge, PsdChallenge, UserRegistrationResponse, VaultRequestResponse, WrappingKeyResponse } from "@ledgerhq/revault-api";
4
4
  //#region src/engine/types.d.ts
@@ -142,6 +142,7 @@ type CorrelationIdOpts = {
142
142
  type ApproveRequestParams = {
143
143
  onScreenDisplayed?: () => void | Promise<void>;
144
144
  onPsdChallengeSigned?: () => void | Promise<void>;
145
+ signal?: AbortSignal;
145
146
  } & CorrelationIdOpts;
146
147
  type DecorateWithWorkspacePsdAuthenticated = {
147
148
  /**
@@ -1,4 +1,4 @@
1
- import { u as Device } from "./index-B1WQdM71.js";
1
+ import { u as Device } from "./index-DQgupTPR.js";
2
2
  import { i as TRPCClientOptions, r as RouterOutputs, t as RevaultApiTRPCClient } from "./trpc-BCwyqVKi.js";
3
3
  import { ApiChallenge, ClaimedRole, OnboardingSeedChallenge, PsdChallenge, UserRegistrationResponse, VaultRequestResponse, WrappingKeyResponse } from "@ledgerhq/revault-api";
4
4
  //#region src/engine/types.d.ts
@@ -142,6 +142,7 @@ type CorrelationIdOpts = {
142
142
  type ApproveRequestParams = {
143
143
  onScreenDisplayed?: () => void | Promise<void>;
144
144
  onPsdChallengeSigned?: () => void | Promise<void>;
145
+ signal?: AbortSignal;
145
146
  } & CorrelationIdOpts;
146
147
  type DecorateWithWorkspacePsdAuthenticated = {
147
148
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/revault-sdk",
3
- "version": "0.28.11",
3
+ "version": "0.28.14",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -46,7 +46,8 @@
46
46
  "dependencies": {
47
47
  "@ledgerhq/errors": "^6.36.0",
48
48
  "@ledgerhq/hw-transport": "^6.35.4",
49
- "@noble/hashes": "^2.0.1",
49
+ "@noble/curves": "^2.3.0",
50
+ "@noble/hashes": "^2.3.0",
50
51
  "@scure/bip32": "^2.0.1",
51
52
  "@scure/bip39": "^2.0.1",
52
53
  "@trpc/client": "11.17.0",
@@ -55,7 +56,6 @@
55
56
  "axios": "^1.19.0",
56
57
  "axios-retry": "^4.5.0",
57
58
  "bn.js": "^5.2.3",
58
- "elliptic": "^6.6.1",
59
59
  "invariant": "^2.2.4",
60
60
  "jose": "^6.2.8",
61
61
  "lodash": "^4.18.1",
@@ -64,13 +64,12 @@
64
64
  "ts-pattern": "^5.9.0",
65
65
  "uuid": "^14.0.0",
66
66
  "zod": "^4.4.3",
67
- "@ledgerhq/revault-api": "1.82.2"
67
+ "@ledgerhq/revault-api": "1.83.1"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@eslint/js": "^9.39.4",
71
71
  "@microsoft/api-extractor": "^7.47.0",
72
72
  "@types/bn.js": "^5.2.0",
73
- "@types/elliptic": "^6.4.18",
74
73
  "@types/invariant": "^2.2.37",
75
74
  "@types/lodash": "^4.17.24",
76
75
  "@types/node": "^25.9.3",
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-BTN8FS8v.cjs","names":["sha256","entropyToMnemonic","wordlist","mnemonicToSeed","HDKey","asn1","BN","crypto"],"sources":["../src/crypto/gen-seed.ts","../src/crypto/key-encoder.ts","../src/crypto/utils.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport { entropyToMnemonic, mnemonicToSeed } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\n\n/**\n * Generate a deterministic BIP39 mnemonic from a salt and device index.\n *\n * Produces `entropyToMnemonic(SHA256(salt + \"_\" + index))`, matching\n * the behavior of `@ledgerhq/vault-common`'s `genSeed`.\n *\n * @param salt The workspace salt\n * @param index The device index (1-based)\n * @returns A 24-word BIP39 mnemonic string\n */\nexport function genSeed(salt: string, index: number): string {\n const input = new TextEncoder().encode(`${salt}_${index}`);\n const entropy = sha256(input);\n return entropyToMnemonic(entropy, wordlist);\n}\n\nconst getSeedFragment = async (salt: string, index: number): Promise<Uint8Array> => {\n const seed = await mnemonicToSeed(genSeed(salt, index));\n const secpKey = HDKey.fromMasterSeed(seed);\n const fragment = secpKey.derive(\"m/5655636'/4932953'\");\n return Buffer.concat([fragment.privateKey!, fragment.chainCode!]);\n};\n\nexport const getMasterSeed = async (salt: string): Promise<Uint8Array> => {\n const fragments = await Promise.all([\n getSeedFragment(salt, 7),\n getSeedFragment(salt, 8),\n getSeedFragment(salt, 9),\n ]);\n\n const masterSeed = new Uint8Array(fragments[0].length);\n for (let i = 0; i < fragments[0].length; i++) {\n masterSeed[i] = fragments[0][i]! ^ fragments[1][i]! ^ fragments[2][i]!;\n }\n\n return masterSeed;\n};\n","// ========================================================================== //\n// //\n// DISCLAIMER //\n// //\n// This code has been blindly copy-pasted from: //\n// https://github.com/LedgerHQ/pkey-ts //\n// //\n// ========================================================================== //\n//\n// @ts-expect-error this library does not ship types\nimport asn1 from \"asn1.js\";\nimport BN from \"bn.js\";\nimport elliptic from \"elliptic\";\n\n/* cspell:disable */\nconst ECPrivateKeyASN = asn1.define(\"ECPrivateKey\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self.key(\"privateKey\").octstr(),\n self.key(\"parameters\").explicit(0).objid().optional(),\n self.key(\"publicKey\").explicit(1).bitstr().optional(),\n );\n});\n\nconst ECPrivateKey8ASN = asn1.define(\n \"ECPrivateKey\",\n /* v8 ignore next -- @preserve */\n function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self\n .key(\"privateKeyAlgorithm\")\n .seq()\n .obj(self.key(\"ecPublicKey\").objid(), self.key(\"curve\").objid()),\n self.key(\"privateKey\").octstr().contains(ECPrivateKeyASN),\n self.key(\"attributes\").explicit(0).bitstr().optional(),\n );\n },\n);\n\nconst SubjectPublicKeyInfoASN = asn1.define(\"SubjectPublicKeyInfo\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"algorithm\").seq().obj(self.key(\"id\").objid(), self.key(\"curve\").objid()),\n self.key(\"pub\").bitstr(),\n );\n});\n\ntype CurveOptions = {\n curveParameters: number[];\n privatePEMOptions: { label: string };\n publicPEMOptions: { label: string };\n curve: elliptic.ec;\n};\n\nconst curves: Record<string, CurveOptions> = {\n secp256k1: {\n curveParameters: [1, 3, 132, 0, 10],\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"secp256k1\"),\n },\n p256: {\n curveParameters: [1, 2, 840, 10045, 3, 1, 7], // OID for p256 curve\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"p256\"),\n },\n};\n\ntype PrivateKeyPKCS1 = {\n version: BN;\n privateKey: Buffer;\n parameters: number[];\n publicKey?: {\n unused: number;\n data: Buffer;\n };\n};\n\ntype PrivateKeyPKCS8 = {\n version: BN;\n privateKey: PrivateKeyPKCS1;\n privateKeyAlgorithm: { ecPublicKey: number[]; curve: number[] };\n};\n\nexport type KeyFormat = \"raw\" | \"pem\" | \"der\";\n\nexport class KeyEncoder {\n algorithmID: number[];\n options: CurveOptions;\n\n constructor(options: string | CurveOptions) {\n /* v8 ignore else -- @preserve */\n if (typeof options === \"string\") {\n /* v8 ignore if -- @preserve */\n if (options !== \"secp256k1\" && options !== \"p256\") {\n throw new Error(`Unknown curve ${options}`);\n }\n options = curves[options]!;\n }\n this.options = options;\n this.algorithmID = [1, 2, 840, 10045, 2, 1];\n }\n\n /* v8 ignore next -- @preserve */\n private PKCS1toPKCS8(privateKey: PrivateKeyPKCS1): PrivateKeyPKCS8 {\n return {\n version: new BN(0),\n privateKey,\n privateKeyAlgorithm: {\n ecPublicKey: this.algorithmID,\n curve: privateKey.parameters,\n },\n };\n }\n\n privateKeyObject(rawPrivateKey: string, rawPublicKey: string): PrivateKeyPKCS1 {\n const privateKeyObject: PrivateKeyPKCS1 = {\n version: new BN(1),\n privateKey: Buffer.from(rawPrivateKey, \"hex\"),\n parameters: this.options.curveParameters,\n };\n\n /* v8 ignore else -- @preserve */\n if (rawPublicKey) {\n privateKeyObject.publicKey = {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n };\n }\n\n return privateKeyObject;\n }\n\n publicKeyObject(rawPublicKey: string): {\n algorithm: { id: number[]; curve: number[] };\n pub: { unused: number; data: Buffer };\n } {\n return {\n algorithm: {\n id: this.algorithmID,\n curve: this.options.curveParameters,\n },\n pub: {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n },\n };\n }\n\n encodePrivate(\n privateKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n destinationFormatType: \"pkcs8\" | \"pkcs1\" = \"pkcs1\",\n ): string {\n let privateKeyObject: PrivateKeyPKCS1;\n\n /* Parse the incoming private key and convert it to a private key object */\n switch (originalFormat) {\n case \"raw\": {\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n const keyPair = this.options.curve.keyFromPrivate(privateKey, \"hex\");\n const rawPublicKey = keyPair.getPublic(\"hex\");\n privateKeyObject = this.privateKeyObject(privateKey, rawPublicKey);\n break;\n }\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof privateKey === \"string\") {\n privateKey = Buffer.from(privateKey, \"hex\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(privateKey, \"der\");\n break;\n case \"pem\":\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(\n privateKey,\n \"pem\",\n this.options.privatePEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid private key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n if (destinationFormatType === \"pkcs1\") {\n return privateKeyObject.privateKey.toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return this.PKCS1toPKCS8(privateKeyObject).privateKey.privateKey.toString(\"hex\");\n }\n break;\n case \"der\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"der\").toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"der\").toString(\n \"hex\",\n );\n }\n break;\n case \"pem\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"pem\", this.options.privatePEMOptions);\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"pem\", {\n ...this.options.privatePEMOptions,\n label: \"PRIVATE KEY\",\n });\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for private key\");\n }\n\n throw new Error(\"unsupported destination format or type\");\n }\n\n encodePublic(\n publicKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n ): string {\n // biome-ignore lint/suspicious/noImplicitAnyLet: melting pot object\n let publicKeyObject;\n\n switch (originalFormat) {\n case \"raw\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = this.publicKeyObject(publicKey);\n break;\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof publicKey === \"string\") {\n publicKey = Buffer.from(publicKey, \"hex\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(publicKey, \"der\");\n break;\n case \"pem\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(\n publicKey,\n \"pem\",\n this.options.publicPEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid public key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n return publicKeyObject.pub.data.toString(\"hex\");\n case \"der\":\n return SubjectPublicKeyInfoASN.encode(publicKeyObject, \"der\").toString(\"hex\");\n case \"pem\":\n return SubjectPublicKeyInfoASN.encode(\n publicKeyObject,\n \"pem\",\n this.options.publicPEMOptions,\n );\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for public key\");\n }\n }\n}\n/* cspell:enable */\n","import elliptic from \"elliptic\";\nimport * as jose from \"jose\";\n\nimport { KeyEncoder } from \"./key-encoder\";\nimport type { GeneratedKeys } from \"./types\";\nimport crypto from \"node:crypto\";\n\nfunction extractPublicKey(pemKey: string): string {\n // convert the PEM formatted public key to raw public key in X9.62 uncompressed format\n // this is an oversimplified method and may not work with different curves or PEM formats\n const pem = pemKey.split(\"\\n\");\n pem.shift(); // remove the first line (BEGIN PUBLIC KEY)\n pem.pop(); // remove the last line (END PUBLIC KEY)\n // convert base64 to buffer\n const keyBuffer = Buffer.from(pem.join(\"\"), \"base64\");\n // assuming the first 26 bytes are the header for the SPKI formatted key.\n // the actual key should begin after this header.\n const actualKeyBuffer = keyBuffer.slice(26);\n return actualKeyBuffer.toString(\"hex\").toUpperCase();\n}\n\nfunction hexToPem(hexString: string, { isPrivate = true } = {}): string {\n const keyEncoder = new KeyEncoder(\"p256\");\n if (isPrivate) {\n return keyEncoder.encodePrivate(hexString, \"raw\", \"pem\");\n }\n return keyEncoder.encodePublic(hexString, \"raw\", \"pem\");\n}\n\n/**\n * If `entropy` is passed, will generate keys pair deterministically\n * else, random keys pair generated\n */\nexport function genKeys(entropy?: string): GeneratedKeys {\n if (entropy) {\n const ec = new elliptic.ec(\"p256\");\n const hashedEntropy = crypto.createHash(\"sha256\").update(entropy).digest(\"hex\");\n const keyPair = ec.genKeyPair({\n entropy: Buffer.from(hashedEntropy, \"hex\"),\n });\n return {\n privateKey: String(hexToPem(keyPair.getPrivate(\"hex\"))),\n publicKey: String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false })),\n hexPubKey: extractPublicKey(String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false }))),\n };\n }\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ec\", {\n namedCurve: \"P-256\",\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n privateKeyEncoding: { type: \"sec1\", format: \"pem\" },\n });\n const hexPubKey = extractPublicKey(publicKey);\n return {\n privateKey,\n publicKey,\n hexPubKey,\n };\n}\n\nexport const sign = async (privateKeyPem: string, base64Challenge: string): Promise<string> => {\n // Decode base64url challenge to bytes\n const challengeDataBytes = jose.base64url.decode(base64Challenge);\n\n // For EC private key format, we need to use a different import method\n // Since jose doesn't support SEC1 format directly, let's use Node.js crypto\n // Create a KeyObject from the EC private key\n const privateKey = crypto.createPrivateKey(privateKeyPem);\n\n // Use jose with the KeyObject\n return new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,MAAM,QAAQ,IAAI,YAAY,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,OAAO;CACzD,MAAM,WAAA,GAAUA,sBAAAA,OAAAA,CAAO,KAAK;CAC5B,QAAA,GAAOC,aAAAA,kBAAAA,CAAkB,SAASC,kCAAAA,QAAQ;AAC5C;AAEA,MAAM,kBAAkB,OAAO,MAAc,UAAuC;CAClF,MAAM,OAAO,OAAA,GAAMC,aAAAA,eAAAA,CAAe,QAAQ,MAAM,KAAK,CAAC;CAEtD,MAAM,WADUC,aAAAA,MAAM,eAAe,IACd,CAAC,CAAC,OAAO,qBAAqB;CACrD,OAAO,OAAO,OAAO,CAAC,SAAS,YAAa,SAAS,SAAU,CAAC;AAClE;AAEA,MAAa,gBAAgB,OAAO,SAAsC;CACxE,MAAM,YAAY,MAAM,QAAQ,IAAI;EAClC,gBAAgB,MAAM,CAAC;EACvB,gBAAgB,MAAM,CAAC;EACvB,gBAAgB,MAAM,CAAC;CACzB,CAAC;CAED,MAAM,aAAa,IAAI,WAAW,UAAU,EAAE,CAAC,MAAM;CACrD,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC,QAAQ,KACvC,WAAW,KAAK,UAAU,EAAE,CAAC,KAAM,UAAU,EAAE,CAAC,KAAM,UAAU,EAAE,CAAC;CAGrE,OAAO;AACT;;;AC1BA,MAAM,kBAAkBC,QAAAA,QAAK,OAAO,gBAAgB,WAAY;CAG9D,MAAM,OAAO;CACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,SAAS,CAAC,CAAC,IAAI,GACxB,KAAK,IAAI,YAAY,CAAC,CAAC,OAAO,GAC9B,KAAK,IAAI,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,GACpD,KAAK,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CACtD;AACJ,CAAC;AAED,MAAM,mBAAmBA,QAAAA,QAAK;CAC5B;;CAEA,WAAY;EAGV,MAAM,OAAO;EACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,SAAS,CAAC,CAAC,IAAI,GACxB,KACG,IAAI,qBAAqB,CAAC,CAC1B,IAAI,CAAC,CACL,IAAI,KAAK,IAAI,aAAa,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,GACjE,KAAK,IAAI,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,eAAe,GACxD,KAAK,IAAI,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CACvD;CACJ;AACF;AAEA,MAAM,0BAA0BA,QAAAA,QAAK,OAAO,wBAAwB,WAAY;CAG9E,MAAM,OAAO;CACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,GACjF,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,CACzB;AACJ,CAAC;AASD,MAAM,SAAuC;CAC3C,WAAW;EACT,iBAAiB;GAAC;GAAG;GAAG;GAAK;GAAG;EAAE;EAClC,mBAAmB,EAAE,OAAO,iBAAiB;EAC7C,kBAAkB,EAAE,OAAO,aAAa;EACxC,OAAO,IAAI,SAAA,QAAS,GAAG,WAAW;CACpC;CACA,MAAM;EACJ,iBAAiB;GAAC;GAAG;GAAG;GAAK;GAAO;GAAG;GAAG;EAAC;EAC3C,mBAAmB,EAAE,OAAO,iBAAiB;EAC7C,kBAAkB,EAAE,OAAO,aAAa;EACxC,OAAO,IAAI,SAAA,QAAS,GAAG,MAAM;CAC/B;AACF;AAoBA,IAAa,aAAb,MAAwB;CACtB;CACA;CAEA,YAAY,SAAgC;;EAE1C,IAAI,OAAO,YAAY,UAAU;;GAE/B,IAAI,YAAY,eAAe,YAAY,QACzC,MAAM,IAAI,MAAM,iBAAiB,SAAS;GAE5C,UAAU,OAAO;EACnB;EACA,KAAK,UAAU;EACf,KAAK,cAAc;GAAC;GAAG;GAAG;GAAK;GAAO;GAAG;EAAC;CAC5C;;CAGA,aAAqB,YAA8C;EACjE,OAAO;GACL,SAAS,IAAIC,MAAAA,QAAG,CAAC;GACjB;GACA,qBAAqB;IACnB,aAAa,KAAK;IAClB,OAAO,WAAW;GACpB;EACF;CACF;CAEA,iBAAiB,eAAuB,cAAuC;EAC7E,MAAM,mBAAoC;GACxC,SAAS,IAAIA,MAAAA,QAAG,CAAC;GACjB,YAAY,OAAO,KAAK,eAAe,KAAK;GAC5C,YAAY,KAAK,QAAQ;EAC3B;;EAGA,IAAI,cACF,iBAAiB,YAAY;GAC3B,QAAQ;GACR,MAAM,OAAO,KAAK,cAAc,KAAK;EACvC;EAGF,OAAO;CACT;CAEA,gBAAgB,cAGd;EACA,OAAO;GACL,WAAW;IACT,IAAI,KAAK;IACT,OAAO,KAAK,QAAQ;GACtB;GACA,KAAK;IACH,QAAQ;IACR,MAAM,OAAO,KAAK,cAAc,KAAK;GACvC;EACF;CACF;CAEA,cACE,YACA,gBACA,mBACA,wBAA2C,SACnC;EACR,IAAI;EAGJ,QAAQ,gBAAR;GACE,KAAK,OAAO;IACV,IAAI,OAAO,eAAe,UACxB,MAAM,IAAI,MAAM,8BAA8B;IAGhD,MAAM,eADU,KAAK,QAAQ,MAAM,eAAe,YAAY,KACnC,CAAC,CAAC,UAAU,KAAK;IAC5C,mBAAmB,KAAK,iBAAiB,YAAY,YAAY;IACjE;GACF;;GAEA,KAAK;IACH,IAAI,OAAO,eAAe,UACxB,aAAa,OAAO,KAAK,YAAY,KAAK;IAE5C,mBAAmB,gBAAgB,OAAO,YAAY,KAAK;IAC3D;GACF,KAAK;IACH,IAAI,OAAO,eAAe,UACxB,MAAM,IAAI,MAAM,8BAA8B;IAEhD,mBAAmB,gBAAgB,OACjC,YACA,OACA,KAAK,QAAQ,iBACf;IACA;;GAEF,SACE,MAAM,IAAI,MAAM,4BAA4B;EAChD;EAGA,QAAQ,mBAAR;GACE,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,iBAAiB,WAAW,SAAS,KAAK;SAC5C,IAAI,0BAA0B,SACnC,OAAO,KAAK,aAAa,gBAAgB,CAAC,CAAC,WAAW,WAAW,SAAS,KAAK;IAEjF;GACF,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,gBAAgB,OAAO,kBAAkB,KAAK,CAAC,CAAC,SAAS,KAAK;SAChE,IAAI,0BAA0B,SACnC,OAAO,iBAAiB,OAAO,KAAK,aAAa,gBAAgB,GAAG,KAAK,CAAC,CAAC,SACzE,KACF;IAEF;GACF,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,gBAAgB,OAAO,kBAAkB,OAAO,KAAK,QAAQ,iBAAiB;SAChF,IAAI,0BAA0B,SACnC,OAAO,iBAAiB,OAAO,KAAK,aAAa,gBAAgB,GAAG,OAAO;KACzE,GAAG,KAAK,QAAQ;KAChB,OAAO;IACT,CAAC;IAEH;;GAEF,SACE,MAAM,IAAI,MAAM,4CAA4C;EAChE;EAEA,MAAM,IAAI,MAAM,wCAAwC;CAC1D;CAEA,aACE,WACA,gBACA,mBACQ;EAER,IAAI;EAEJ,QAAQ,gBAAR;GACE,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,MAAM,IAAI,MAAM,6BAA6B;IAE/C,kBAAkB,KAAK,gBAAgB,SAAS;IAChD;;GAEF,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,YAAY,OAAO,KAAK,WAAW,KAAK;IAE1C,kBAAkB,wBAAwB,OAAO,WAAW,KAAK;IACjE;GACF,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,MAAM,IAAI,MAAM,6BAA6B;IAE/C,kBAAkB,wBAAwB,OACxC,WACA,OACA,KAAK,QAAQ,gBACf;IACA;;GAEF,SACE,MAAM,IAAI,MAAM,2BAA2B;EAC/C;EAGA,QAAQ,mBAAR;GACE,KAAK,OACH,OAAO,gBAAgB,IAAI,KAAK,SAAS,KAAK;GAChD,KAAK,OACH,OAAO,wBAAwB,OAAO,iBAAiB,KAAK,CAAC,CAAC,SAAS,KAAK;GAC9E,KAAK,OACH,OAAO,wBAAwB,OAC7B,iBACA,OACA,KAAK,QAAQ,gBACf;;GAEF,SACE,MAAM,IAAI,MAAM,2CAA2C;EAC/D;CACF;AACF;;;ACjSA,SAAS,iBAAiB,QAAwB;CAGhD,MAAM,MAAM,OAAO,MAAM,IAAI;CAC7B,IAAI,MAAM;CACV,IAAI,IAAI;CAMR,OAJkB,OAAO,KAAK,IAAI,KAAK,EAAE,GAAG,QAGZ,CAAC,CAAC,MAAM,EACnB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,YAAY;AACrD;AAEA,SAAS,SAAS,WAAmB,EAAE,YAAY,SAAS,CAAC,GAAW;CACtE,MAAM,aAAa,IAAI,WAAW,MAAM;CACxC,IAAI,WACF,OAAO,WAAW,cAAc,WAAW,OAAO,KAAK;CAEzD,OAAO,WAAW,aAAa,WAAW,OAAO,KAAK;AACxD;;;;;AAMA,SAAgB,QAAQ,SAAiC;CACvD,IAAI,SAAS;EACX,MAAM,KAAK,IAAI,SAAA,QAAS,GAAG,MAAM;EACjC,MAAM,gBAAgBC,YAAAA,QAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK;EAC9E,MAAM,UAAU,GAAG,WAAW,EAC5B,SAAS,OAAO,KAAK,eAAe,KAAK,EAC3C,CAAC;EACD,OAAO;GACL,YAAY,OAAO,SAAS,QAAQ,WAAW,KAAK,CAAC,CAAC;GACtD,WAAW,OAAO,SAAS,QAAQ,UAAU,KAAK,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC;GAC1E,WAAW,iBAAiB,OAAO,SAAS,QAAQ,UAAU,KAAK,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC,CAAC;EAC9F;CACF;CACA,MAAM,EAAE,WAAW,eAAeA,YAAAA,QAAO,oBAAoB,MAAM;EACjE,YAAY;EACZ,mBAAmB;GAAE,MAAM;GAAQ,QAAQ;EAAM;EACjD,oBAAoB;GAAE,MAAM;GAAQ,QAAQ;EAAM;CACpD,CAAC;CAED,OAAO;EACL;EACA;EACA,WAJgB,iBAAiB,SAIzB;CACV;AACF;AAEA,MAAa,OAAO,OAAO,eAAuB,oBAA6C;CAE7F,MAAM,qBAAqB,KAAK,UAAU,OAAO,eAAe;CAKhE,MAAM,aAAaA,YAAAA,QAAO,iBAAiB,aAAa;CAGxD,OAAO,IAAI,KAAK,YAAY,kBAAkB,CAAC,CAC5C,mBAAmB;EAAE,KAAK;EAAS,KAAK;CAAM,CAAC,CAAC,CAChD,KAAK,UAAU;AACpB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-BcqzGi2f.js","names":[],"sources":["../src/crypto/gen-seed.ts","../src/crypto/key-encoder.ts","../src/crypto/utils.ts"],"sourcesContent":["import { sha256 } from \"@noble/hashes/sha2.js\";\nimport { HDKey } from \"@scure/bip32\";\nimport { entropyToMnemonic, mnemonicToSeed } from \"@scure/bip39\";\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\";\n\n/**\n * Generate a deterministic BIP39 mnemonic from a salt and device index.\n *\n * Produces `entropyToMnemonic(SHA256(salt + \"_\" + index))`, matching\n * the behavior of `@ledgerhq/vault-common`'s `genSeed`.\n *\n * @param salt The workspace salt\n * @param index The device index (1-based)\n * @returns A 24-word BIP39 mnemonic string\n */\nexport function genSeed(salt: string, index: number): string {\n const input = new TextEncoder().encode(`${salt}_${index}`);\n const entropy = sha256(input);\n return entropyToMnemonic(entropy, wordlist);\n}\n\nconst getSeedFragment = async (salt: string, index: number): Promise<Uint8Array> => {\n const seed = await mnemonicToSeed(genSeed(salt, index));\n const secpKey = HDKey.fromMasterSeed(seed);\n const fragment = secpKey.derive(\"m/5655636'/4932953'\");\n return Buffer.concat([fragment.privateKey!, fragment.chainCode!]);\n};\n\nexport const getMasterSeed = async (salt: string): Promise<Uint8Array> => {\n const fragments = await Promise.all([\n getSeedFragment(salt, 7),\n getSeedFragment(salt, 8),\n getSeedFragment(salt, 9),\n ]);\n\n const masterSeed = new Uint8Array(fragments[0].length);\n for (let i = 0; i < fragments[0].length; i++) {\n masterSeed[i] = fragments[0][i]! ^ fragments[1][i]! ^ fragments[2][i]!;\n }\n\n return masterSeed;\n};\n","// ========================================================================== //\n// //\n// DISCLAIMER //\n// //\n// This code has been blindly copy-pasted from: //\n// https://github.com/LedgerHQ/pkey-ts //\n// //\n// ========================================================================== //\n//\n// @ts-expect-error this library does not ship types\nimport asn1 from \"asn1.js\";\nimport BN from \"bn.js\";\nimport elliptic from \"elliptic\";\n\n/* cspell:disable */\nconst ECPrivateKeyASN = asn1.define(\"ECPrivateKey\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self.key(\"privateKey\").octstr(),\n self.key(\"parameters\").explicit(0).objid().optional(),\n self.key(\"publicKey\").explicit(1).bitstr().optional(),\n );\n});\n\nconst ECPrivateKey8ASN = asn1.define(\n \"ECPrivateKey\",\n /* v8 ignore next -- @preserve */\n function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"version\").int(),\n self\n .key(\"privateKeyAlgorithm\")\n .seq()\n .obj(self.key(\"ecPublicKey\").objid(), self.key(\"curve\").objid()),\n self.key(\"privateKey\").octstr().contains(ECPrivateKeyASN),\n self.key(\"attributes\").explicit(0).bitstr().optional(),\n );\n },\n);\n\nconst SubjectPublicKeyInfoASN = asn1.define(\"SubjectPublicKeyInfo\", function () {\n // @ts-expect-error pure black box\n // biome-ignore lint/suspicious/noExplicitAny: black box\n const self = this as any;\n self\n .seq()\n .obj(\n self.key(\"algorithm\").seq().obj(self.key(\"id\").objid(), self.key(\"curve\").objid()),\n self.key(\"pub\").bitstr(),\n );\n});\n\ntype CurveOptions = {\n curveParameters: number[];\n privatePEMOptions: { label: string };\n publicPEMOptions: { label: string };\n curve: elliptic.ec;\n};\n\nconst curves: Record<string, CurveOptions> = {\n secp256k1: {\n curveParameters: [1, 3, 132, 0, 10],\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"secp256k1\"),\n },\n p256: {\n curveParameters: [1, 2, 840, 10045, 3, 1, 7], // OID for p256 curve\n privatePEMOptions: { label: \"EC PRIVATE KEY\" },\n publicPEMOptions: { label: \"PUBLIC KEY\" },\n curve: new elliptic.ec(\"p256\"),\n },\n};\n\ntype PrivateKeyPKCS1 = {\n version: BN;\n privateKey: Buffer;\n parameters: number[];\n publicKey?: {\n unused: number;\n data: Buffer;\n };\n};\n\ntype PrivateKeyPKCS8 = {\n version: BN;\n privateKey: PrivateKeyPKCS1;\n privateKeyAlgorithm: { ecPublicKey: number[]; curve: number[] };\n};\n\nexport type KeyFormat = \"raw\" | \"pem\" | \"der\";\n\nexport class KeyEncoder {\n algorithmID: number[];\n options: CurveOptions;\n\n constructor(options: string | CurveOptions) {\n /* v8 ignore else -- @preserve */\n if (typeof options === \"string\") {\n /* v8 ignore if -- @preserve */\n if (options !== \"secp256k1\" && options !== \"p256\") {\n throw new Error(`Unknown curve ${options}`);\n }\n options = curves[options]!;\n }\n this.options = options;\n this.algorithmID = [1, 2, 840, 10045, 2, 1];\n }\n\n /* v8 ignore next -- @preserve */\n private PKCS1toPKCS8(privateKey: PrivateKeyPKCS1): PrivateKeyPKCS8 {\n return {\n version: new BN(0),\n privateKey,\n privateKeyAlgorithm: {\n ecPublicKey: this.algorithmID,\n curve: privateKey.parameters,\n },\n };\n }\n\n privateKeyObject(rawPrivateKey: string, rawPublicKey: string): PrivateKeyPKCS1 {\n const privateKeyObject: PrivateKeyPKCS1 = {\n version: new BN(1),\n privateKey: Buffer.from(rawPrivateKey, \"hex\"),\n parameters: this.options.curveParameters,\n };\n\n /* v8 ignore else -- @preserve */\n if (rawPublicKey) {\n privateKeyObject.publicKey = {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n };\n }\n\n return privateKeyObject;\n }\n\n publicKeyObject(rawPublicKey: string): {\n algorithm: { id: number[]; curve: number[] };\n pub: { unused: number; data: Buffer };\n } {\n return {\n algorithm: {\n id: this.algorithmID,\n curve: this.options.curveParameters,\n },\n pub: {\n unused: 0,\n data: Buffer.from(rawPublicKey, \"hex\"),\n },\n };\n }\n\n encodePrivate(\n privateKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n destinationFormatType: \"pkcs8\" | \"pkcs1\" = \"pkcs1\",\n ): string {\n let privateKeyObject: PrivateKeyPKCS1;\n\n /* Parse the incoming private key and convert it to a private key object */\n switch (originalFormat) {\n case \"raw\": {\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n const keyPair = this.options.curve.keyFromPrivate(privateKey, \"hex\");\n const rawPublicKey = keyPair.getPublic(\"hex\");\n privateKeyObject = this.privateKeyObject(privateKey, rawPublicKey);\n break;\n }\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof privateKey === \"string\") {\n privateKey = Buffer.from(privateKey, \"hex\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(privateKey, \"der\");\n break;\n case \"pem\":\n if (typeof privateKey !== \"string\") {\n throw new Error(\"private key must be a string\");\n }\n privateKeyObject = ECPrivateKeyASN.decode(\n privateKey,\n \"pem\",\n this.options.privatePEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid private key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n if (destinationFormatType === \"pkcs1\") {\n return privateKeyObject.privateKey.toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return this.PKCS1toPKCS8(privateKeyObject).privateKey.privateKey.toString(\"hex\");\n }\n break;\n case \"der\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"der\").toString(\"hex\");\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"der\").toString(\n \"hex\",\n );\n }\n break;\n case \"pem\":\n if (destinationFormatType === \"pkcs1\") {\n return ECPrivateKeyASN.encode(privateKeyObject, \"pem\", this.options.privatePEMOptions);\n } else if (destinationFormatType === \"pkcs8\") {\n return ECPrivateKey8ASN.encode(this.PKCS1toPKCS8(privateKeyObject), \"pem\", {\n ...this.options.privatePEMOptions,\n label: \"PRIVATE KEY\",\n });\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for private key\");\n }\n\n throw new Error(\"unsupported destination format or type\");\n }\n\n encodePublic(\n publicKey: string | Buffer,\n originalFormat: KeyFormat,\n destinationFormat: KeyFormat,\n ): string {\n // biome-ignore lint/suspicious/noImplicitAnyLet: melting pot object\n let publicKeyObject;\n\n switch (originalFormat) {\n case \"raw\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = this.publicKeyObject(publicKey);\n break;\n /* v8 ignore next -- @preserve */\n case \"der\":\n if (typeof publicKey === \"string\") {\n publicKey = Buffer.from(publicKey, \"hex\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(publicKey, \"der\");\n break;\n case \"pem\":\n if (typeof publicKey !== \"string\") {\n throw new Error(\"public key must be a string\");\n }\n publicKeyObject = SubjectPublicKeyInfoASN.decode(\n publicKey,\n \"pem\",\n this.options.publicPEMOptions,\n );\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid public key format\");\n }\n\n /* Export the private key object to the desired format */\n switch (destinationFormat) {\n case \"raw\":\n return publicKeyObject.pub.data.toString(\"hex\");\n case \"der\":\n return SubjectPublicKeyInfoASN.encode(publicKeyObject, \"der\").toString(\"hex\");\n case \"pem\":\n return SubjectPublicKeyInfoASN.encode(\n publicKeyObject,\n \"pem\",\n this.options.publicPEMOptions,\n );\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(\"invalid destination format for public key\");\n }\n }\n}\n/* cspell:enable */\n","import elliptic from \"elliptic\";\nimport * as jose from \"jose\";\n\nimport { KeyEncoder } from \"./key-encoder\";\nimport type { GeneratedKeys } from \"./types\";\nimport crypto from \"node:crypto\";\n\nfunction extractPublicKey(pemKey: string): string {\n // convert the PEM formatted public key to raw public key in X9.62 uncompressed format\n // this is an oversimplified method and may not work with different curves or PEM formats\n const pem = pemKey.split(\"\\n\");\n pem.shift(); // remove the first line (BEGIN PUBLIC KEY)\n pem.pop(); // remove the last line (END PUBLIC KEY)\n // convert base64 to buffer\n const keyBuffer = Buffer.from(pem.join(\"\"), \"base64\");\n // assuming the first 26 bytes are the header for the SPKI formatted key.\n // the actual key should begin after this header.\n const actualKeyBuffer = keyBuffer.slice(26);\n return actualKeyBuffer.toString(\"hex\").toUpperCase();\n}\n\nfunction hexToPem(hexString: string, { isPrivate = true } = {}): string {\n const keyEncoder = new KeyEncoder(\"p256\");\n if (isPrivate) {\n return keyEncoder.encodePrivate(hexString, \"raw\", \"pem\");\n }\n return keyEncoder.encodePublic(hexString, \"raw\", \"pem\");\n}\n\n/**\n * If `entropy` is passed, will generate keys pair deterministically\n * else, random keys pair generated\n */\nexport function genKeys(entropy?: string): GeneratedKeys {\n if (entropy) {\n const ec = new elliptic.ec(\"p256\");\n const hashedEntropy = crypto.createHash(\"sha256\").update(entropy).digest(\"hex\");\n const keyPair = ec.genKeyPair({\n entropy: Buffer.from(hashedEntropy, \"hex\"),\n });\n return {\n privateKey: String(hexToPem(keyPair.getPrivate(\"hex\"))),\n publicKey: String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false })),\n hexPubKey: extractPublicKey(String(hexToPem(keyPair.getPublic(\"hex\"), { isPrivate: false }))),\n };\n }\n const { publicKey, privateKey } = crypto.generateKeyPairSync(\"ec\", {\n namedCurve: \"P-256\",\n publicKeyEncoding: { type: \"spki\", format: \"pem\" },\n privateKeyEncoding: { type: \"sec1\", format: \"pem\" },\n });\n const hexPubKey = extractPublicKey(publicKey);\n return {\n privateKey,\n publicKey,\n hexPubKey,\n };\n}\n\nexport const sign = async (privateKeyPem: string, base64Challenge: string): Promise<string> => {\n // Decode base64url challenge to bytes\n const challengeDataBytes = jose.base64url.decode(base64Challenge);\n\n // For EC private key format, we need to use a different import method\n // Since jose doesn't support SEC1 format directly, let's use Node.js crypto\n // Create a KeyObject from the EC private key\n const privateKey = crypto.createPrivateKey(privateKeyPem);\n\n // Use jose with the KeyObject\n return new jose.CompactSign(challengeDataBytes)\n .setProtectedHeader({ alg: \"ES256\", typ: \"JWT\" })\n .sign(privateKey);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAeA,SAAgB,QAAQ,MAAc,OAAuB;CAC3D,MAAM,QAAQ,IAAI,YAAY,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,OAAO;CACzD,MAAM,UAAU,OAAO,KAAK;CAC5B,OAAO,kBAAkB,SAAS,QAAQ;AAC5C;AAEA,MAAM,kBAAkB,OAAO,MAAc,UAAuC;CAClF,MAAM,OAAO,MAAM,eAAe,QAAQ,MAAM,KAAK,CAAC;CAEtD,MAAM,WADU,MAAM,eAAe,IACd,CAAC,CAAC,OAAO,qBAAqB;CACrD,OAAO,OAAO,OAAO,CAAC,SAAS,YAAa,SAAS,SAAU,CAAC;AAClE;AAEA,MAAa,gBAAgB,OAAO,SAAsC;CACxE,MAAM,YAAY,MAAM,QAAQ,IAAI;EAClC,gBAAgB,MAAM,CAAC;EACvB,gBAAgB,MAAM,CAAC;EACvB,gBAAgB,MAAM,CAAC;CACzB,CAAC;CAED,MAAM,aAAa,IAAI,WAAW,UAAU,EAAE,CAAC,MAAM;CACrD,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC,QAAQ,KACvC,WAAW,KAAK,UAAU,EAAE,CAAC,KAAM,UAAU,EAAE,CAAC,KAAM,UAAU,EAAE,CAAC;CAGrE,OAAO;AACT;;;AC1BA,MAAM,kBAAkB,KAAK,OAAO,gBAAgB,WAAY;CAG9D,MAAM,OAAO;CACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,SAAS,CAAC,CAAC,IAAI,GACxB,KAAK,IAAI,YAAY,CAAC,CAAC,OAAO,GAC9B,KAAK,IAAI,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,GACpD,KAAK,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CACtD;AACJ,CAAC;AAED,MAAM,mBAAmB,KAAK;CAC5B;;CAEA,WAAY;EAGV,MAAM,OAAO;EACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,SAAS,CAAC,CAAC,IAAI,GACxB,KACG,IAAI,qBAAqB,CAAC,CAC1B,IAAI,CAAC,CACL,IAAI,KAAK,IAAI,aAAa,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,GACjE,KAAK,IAAI,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,eAAe,GACxD,KAAK,IAAI,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CACvD;CACJ;AACF;AAEA,MAAM,0BAA0B,KAAK,OAAO,wBAAwB,WAAY;CAG9E,MAAM,OAAO;CACb,KACG,IAAI,CAAC,CACL,IACC,KAAK,IAAI,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,GACjF,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,CACzB;AACJ,CAAC;AASD,MAAM,SAAuC;CAC3C,WAAW;EACT,iBAAiB;GAAC;GAAG;GAAG;GAAK;GAAG;EAAE;EAClC,mBAAmB,EAAE,OAAO,iBAAiB;EAC7C,kBAAkB,EAAE,OAAO,aAAa;EACxC,OAAO,IAAI,SAAS,GAAG,WAAW;CACpC;CACA,MAAM;EACJ,iBAAiB;GAAC;GAAG;GAAG;GAAK;GAAO;GAAG;GAAG;EAAC;EAC3C,mBAAmB,EAAE,OAAO,iBAAiB;EAC7C,kBAAkB,EAAE,OAAO,aAAa;EACxC,OAAO,IAAI,SAAS,GAAG,MAAM;CAC/B;AACF;AAoBA,IAAa,aAAb,MAAwB;CACtB;CACA;CAEA,YAAY,SAAgC;;EAE1C,IAAI,OAAO,YAAY,UAAU;;GAE/B,IAAI,YAAY,eAAe,YAAY,QACzC,MAAM,IAAI,MAAM,iBAAiB,SAAS;GAE5C,UAAU,OAAO;EACnB;EACA,KAAK,UAAU;EACf,KAAK,cAAc;GAAC;GAAG;GAAG;GAAK;GAAO;GAAG;EAAC;CAC5C;;CAGA,aAAqB,YAA8C;EACjE,OAAO;GACL,SAAS,IAAI,GAAG,CAAC;GACjB;GACA,qBAAqB;IACnB,aAAa,KAAK;IAClB,OAAO,WAAW;GACpB;EACF;CACF;CAEA,iBAAiB,eAAuB,cAAuC;EAC7E,MAAM,mBAAoC;GACxC,SAAS,IAAI,GAAG,CAAC;GACjB,YAAY,OAAO,KAAK,eAAe,KAAK;GAC5C,YAAY,KAAK,QAAQ;EAC3B;;EAGA,IAAI,cACF,iBAAiB,YAAY;GAC3B,QAAQ;GACR,MAAM,OAAO,KAAK,cAAc,KAAK;EACvC;EAGF,OAAO;CACT;CAEA,gBAAgB,cAGd;EACA,OAAO;GACL,WAAW;IACT,IAAI,KAAK;IACT,OAAO,KAAK,QAAQ;GACtB;GACA,KAAK;IACH,QAAQ;IACR,MAAM,OAAO,KAAK,cAAc,KAAK;GACvC;EACF;CACF;CAEA,cACE,YACA,gBACA,mBACA,wBAA2C,SACnC;EACR,IAAI;EAGJ,QAAQ,gBAAR;GACE,KAAK,OAAO;IACV,IAAI,OAAO,eAAe,UACxB,MAAM,IAAI,MAAM,8BAA8B;IAGhD,MAAM,eADU,KAAK,QAAQ,MAAM,eAAe,YAAY,KACnC,CAAC,CAAC,UAAU,KAAK;IAC5C,mBAAmB,KAAK,iBAAiB,YAAY,YAAY;IACjE;GACF;;GAEA,KAAK;IACH,IAAI,OAAO,eAAe,UACxB,aAAa,OAAO,KAAK,YAAY,KAAK;IAE5C,mBAAmB,gBAAgB,OAAO,YAAY,KAAK;IAC3D;GACF,KAAK;IACH,IAAI,OAAO,eAAe,UACxB,MAAM,IAAI,MAAM,8BAA8B;IAEhD,mBAAmB,gBAAgB,OACjC,YACA,OACA,KAAK,QAAQ,iBACf;IACA;;GAEF,SACE,MAAM,IAAI,MAAM,4BAA4B;EAChD;EAGA,QAAQ,mBAAR;GACE,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,iBAAiB,WAAW,SAAS,KAAK;SAC5C,IAAI,0BAA0B,SACnC,OAAO,KAAK,aAAa,gBAAgB,CAAC,CAAC,WAAW,WAAW,SAAS,KAAK;IAEjF;GACF,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,gBAAgB,OAAO,kBAAkB,KAAK,CAAC,CAAC,SAAS,KAAK;SAChE,IAAI,0BAA0B,SACnC,OAAO,iBAAiB,OAAO,KAAK,aAAa,gBAAgB,GAAG,KAAK,CAAC,CAAC,SACzE,KACF;IAEF;GACF,KAAK;IACH,IAAI,0BAA0B,SAC5B,OAAO,gBAAgB,OAAO,kBAAkB,OAAO,KAAK,QAAQ,iBAAiB;SAChF,IAAI,0BAA0B,SACnC,OAAO,iBAAiB,OAAO,KAAK,aAAa,gBAAgB,GAAG,OAAO;KACzE,GAAG,KAAK,QAAQ;KAChB,OAAO;IACT,CAAC;IAEH;;GAEF,SACE,MAAM,IAAI,MAAM,4CAA4C;EAChE;EAEA,MAAM,IAAI,MAAM,wCAAwC;CAC1D;CAEA,aACE,WACA,gBACA,mBACQ;EAER,IAAI;EAEJ,QAAQ,gBAAR;GACE,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,MAAM,IAAI,MAAM,6BAA6B;IAE/C,kBAAkB,KAAK,gBAAgB,SAAS;IAChD;;GAEF,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,YAAY,OAAO,KAAK,WAAW,KAAK;IAE1C,kBAAkB,wBAAwB,OAAO,WAAW,KAAK;IACjE;GACF,KAAK;IACH,IAAI,OAAO,cAAc,UACvB,MAAM,IAAI,MAAM,6BAA6B;IAE/C,kBAAkB,wBAAwB,OACxC,WACA,OACA,KAAK,QAAQ,gBACf;IACA;;GAEF,SACE,MAAM,IAAI,MAAM,2BAA2B;EAC/C;EAGA,QAAQ,mBAAR;GACE,KAAK,OACH,OAAO,gBAAgB,IAAI,KAAK,SAAS,KAAK;GAChD,KAAK,OACH,OAAO,wBAAwB,OAAO,iBAAiB,KAAK,CAAC,CAAC,SAAS,KAAK;GAC9E,KAAK,OACH,OAAO,wBAAwB,OAC7B,iBACA,OACA,KAAK,QAAQ,gBACf;;GAEF,SACE,MAAM,IAAI,MAAM,2CAA2C;EAC/D;CACF;AACF;;;ACjSA,SAAS,iBAAiB,QAAwB;CAGhD,MAAM,MAAM,OAAO,MAAM,IAAI;CAC7B,IAAI,MAAM;CACV,IAAI,IAAI;CAMR,OAJkB,OAAO,KAAK,IAAI,KAAK,EAAE,GAAG,QAGZ,CAAC,CAAC,MAAM,EACnB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,YAAY;AACrD;AAEA,SAAS,SAAS,WAAmB,EAAE,YAAY,SAAS,CAAC,GAAW;CACtE,MAAM,aAAa,IAAI,WAAW,MAAM;CACxC,IAAI,WACF,OAAO,WAAW,cAAc,WAAW,OAAO,KAAK;CAEzD,OAAO,WAAW,aAAa,WAAW,OAAO,KAAK;AACxD;;;;;AAMA,SAAgB,QAAQ,SAAiC;CACvD,IAAI,SAAS;EACX,MAAM,KAAK,IAAI,SAAS,GAAG,MAAM;EACjC,MAAM,gBAAgB,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK;EAC9E,MAAM,UAAU,GAAG,WAAW,EAC5B,SAAS,OAAO,KAAK,eAAe,KAAK,EAC3C,CAAC;EACD,OAAO;GACL,YAAY,OAAO,SAAS,QAAQ,WAAW,KAAK,CAAC,CAAC;GACtD,WAAW,OAAO,SAAS,QAAQ,UAAU,KAAK,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC;GAC1E,WAAW,iBAAiB,OAAO,SAAS,QAAQ,UAAU,KAAK,GAAG,EAAE,WAAW,MAAM,CAAC,CAAC,CAAC;EAC9F;CACF;CACA,MAAM,EAAE,WAAW,eAAe,OAAO,oBAAoB,MAAM;EACjE,YAAY;EACZ,mBAAmB;GAAE,MAAM;GAAQ,QAAQ;EAAM;EACjD,oBAAoB;GAAE,MAAM;GAAQ,QAAQ;EAAM;CACpD,CAAC;CAED,OAAO;EACL;EACA;EACA,WAJgB,iBAAiB,SAIzB;CACV;AACF;AAEA,MAAa,OAAO,OAAO,eAAuB,oBAA6C;CAE7F,MAAM,qBAAqB,KAAK,UAAU,OAAO,eAAe;CAKhE,MAAM,aAAa,OAAO,iBAAiB,aAAa;CAGxD,OAAO,IAAI,KAAK,YAAY,kBAAkB,CAAC,CAC5C,mBAAmB;EAAE,KAAK;EAAS,KAAK;CAAM,CAAC,CAAC,CAChD,KAAK,UAAU;AACpB"}