@ledgerhq/revault-sdk 0.27.3 → 0.27.7

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.
@@ -67,13 +67,10 @@ const checkHsmHostingMode = (state, expectedMode) => {
67
67
  if (state.hsmHostingMode !== expectedMode) throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);
68
68
  };
69
69
  /* v8 ignore next -- @preserve */
70
- const checkExternalSigners = (state, externalSigners, debugAuthToken) => {
71
- const hasExternalSigners = externalSigners && externalSigners.length > 0;
72
- const canFetchExternalSigner = !!debugAuthToken;
73
- const errorMessage = (0, ts_pattern.match)(state.hsmHostingMode).with("HOSTED", () => !hasExternalSigners ? null : "Hosted HSM does not support external signers").with("ON_PREM", () => hasExternalSigners || canFetchExternalSigner ? null : "On-premises HSM requires at least 1 external signer or a debug auth token").exhaustive();
70
+ const checkExternalSigners = (state, debugAuthToken) => {
71
+ const errorMessage = (0, ts_pattern.match)(state.hsmHostingMode).with("HOSTED", () => null).with("ON_PREM", () => debugAuthToken ? null : "On-premises HSM requires a debug auth token").exhaustive();
74
72
  if (errorMessage !== null) throw new Error(errorMessage);
75
73
  };
76
- const base64ToHex = (value) => Buffer.from(value, "base64").toString("hex");
77
74
  const STEPS = {
78
75
  PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {
79
76
  const promises = [];
@@ -166,10 +163,9 @@ const STEPS = {
166
163
  }));
167
164
  return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });
168
165
  },
169
- PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners, debugAuthToken, signerSeed }, logger) => {
166
+ PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, debugAuthToken, signerSeed }, logger) => {
170
167
  checkHsmHostingMode(state, "ON_PREM");
171
168
  const { id: onboardingId } = state;
172
- let externalSignerPublicKeys = externalSigners;
173
169
  if (debugAuthToken) {
174
170
  const debugClient = engine.createClient({ debugAuthToken });
175
171
  const seed = signerSeed ?? Buffer.from(await require_crypto.getMasterSeed(engine.__options.salt)).toString("base64");
@@ -178,17 +174,8 @@ const STEPS = {
178
174
  seed
179
175
  });
180
176
  logger.info("Inserted external signer seed");
181
- if (!externalSignerPublicKeys || externalSignerPublicKeys.length === 0) {
182
- const { publicKey } = await debugClient.debug.getExternalSignerAuthKeypair.query({ workspaceName: state.workspaceName });
183
- externalSignerPublicKeys = [base64ToHex(publicKey)];
184
- logger.info("Fetched external signer public key");
185
- }
186
177
  }
187
- (0, invariant.default)(externalSignerPublicKeys && externalSignerPublicKeys.length > 0, "External signers must exist");
188
- state = await engine.client.onboarding.startExternalSignersRegistration.mutate({
189
- onboardingId,
190
- externalSigners: externalSignerPublicKeys
191
- });
178
+ state = await engine.client.onboarding.startExternalSignersRegistration.mutate({ onboardingId });
192
179
  const toCollect = state.masterAdmins.filter((admin) => !admin.reviewOfExternalSigners?.signature);
193
180
  await Promise.all(toCollect.map(async (admin) => {
194
181
  const index = deviceNameToIndex(admin.name);
@@ -214,11 +201,11 @@ const STEPS = {
214
201
  PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
215
202
  };
216
203
  async function onboard(opts, logger) {
217
- const { engine, externalSigners, debugAuthToken, signerSeed, untilStep } = opts;
204
+ const { engine, debugAuthToken, signerSeed, untilStep } = opts;
218
205
  const { __onboardingId } = engine;
219
206
  logger.info(`Joining onboarding ${__onboardingId}`);
220
207
  let state = await engine.client.onboarding.getOnboarding.query({ onboardingId: __onboardingId });
221
- checkExternalSigners(state, externalSigners, debugAuthToken);
208
+ checkExternalSigners(state, debugAuthToken);
222
209
  while (state.step !== "COMPLETED") {
223
210
  if (untilStep && state.step === untilStep) {
224
211
  logger.info("Skipping the rest of the onboarding");
@@ -229,7 +216,6 @@ async function onboard(opts, logger) {
229
216
  state = await step({
230
217
  engine,
231
218
  state,
232
- externalSigners,
233
219
  debugAuthToken,
234
220
  signerSeed
235
221
  }, logger);
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding.cjs","names":["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 externalSigners?: string[];\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 externalSigners: string[] | undefined,\n debugAuthToken: string | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const canFetchExternalSigner = !!debugAuthToken;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners || canFetchExternalSigner\n ? null\n : \"On-premises HSM requires at least 1 external signer or a debug auth token\",\n )\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nconst base64ToHex = (value: string): string => Buffer.from(value, \"base64\").toString(\"hex\");\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 /* 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, externalSigners, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n let externalSignerPublicKeys = externalSigners;\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 if (!externalSignerPublicKeys || externalSignerPublicKeys.length === 0) {\n const { publicKey } = await debugClient.debug.getExternalSignerAuthKeypair.query({\n workspaceName: state.workspaceName,\n });\n externalSignerPublicKeys = [base64ToHex(publicKey)];\n logger.info(\"Fetched external signer public key\");\n }\n }\n invariant(\n externalSignerPublicKeys && externalSignerPublicKeys.length > 0,\n \"External signers must exist\",\n );\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners: externalSignerPublicKeys,\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 externalSigners?: string[];\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, 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, externalSigners, 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, externalSigners, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":";;;;;;;AAyBA,MAAM,aAA0C;CAC9C,oBAAoB;CACpB,cAAc;CACd,cAAc;CACf;AAED,MAAM,UAAgE;CACpE;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACzE;AAED,MAAM,qBAAqB,SAAyB;CAClD,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,SAAS,KAAK,EAAE;AACpD,EAAA,GAAA,UAAA,SAAU,UAAU,KAAA,GAAW,kBAAkB,OAAO;AACxD,QAAO;;AAGT,MAAM,uBACJ,OACA,iBACS;;AAET,KAAI,MAAM,mBAAmB,aAC3B,OAAM,IAAI,MAAM,8BAA8B,aAAa,UAAU,MAAM,iBAAiB;;;AAKhG,MAAM,wBACJ,OACA,iBACA,mBACS;CACT,MAAM,qBAAqB,mBAAmB,gBAAgB,SAAS;CACvE,MAAM,yBAAyB,CAAC,CAAC;CACjC,MAAM,gBAAA,GAAA,WAAA,OAAqB,MAAM,eAAe,CAC7C,KAAK,gBACJ,CAAC,qBAAqB,OAAO,+CAC9B,CACA,KAAK,iBACJ,sBAAsB,yBAClB,OACA,4EACL,CACA,YAAY;AACf,KAAI,iBAAiB,KACnB,OAAM,IAAI,MAAM,aAAa;;AAIjC,MAAM,eAAe,UAA0B,OAAO,KAAK,OAAO,SAAS,CAAC,SAAS,MAAM;AAE3F,MAAa,QAAQ;CAInB,uBAAuB,OAAO,EAAE,OAAO,UAAU,WAAW;EAC1D,MAAM,WAA4B,EAAE;AACpC,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,MAAM,mBAAmB,aAAa,OAAO,SAAS,eACxD;;AAGF,OACE,MAAM,eAAe;;KAElB,MAAM,EAAE,eAAe,OAAO;IAChC,KAAK,KAAA,GACN;IACA,MAAM,UAAU,OACb,gBAAgB,OAAO,MAAM,CAC7B,YAAY;KAAE,MAAM,OAAO;KAAM,YAAY,OAAO;KAAM,CAAC,CAC3D,WAAW,OAAO,KAAK,WAAW,OAAO,OAAO,CAAC;AACpD,aAAS,KAAK,QAAQ;;;AAG1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,OAAO,OAAO,WAAW,mBAAmB,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;;CAMvF,mCAAmC,OAAO,EAAE,OAAO,UAAU,WAAW;EACtE,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,6BAA6B,OAAO,EAAE,cAAc,CAAC;EAC5F,MAAM,cAAc,MAAM;EAC1B,MAAM,YAAY,MAAM,eACrB,QAAQ,YAAY;AACnB,OAAI,QAAQ,SAAS,qBAAsB,QAAO;AAKlD,UAAO,CAJY,CAAC,CAAC,MAAM,aAAa,UAAU;;KAE/C,MAAM,EAAE,WAAW,QAAQ;IAC7B;IAED,CACD,KAAK,MAAM;AAEV,UADc,kBAAkB,EAAE,WAAW;IAE7C;AACJ,QAAM,QAAQ,IACZ,UAAU,KAAK,UACb,OACG,gBAAgB,MAAM,CACtB,2BAA2B,YAAY,CACvC,WAAW,OAAO,KAAK,0BAA0B,QAAQ,CAAC,CAC9D,CACF;AACD,SAAO,OAAO,OAAO,WAAW,kBAAkB,OAAO,EAAE,cAAc,CAAC;;CAM5E,yCAAyC,OAAO,EAAE,QAAQ,YACxD,OAAO,OAAO,WAAW,8BAA8B,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;CAK3F,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;EACvE,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;AAC1D,OAAI,QAAQ,SAAS,eAAgB,QAAO;AAK5C,UAAO,CAJe,CAAC,CAAC,MAAM,aAAa;;KAExC,MAAM,EAAE,WAAW,QAAQ;IAC7B;IAED;AACF,QAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,KAAK;AACrC,SAAM,OAAO,gBAAgB,MAAM,CAAC,eAAe;IAAE,MAAM;IAAS;IAAM,CAAC;AAC3E,UAAO,KAAK,cAAc,OAAO;IACjC,CACH;AACD,SAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,cAAc,CAAC;;CAMjF,yCAAyC,OAAO,EAAE,QAAQ,YAAY;AACpE,sBAAoB,OAAO,SAAS;AACpC,SAAO,OAAO,OAAO,WAAW,8BAA8B,OAAO,EACnE,cAAc,MAAM,IACrB,CAAC;;CAMJ,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;AACvE,sBAAoB,OAAO,SAAS;EACpC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;AAC1D,OAAI,QAAQ,SAAS,eAAgB,QAAO;AAI5C,UAAO,CAHe,CAAC,CAAC,MAAM,aAAa;;KACN,MAAM,EAAE,WAAW,QAAQ;IAC/D;IAED;AACF,QAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,KAAK;AACrC,SAAM,OAAO,gBAAgB,MAAM,CAAC,eAAe;IAAE,MAAM;IAAgB;IAAM,CAAC;AAClF,UAAO,KAAK,cAAc,OAAO;IACjC,CACH;AACD,SAAO,OAAO,OAAO,WAAW,+BAA+B,OAAO,EAAE,cAAc,CAAC;;CAMzF,iCAAiC,OAAO,EAAE,OAAO,UAAU,WAAW;EACpE,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,0BAA0B,OAAO,EAAE,cAAc,CAAC;EACzF,MAAM,YAAY,MAAM,aAAa,QAAQ,UAAU,CAAC,MAAM,QAAQ,UAAU;AAChF,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,KAAK;GAC3C,MAAM,YAAY,MAAM,QAAQ;AAChC,SAAM,OAAO,gBAAgB,MAAM,CAAC,kBAAkB,UAAW;AACjE,UAAO,KAAK,iBAAiB,MAAM,OAAO;IAC1C,CACH;AACD,SAAO,OAAO,OAAO,WAAW,2BAA2B,OAAO,EAAE,cAAc,CAAC;;CAGrF,uCAAuC,OACrC,EAAE,OAAO,QAAQ,iBAAiB,gBAAgB,cAClD,WACG;AACH,sBAAoB,OAAO,UAAU;EACrC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,IAAI,2BAA2B;AAC/B,MAAI,gBAAgB;GAClB,MAAM,cAAc,OAAO,aAAa,EAAE,gBAAgB,CAAC;GAC3D,MAAM,OACJ,cAAc,OAAO,KAAK,MAAMA,eAAAA,cAAc,OAAO,UAAU,KAAK,CAAC,CAAC,SAAS,SAAS;AAC1F,SAAM,YAAY,MAAM,yBAAyB,OAAO;IACtD,eAAe,MAAM;IACrB;IACD,CAAC;AACF,UAAO,KAAK,gCAAgC;AAE5C,OAAI,CAAC,4BAA4B,yBAAyB,WAAW,GAAG;IACtE,MAAM,EAAE,cAAc,MAAM,YAAY,MAAM,6BAA6B,MAAM,EAC/E,eAAe,MAAM,eACtB,CAAC;AACF,+BAA2B,CAAC,YAAY,UAAU,CAAC;AACnD,WAAO,KAAK,qCAAqC;;;AAGrD,GAAA,GAAA,UAAA,SACE,4BAA4B,yBAAyB,SAAS,GAC9D,8BACD;AACD,UAAQ,MAAM,OAAO,OAAO,WAAW,iCAAiC,OAAO;GAC7E;GACA,iBAAiB;GAClB,CAAC;EACF,MAAM,YAAY,MAAM,aAAa,QAClC,UAAU,CAAC,MAAM,yBAAyB,UAC5C;AACD,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,KAAK;GAC3C,MAAM,YAAY,MAAM,yBAAyB;AACjD,SAAM,OAAO,gBAAgB,MAAM,CAAC,sBAAsB,UAAW;AACrE,UAAO,KAAK,iBAAiB,MAAM,OAAO;IAC1C,CACH;AACD,SAAO,OAAO,OAAO,WAAW,kCAAkC,OAAO,EAAE,cAAc,CAAC;;CAM5F,2BAA2B,OAAO,EAAE,OAAO,UAAU,WAAW;AAC9D,sBAAoB,OAAO,SAAS;EACpC,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,sBAAsB,OAAO,EAAE,cAAc,CAAC;EACrF,MAAM,YAAY,MAAM,aAAa,QAAQ,OAAO,CAAC,GAAG,QAAQ,aAAa;AAC7E,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,OAAO;GAC1B,MAAM,QAAQ,kBAAkB,GAAG,KAAK;GACxC,MAAM,YAAY,GAAG,QAAQ;AAC7B,SAAM,OAAO,gBAAgB,MAAM,CAAC,oBAAoB,UAAW;AACnE,UAAO,KAAK,0BAA0B,GAAG,OAAO;IAChD,CACH;AACD,SAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,cAAc,CAAC;;CAMjF,kCAAkC,OAAO,EAAE,OAAO,aAChD,OAAO,OAAO,WAAW,oBAAoB,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;CAClF;AAED,eAAsB,QACpB,MAOA,QACe;CACf,MAAM,EAAE,QAAQ,iBAAiB,gBAAgB,YAAY,cAAc;CAE3E,MAAM,EAAE,mBAAmB;AAC3B,QAAO,KAAK,sBAAsB,iBAAiB;CACnD,IAAI,QAAQ,MAAM,OAAO,OAAO,WAAW,cAAc,MAAM,EAC7D,cAAc,gBACf,CAAC;AAEF,sBAAqB,OAAO,iBAAiB,eAAe;AAE5D,QAAO,MAAM,SAAS,aAAa;AACjC,MAAI,aAAa,MAAM,SAAS,WAAW;AACzC,UAAO,KAAK,sCAAsC;AAClD;;EAEF,MAAM,OAAO,MAAM,MAAM;AACzB,SAAO,KAAK,KAAK,KAAK;AACtB,UAAQ,MAAM,KAAK;GAAE;GAAQ;GAAO;GAAiB;GAAgB;GAAY,EAAE,OAAO"}
1
+ {"version":3,"file":"onboarding.cjs","names":["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 /* 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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"}
@@ -13,7 +13,6 @@ declare const STEPS: {
13
13
  }: {
14
14
  engine: Engine<WithOnboarding>;
15
15
  state: OnboardingFullStateResponse;
16
- externalSigners?: string[];
17
16
  debugAuthToken?: string;
18
17
  signerSeed?: string;
19
18
  }, logger: Logger) => Promise<{
@@ -207,7 +206,6 @@ declare const STEPS: {
207
206
  }: {
208
207
  engine: Engine<WithOnboarding>;
209
208
  state: OnboardingFullStateResponse;
210
- externalSigners?: string[];
211
209
  debugAuthToken?: string;
212
210
  signerSeed?: string;
213
211
  }, logger: Logger) => Promise<{
@@ -401,7 +399,6 @@ declare const STEPS: {
401
399
  }: {
402
400
  engine: Engine<WithOnboarding>;
403
401
  state: OnboardingFullStateResponse;
404
- externalSigners?: string[];
405
402
  debugAuthToken?: string;
406
403
  signerSeed?: string;
407
404
  }) => Promise<{
@@ -595,7 +592,6 @@ declare const STEPS: {
595
592
  }: {
596
593
  engine: Engine<WithOnboarding>;
597
594
  state: OnboardingFullStateResponse;
598
- externalSigners?: string[];
599
595
  debugAuthToken?: string;
600
596
  signerSeed?: string;
601
597
  }, logger: Logger) => Promise<{
@@ -789,7 +785,6 @@ declare const STEPS: {
789
785
  }: {
790
786
  engine: Engine<WithOnboarding>;
791
787
  state: OnboardingFullStateResponse;
792
- externalSigners?: string[];
793
788
  debugAuthToken?: string;
794
789
  signerSeed?: string;
795
790
  }) => Promise<{
@@ -983,7 +978,6 @@ declare const STEPS: {
983
978
  }: {
984
979
  engine: Engine<WithOnboarding>;
985
980
  state: OnboardingFullStateResponse;
986
- externalSigners?: string[];
987
981
  debugAuthToken?: string;
988
982
  signerSeed?: string;
989
983
  }, logger: Logger) => Promise<{
@@ -1177,7 +1171,6 @@ declare const STEPS: {
1177
1171
  }: {
1178
1172
  engine: Engine<WithOnboarding>;
1179
1173
  state: OnboardingFullStateResponse;
1180
- externalSigners?: string[];
1181
1174
  debugAuthToken?: string;
1182
1175
  signerSeed?: string;
1183
1176
  }, logger: Logger) => Promise<{
@@ -1365,13 +1358,11 @@ declare const STEPS: {
1365
1358
  readonly PENDING_EXTERNAL_SIGNERS_REGISTRATION: ({
1366
1359
  state,
1367
1360
  engine,
1368
- externalSigners,
1369
1361
  debugAuthToken,
1370
1362
  signerSeed
1371
1363
  }: {
1372
1364
  engine: Engine<WithOnboarding>;
1373
1365
  state: OnboardingFullStateResponse;
1374
- externalSigners?: string[];
1375
1366
  debugAuthToken?: string;
1376
1367
  signerSeed?: string;
1377
1368
  }, logger: Logger) => Promise<{
@@ -1565,7 +1556,6 @@ declare const STEPS: {
1565
1556
  }: {
1566
1557
  engine: Engine<WithOnboarding>;
1567
1558
  state: OnboardingFullStateResponse;
1568
- externalSigners?: string[];
1569
1559
  debugAuthToken?: string;
1570
1560
  signerSeed?: string;
1571
1561
  }, logger: Logger) => Promise<{
@@ -1759,7 +1749,6 @@ declare const STEPS: {
1759
1749
  }: {
1760
1750
  engine: Engine<WithOnboarding>;
1761
1751
  state: OnboardingFullStateResponse;
1762
- externalSigners?: string[];
1763
1752
  debugAuthToken?: string;
1764
1753
  signerSeed?: string;
1765
1754
  }) => Promise<{
@@ -1947,7 +1936,6 @@ declare const STEPS: {
1947
1936
  };
1948
1937
  declare function onboard(opts: {
1949
1938
  engine: Engine<WithOnboarding>;
1950
- externalSigners?: string[];
1951
1939
  debugAuthToken?: string;
1952
1940
  signerSeed?: string;
1953
1941
  untilStep?: OnboardingStep;
@@ -13,7 +13,6 @@ declare const STEPS: {
13
13
  }: {
14
14
  engine: Engine<WithOnboarding>;
15
15
  state: OnboardingFullStateResponse;
16
- externalSigners?: string[];
17
16
  debugAuthToken?: string;
18
17
  signerSeed?: string;
19
18
  }, logger: Logger) => Promise<{
@@ -207,7 +206,6 @@ declare const STEPS: {
207
206
  }: {
208
207
  engine: Engine<WithOnboarding>;
209
208
  state: OnboardingFullStateResponse;
210
- externalSigners?: string[];
211
209
  debugAuthToken?: string;
212
210
  signerSeed?: string;
213
211
  }, logger: Logger) => Promise<{
@@ -401,7 +399,6 @@ declare const STEPS: {
401
399
  }: {
402
400
  engine: Engine<WithOnboarding>;
403
401
  state: OnboardingFullStateResponse;
404
- externalSigners?: string[];
405
402
  debugAuthToken?: string;
406
403
  signerSeed?: string;
407
404
  }) => Promise<{
@@ -595,7 +592,6 @@ declare const STEPS: {
595
592
  }: {
596
593
  engine: Engine<WithOnboarding>;
597
594
  state: OnboardingFullStateResponse;
598
- externalSigners?: string[];
599
595
  debugAuthToken?: string;
600
596
  signerSeed?: string;
601
597
  }, logger: Logger) => Promise<{
@@ -789,7 +785,6 @@ declare const STEPS: {
789
785
  }: {
790
786
  engine: Engine<WithOnboarding>;
791
787
  state: OnboardingFullStateResponse;
792
- externalSigners?: string[];
793
788
  debugAuthToken?: string;
794
789
  signerSeed?: string;
795
790
  }) => Promise<{
@@ -983,7 +978,6 @@ declare const STEPS: {
983
978
  }: {
984
979
  engine: Engine<WithOnboarding>;
985
980
  state: OnboardingFullStateResponse;
986
- externalSigners?: string[];
987
981
  debugAuthToken?: string;
988
982
  signerSeed?: string;
989
983
  }, logger: Logger) => Promise<{
@@ -1177,7 +1171,6 @@ declare const STEPS: {
1177
1171
  }: {
1178
1172
  engine: Engine<WithOnboarding>;
1179
1173
  state: OnboardingFullStateResponse;
1180
- externalSigners?: string[];
1181
1174
  debugAuthToken?: string;
1182
1175
  signerSeed?: string;
1183
1176
  }, logger: Logger) => Promise<{
@@ -1365,13 +1358,11 @@ declare const STEPS: {
1365
1358
  readonly PENDING_EXTERNAL_SIGNERS_REGISTRATION: ({
1366
1359
  state,
1367
1360
  engine,
1368
- externalSigners,
1369
1361
  debugAuthToken,
1370
1362
  signerSeed
1371
1363
  }: {
1372
1364
  engine: Engine<WithOnboarding>;
1373
1365
  state: OnboardingFullStateResponse;
1374
- externalSigners?: string[];
1375
1366
  debugAuthToken?: string;
1376
1367
  signerSeed?: string;
1377
1368
  }, logger: Logger) => Promise<{
@@ -1565,7 +1556,6 @@ declare const STEPS: {
1565
1556
  }: {
1566
1557
  engine: Engine<WithOnboarding>;
1567
1558
  state: OnboardingFullStateResponse;
1568
- externalSigners?: string[];
1569
1559
  debugAuthToken?: string;
1570
1560
  signerSeed?: string;
1571
1561
  }, logger: Logger) => Promise<{
@@ -1759,7 +1749,6 @@ declare const STEPS: {
1759
1749
  }: {
1760
1750
  engine: Engine<WithOnboarding>;
1761
1751
  state: OnboardingFullStateResponse;
1762
- externalSigners?: string[];
1763
1752
  debugAuthToken?: string;
1764
1753
  signerSeed?: string;
1765
1754
  }) => Promise<{
@@ -1947,7 +1936,6 @@ declare const STEPS: {
1947
1936
  };
1948
1937
  declare function onboard(opts: {
1949
1938
  engine: Engine<WithOnboarding>;
1950
- externalSigners?: string[];
1951
1939
  debugAuthToken?: string;
1952
1940
  signerSeed?: string;
1953
1941
  untilStep?: OnboardingStep;
package/lib/onboarding.js CHANGED
@@ -64,13 +64,10 @@ const checkHsmHostingMode = (state, expectedMode) => {
64
64
  if (state.hsmHostingMode !== expectedMode) throw new Error(`HSM hosting mode should be ${expectedMode} but is ${state.hsmHostingMode}`);
65
65
  };
66
66
  /* v8 ignore next -- @preserve */
67
- const checkExternalSigners = (state, externalSigners, debugAuthToken) => {
68
- const hasExternalSigners = externalSigners && externalSigners.length > 0;
69
- const canFetchExternalSigner = !!debugAuthToken;
70
- const errorMessage = match(state.hsmHostingMode).with("HOSTED", () => !hasExternalSigners ? null : "Hosted HSM does not support external signers").with("ON_PREM", () => hasExternalSigners || canFetchExternalSigner ? null : "On-premises HSM requires at least 1 external signer or a debug auth token").exhaustive();
67
+ const checkExternalSigners = (state, debugAuthToken) => {
68
+ const errorMessage = match(state.hsmHostingMode).with("HOSTED", () => null).with("ON_PREM", () => debugAuthToken ? null : "On-premises HSM requires a debug auth token").exhaustive();
71
69
  if (errorMessage !== null) throw new Error(errorMessage);
72
70
  };
73
- const base64ToHex = (value) => Buffer.from(value, "base64").toString("hex");
74
71
  const STEPS = {
75
72
  PENDING_DEVICE_CLAIMS: async ({ state, engine }, logger) => {
76
73
  const promises = [];
@@ -163,10 +160,9 @@ const STEPS = {
163
160
  }));
164
161
  return engine.client.onboarding.commitReviewByMasterAdmins.mutate({ onboardingId });
165
162
  },
166
- PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, externalSigners, debugAuthToken, signerSeed }, logger) => {
163
+ PENDING_EXTERNAL_SIGNERS_REGISTRATION: async ({ state, engine, debugAuthToken, signerSeed }, logger) => {
167
164
  checkHsmHostingMode(state, "ON_PREM");
168
165
  const { id: onboardingId } = state;
169
- let externalSignerPublicKeys = externalSigners;
170
166
  if (debugAuthToken) {
171
167
  const debugClient = engine.createClient({ debugAuthToken });
172
168
  const seed = signerSeed ?? Buffer.from(await getMasterSeed(engine.__options.salt)).toString("base64");
@@ -175,17 +171,8 @@ const STEPS = {
175
171
  seed
176
172
  });
177
173
  logger.info("Inserted external signer seed");
178
- if (!externalSignerPublicKeys || externalSignerPublicKeys.length === 0) {
179
- const { publicKey } = await debugClient.debug.getExternalSignerAuthKeypair.query({ workspaceName: state.workspaceName });
180
- externalSignerPublicKeys = [base64ToHex(publicKey)];
181
- logger.info("Fetched external signer public key");
182
- }
183
174
  }
184
- invariant(externalSignerPublicKeys && externalSignerPublicKeys.length > 0, "External signers must exist");
185
- state = await engine.client.onboarding.startExternalSignersRegistration.mutate({
186
- onboardingId,
187
- externalSigners: externalSignerPublicKeys
188
- });
175
+ state = await engine.client.onboarding.startExternalSignersRegistration.mutate({ onboardingId });
189
176
  const toCollect = state.masterAdmins.filter((admin) => !admin.reviewOfExternalSigners?.signature);
190
177
  await Promise.all(toCollect.map(async (admin) => {
191
178
  const index = deviceNameToIndex(admin.name);
@@ -211,11 +198,11 @@ const STEPS = {
211
198
  PENDING_WORKSPACE_INITIALIZATION: async ({ state, engine }) => engine.client.onboarding.initializeWorkspace.mutate({ onboardingId: state.id })
212
199
  };
213
200
  async function onboard(opts, logger) {
214
- const { engine, externalSigners, debugAuthToken, signerSeed, untilStep } = opts;
201
+ const { engine, debugAuthToken, signerSeed, untilStep } = opts;
215
202
  const { __onboardingId } = engine;
216
203
  logger.info(`Joining onboarding ${__onboardingId}`);
217
204
  let state = await engine.client.onboarding.getOnboarding.query({ onboardingId: __onboardingId });
218
- checkExternalSigners(state, externalSigners, debugAuthToken);
205
+ checkExternalSigners(state, debugAuthToken);
219
206
  while (state.step !== "COMPLETED") {
220
207
  if (untilStep && state.step === untilStep) {
221
208
  logger.info("Skipping the rest of the onboarding");
@@ -226,7 +213,6 @@ async function onboard(opts, logger) {
226
213
  state = await step({
227
214
  engine,
228
215
  state,
229
- externalSigners,
230
216
  debugAuthToken,
231
217
  signerSeed
232
218
  }, logger);
@@ -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 externalSigners?: string[];\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 externalSigners: string[] | undefined,\n debugAuthToken: string | undefined,\n): void => {\n const hasExternalSigners = externalSigners && externalSigners.length > 0;\n const canFetchExternalSigner = !!debugAuthToken;\n const errorMessage = match(state.hsmHostingMode)\n .with(\"HOSTED\", () =>\n !hasExternalSigners ? null : \"Hosted HSM does not support external signers\",\n )\n .with(\"ON_PREM\", () =>\n hasExternalSigners || canFetchExternalSigner\n ? null\n : \"On-premises HSM requires at least 1 external signer or a debug auth token\",\n )\n .exhaustive();\n if (errorMessage !== null) {\n throw new Error(errorMessage);\n }\n};\n\nconst base64ToHex = (value: string): string => Buffer.from(value, \"base64\").toString(\"hex\");\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 /* 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, externalSigners, debugAuthToken, signerSeed },\n logger,\n ) => {\n checkHsmHostingMode(state, \"ON_PREM\");\n const { id: onboardingId } = state;\n let externalSignerPublicKeys = externalSigners;\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 if (!externalSignerPublicKeys || externalSignerPublicKeys.length === 0) {\n const { publicKey } = await debugClient.debug.getExternalSignerAuthKeypair.query({\n workspaceName: state.workspaceName,\n });\n externalSignerPublicKeys = [base64ToHex(publicKey)];\n logger.info(\"Fetched external signer public key\");\n }\n }\n invariant(\n externalSignerPublicKeys && externalSignerPublicKeys.length > 0,\n \"External signers must exist\",\n );\n state = await engine.client.onboarding.startExternalSignersRegistration.mutate({\n onboardingId,\n externalSigners: externalSignerPublicKeys,\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 externalSigners?: string[];\n debugAuthToken?: string;\n signerSeed?: string;\n untilStep?: OnboardingStep;\n },\n logger: Logger,\n): Promise<void> {\n const { engine, externalSigners, 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, externalSigners, 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, externalSigners, debugAuthToken, signerSeed }, logger);\n }\n}\n"],"mappings":";;;;AAyBA,MAAM,aAA0C;CAC9C,oBAAoB;CACpB,cAAc;CACd,cAAc;CACf;AAED,MAAM,UAAgE;CACpE;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAsB,MAAM,GAAG,WAAW,mBAAmB;EAAK;CACpF;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACxE;EAAE,OAAO;EAAG,MAAM;EAAgB,MAAM,GAAG,WAAW,aAAa;EAAK;CACzE;AAED,MAAM,qBAAqB,SAAyB;CAClD,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,SAAS,KAAK,EAAE;AACpD,WAAU,UAAU,KAAA,GAAW,kBAAkB,OAAO;AACxD,QAAO;;AAGT,MAAM,uBACJ,OACA,iBACS;;AAET,KAAI,MAAM,mBAAmB,aAC3B,OAAM,IAAI,MAAM,8BAA8B,aAAa,UAAU,MAAM,iBAAiB;;;AAKhG,MAAM,wBACJ,OACA,iBACA,mBACS;CACT,MAAM,qBAAqB,mBAAmB,gBAAgB,SAAS;CACvE,MAAM,yBAAyB,CAAC,CAAC;CACjC,MAAM,eAAe,MAAM,MAAM,eAAe,CAC7C,KAAK,gBACJ,CAAC,qBAAqB,OAAO,+CAC9B,CACA,KAAK,iBACJ,sBAAsB,yBAClB,OACA,4EACL,CACA,YAAY;AACf,KAAI,iBAAiB,KACnB,OAAM,IAAI,MAAM,aAAa;;AAIjC,MAAM,eAAe,UAA0B,OAAO,KAAK,OAAO,SAAS,CAAC,SAAS,MAAM;AAE3F,MAAa,QAAQ;CAInB,uBAAuB,OAAO,EAAE,OAAO,UAAU,WAAW;EAC1D,MAAM,WAA4B,EAAE;AACpC,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,MAAM,mBAAmB,aAAa,OAAO,SAAS,eACxD;;AAGF,OACE,MAAM,eAAe;;KAElB,MAAM,EAAE,eAAe,OAAO;IAChC,KAAK,KAAA,GACN;IACA,MAAM,UAAU,OACb,gBAAgB,OAAO,MAAM,CAC7B,YAAY;KAAE,MAAM,OAAO;KAAM,YAAY,OAAO;KAAM,CAAC,CAC3D,WAAW,OAAO,KAAK,WAAW,OAAO,OAAO,CAAC;AACpD,aAAS,KAAK,QAAQ;;;AAG1B,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO,OAAO,OAAO,WAAW,mBAAmB,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;;CAMvF,mCAAmC,OAAO,EAAE,OAAO,UAAU,WAAW;EACtE,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,6BAA6B,OAAO,EAAE,cAAc,CAAC;EAC5F,MAAM,cAAc,MAAM;EAC1B,MAAM,YAAY,MAAM,eACrB,QAAQ,YAAY;AACnB,OAAI,QAAQ,SAAS,qBAAsB,QAAO;AAKlD,UAAO,CAJY,CAAC,CAAC,MAAM,aAAa,UAAU;;KAE/C,MAAM,EAAE,WAAW,QAAQ;IAC7B;IAED,CACD,KAAK,MAAM;AAEV,UADc,kBAAkB,EAAE,WAAW;IAE7C;AACJ,QAAM,QAAQ,IACZ,UAAU,KAAK,UACb,OACG,gBAAgB,MAAM,CACtB,2BAA2B,YAAY,CACvC,WAAW,OAAO,KAAK,0BAA0B,QAAQ,CAAC,CAC9D,CACF;AACD,SAAO,OAAO,OAAO,WAAW,kBAAkB,OAAO,EAAE,cAAc,CAAC;;CAM5E,yCAAyC,OAAO,EAAE,QAAQ,YACxD,OAAO,OAAO,WAAW,8BAA8B,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;CAK3F,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;EACvE,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;AAC1D,OAAI,QAAQ,SAAS,eAAgB,QAAO;AAK5C,UAAO,CAJe,CAAC,CAAC,MAAM,aAAa;;KAExC,MAAM,EAAE,WAAW,QAAQ;IAC7B;IAED;AACF,QAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,KAAK;AACrC,SAAM,OAAO,gBAAgB,MAAM,CAAC,eAAe;IAAE,MAAM;IAAS;IAAM,CAAC;AAC3E,UAAO,KAAK,cAAc,OAAO;IACjC,CACH;AACD,SAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,cAAc,CAAC;;CAMjF,yCAAyC,OAAO,EAAE,QAAQ,YAAY;AACpE,sBAAoB,OAAO,SAAS;AACpC,SAAO,OAAO,OAAO,WAAW,8BAA8B,OAAO,EACnE,cAAc,MAAM,IACrB,CAAC;;CAMJ,oCAAoC,OAAO,EAAE,OAAO,UAAU,WAAW;AACvE,sBAAoB,OAAO,SAAS;EACpC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,MAAM,aAAa,MAAM,eAAe,QAAQ,YAAY;AAC1D,OAAI,QAAQ,SAAS,eAAgB,QAAO;AAI5C,UAAO,CAHe,CAAC,CAAC,MAAM,aAAa;;KACN,MAAM,EAAE,WAAW,QAAQ;IAC/D;IAED;AACF,QAAM,QAAQ,IACZ,WAAW,IAAI,OAAO,EAAE,YAAY,WAAW;GAC7C,MAAM,QAAQ,kBAAkB,KAAK;AACrC,SAAM,OAAO,gBAAgB,MAAM,CAAC,eAAe;IAAE,MAAM;IAAgB;IAAM,CAAC;AAClF,UAAO,KAAK,cAAc,OAAO;IACjC,CACH;AACD,SAAO,OAAO,OAAO,WAAW,+BAA+B,OAAO,EAAE,cAAc,CAAC;;CAMzF,iCAAiC,OAAO,EAAE,OAAO,UAAU,WAAW;EACpE,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,0BAA0B,OAAO,EAAE,cAAc,CAAC;EACzF,MAAM,YAAY,MAAM,aAAa,QAAQ,UAAU,CAAC,MAAM,QAAQ,UAAU;AAChF,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,KAAK;GAC3C,MAAM,YAAY,MAAM,QAAQ;AAChC,SAAM,OAAO,gBAAgB,MAAM,CAAC,kBAAkB,UAAW;AACjE,UAAO,KAAK,iBAAiB,MAAM,OAAO;IAC1C,CACH;AACD,SAAO,OAAO,OAAO,WAAW,2BAA2B,OAAO,EAAE,cAAc,CAAC;;CAGrF,uCAAuC,OACrC,EAAE,OAAO,QAAQ,iBAAiB,gBAAgB,cAClD,WACG;AACH,sBAAoB,OAAO,UAAU;EACrC,MAAM,EAAE,IAAI,iBAAiB;EAC7B,IAAI,2BAA2B;AAC/B,MAAI,gBAAgB;GAClB,MAAM,cAAc,OAAO,aAAa,EAAE,gBAAgB,CAAC;GAC3D,MAAM,OACJ,cAAc,OAAO,KAAK,MAAM,cAAc,OAAO,UAAU,KAAK,CAAC,CAAC,SAAS,SAAS;AAC1F,SAAM,YAAY,MAAM,yBAAyB,OAAO;IACtD,eAAe,MAAM;IACrB;IACD,CAAC;AACF,UAAO,KAAK,gCAAgC;AAE5C,OAAI,CAAC,4BAA4B,yBAAyB,WAAW,GAAG;IACtE,MAAM,EAAE,cAAc,MAAM,YAAY,MAAM,6BAA6B,MAAM,EAC/E,eAAe,MAAM,eACtB,CAAC;AACF,+BAA2B,CAAC,YAAY,UAAU,CAAC;AACnD,WAAO,KAAK,qCAAqC;;;AAGrD,YACE,4BAA4B,yBAAyB,SAAS,GAC9D,8BACD;AACD,UAAQ,MAAM,OAAO,OAAO,WAAW,iCAAiC,OAAO;GAC7E;GACA,iBAAiB;GAClB,CAAC;EACF,MAAM,YAAY,MAAM,aAAa,QAClC,UAAU,CAAC,MAAM,yBAAyB,UAC5C;AACD,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,UAAU;GAC7B,MAAM,QAAQ,kBAAkB,MAAM,KAAK;GAC3C,MAAM,YAAY,MAAM,yBAAyB;AACjD,SAAM,OAAO,gBAAgB,MAAM,CAAC,sBAAsB,UAAW;AACrE,UAAO,KAAK,iBAAiB,MAAM,OAAO;IAC1C,CACH;AACD,SAAO,OAAO,OAAO,WAAW,kCAAkC,OAAO,EAAE,cAAc,CAAC;;CAM5F,2BAA2B,OAAO,EAAE,OAAO,UAAU,WAAW;AAC9D,sBAAoB,OAAO,SAAS;EACpC,MAAM,EAAE,IAAI,iBAAiB;AAC7B,UAAQ,MAAM,OAAO,OAAO,WAAW,sBAAsB,OAAO,EAAE,cAAc,CAAC;EACrF,MAAM,YAAY,MAAM,aAAa,QAAQ,OAAO,CAAC,GAAG,QAAQ,aAAa;AAC7E,QAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,OAAO;GAC1B,MAAM,QAAQ,kBAAkB,GAAG,KAAK;GACxC,MAAM,YAAY,GAAG,QAAQ;AAC7B,SAAM,OAAO,gBAAgB,MAAM,CAAC,oBAAoB,UAAW;AACnE,UAAO,KAAK,0BAA0B,GAAG,OAAO;IAChD,CACH;AACD,SAAO,OAAO,OAAO,WAAW,uBAAuB,OAAO,EAAE,cAAc,CAAC;;CAMjF,kCAAkC,OAAO,EAAE,OAAO,aAChD,OAAO,OAAO,WAAW,oBAAoB,OAAO,EAAE,cAAc,MAAM,IAAI,CAAC;CAClF;AAED,eAAsB,QACpB,MAOA,QACe;CACf,MAAM,EAAE,QAAQ,iBAAiB,gBAAgB,YAAY,cAAc;CAE3E,MAAM,EAAE,mBAAmB;AAC3B,QAAO,KAAK,sBAAsB,iBAAiB;CACnD,IAAI,QAAQ,MAAM,OAAO,OAAO,WAAW,cAAc,MAAM,EAC7D,cAAc,gBACf,CAAC;AAEF,sBAAqB,OAAO,iBAAiB,eAAe;AAE5D,QAAO,MAAM,SAAS,aAAa;AACjC,MAAI,aAAa,MAAM,SAAS,WAAW;AACzC,UAAO,KAAK,sCAAsC;AAClD;;EAEF,MAAM,OAAO,MAAM,MAAM;AACzB,SAAO,KAAK,KAAK,KAAK;AACtB,UAAQ,MAAM,KAAK;GAAE;GAAQ;GAAO;GAAiB;GAAgB;GAAY,EAAE,OAAO"}
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 /* 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/revault-sdk",
3
- "version": "0.27.3",
3
+ "version": "0.27.7",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -64,10 +64,11 @@
64
64
  "ts-pattern": "^5.9.0",
65
65
  "uuid": "^14.0.0",
66
66
  "zod": "^4.3.6",
67
- "@ledgerhq/revault-api": "1.64.0"
67
+ "@ledgerhq/revault-api": "1.66.0"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@eslint/js": "^9.39.4",
71
+ "@microsoft/api-extractor": "^7.47.0",
71
72
  "@types/bn.js": "^5.2.0",
72
73
  "@types/elliptic": "^6.4.18",
73
74
  "@types/invariant": "^2.2.37",
@@ -86,6 +87,8 @@
86
87
  "vitest-mock-extended": "^4.0.0"
87
88
  },
88
89
  "scripts": {
90
+ "api:check": "tsx scripts/run-api-extractor.ts",
91
+ "api:extract": "tsx scripts/run-api-extractor.ts",
89
92
  "build": "tsdown",
90
93
  "dev": "tsdown --watch",
91
94
  "lint": "biome check --error-on-warnings",