@learncard/sss-key-manager 0.2.1 → 0.2.3

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 (46) hide show
  1. package/dist/escrow-attestation.d.ts +2 -9
  2. package/dist/escrow-attestation.d.ts.map +1 -1
  3. package/dist/escrow-authority.d.ts +138 -0
  4. package/dist/escrow-authority.d.ts.map +1 -0
  5. package/dist/escrow-authority.types.d.ts +51 -0
  6. package/dist/escrow-authority.types.d.ts.map +1 -0
  7. package/dist/escrow-crypto.d.ts +9 -1
  8. package/dist/escrow-crypto.d.ts.map +1 -1
  9. package/dist/escrow-enrollment-intent.d.ts +13 -0
  10. package/dist/escrow-enrollment-intent.d.ts.map +1 -0
  11. package/dist/escrow-enrollment-intent.types.d.ts +28 -0
  12. package/dist/escrow-enrollment-intent.types.d.ts.map +1 -0
  13. package/dist/escrow-nitro-attestation.d.ts +2 -0
  14. package/dist/escrow-nitro-attestation.d.ts.map +1 -1
  15. package/dist/index.d.ts +8 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/sss-key-manager.cjs.development.js +1652 -214
  18. package/dist/sss-key-manager.cjs.development.js.map +4 -4
  19. package/dist/sss-key-manager.cjs.production.min.js +28 -23
  20. package/dist/sss-key-manager.cjs.production.min.js.map +4 -4
  21. package/dist/sss-key-manager.esm.js +1167 -164
  22. package/dist/sss-key-manager.esm.js.map +4 -4
  23. package/dist/sss-strategy.d.ts +2 -1
  24. package/dist/sss-strategy.d.ts.map +1 -1
  25. package/dist/types.d.ts +21 -1
  26. package/dist/types.d.ts.map +1 -1
  27. package/package.json +2 -2
  28. package/src/__fixtures__/escrow-authority-v1.json +96 -0
  29. package/src/__fixtures__/escrow-carry-contact-contract-v1.json +33 -0
  30. package/src/__fixtures__/escrow-enrollment-intent-v1.json +26 -0
  31. package/src/__fixtures__/nitro-attestation-real/staging-nsm-document.json +16 -0
  32. package/src/escrow-attestation.ts +10 -9
  33. package/src/escrow-authority.test.ts +757 -0
  34. package/src/escrow-authority.ts +671 -0
  35. package/src/escrow-authority.types.ts +56 -0
  36. package/src/escrow-crypto.ts +39 -1
  37. package/src/escrow-enrollment-intent.test.ts +224 -0
  38. package/src/escrow-enrollment-intent.ts +236 -0
  39. package/src/escrow-enrollment-intent.types.ts +28 -0
  40. package/src/escrow-nitro-attestation.test.ts +72 -0
  41. package/src/escrow-nitro-attestation.ts +34 -3
  42. package/src/index.ts +29 -0
  43. package/src/sss-authority.test.ts +889 -0
  44. package/src/sss-strategy.test.ts +32 -0
  45. package/src/sss-strategy.ts +503 -39
  46. package/src/types.ts +27 -3
@@ -205,6 +205,7 @@ var require_types_cjs_development = __commonJS({
205
205
  FlatAuthGrantValidator: /* @__PURE__ */ __name(() => FlatAuthGrantValidator, "FlatAuthGrantValidator"),
206
206
  FrameworkWithSkillsValidator: /* @__PURE__ */ __name(() => FrameworkWithSkillsValidator, "FrameworkWithSkillsValidator"),
207
207
  FullClaimHookValidator: /* @__PURE__ */ __name(() => FullClaimHookValidator, "FullClaimHookValidator"),
208
+ GenerateSkillIconsInputValidator: /* @__PURE__ */ __name(() => GenerateSkillIconsInputValidator, "GenerateSkillIconsInputValidator"),
208
209
  GeoCoordinatesValidator: /* @__PURE__ */ __name(() => GeoCoordinatesValidator, "GeoCoordinatesValidator"),
209
210
  GetCounterEventValidator: /* @__PURE__ */ __name(() => GetCounterEventValidator, "GetCounterEventValidator"),
210
211
  GetCountersEventValidator: /* @__PURE__ */ __name(() => GetCountersEventValidator, "GetCountersEventValidator"),
@@ -365,6 +366,8 @@ var require_types_cjs_development = __commonJS({
365
366
  SHARE_RECOVERY_PROTOCOL: /* @__PURE__ */ __name(() => SHARE_RECOVERY_PROTOCOL, "SHARE_RECOVERY_PROTOCOL"),
366
367
  SHARE_TAG_BYTES: /* @__PURE__ */ __name(() => SHARE_TAG_BYTES, "SHARE_TAG_BYTES"),
367
368
  SHARE_VIEW_RECEIPT_TTL_SECONDS: /* @__PURE__ */ __name(() => SHARE_VIEW_RECEIPT_TTL_SECONDS, "SHARE_VIEW_RECEIPT_TTL_SECONDS"),
369
+ SKILL_ICON_MAX_CHARACTERS_PER_REQUEST: /* @__PURE__ */ __name(() => SKILL_ICON_MAX_CHARACTERS_PER_REQUEST, "SKILL_ICON_MAX_CHARACTERS_PER_REQUEST"),
370
+ SKILL_ICON_MAX_NAMES_PER_REQUEST: /* @__PURE__ */ __name(() => SKILL_ICON_MAX_NAMES_PER_REQUEST, "SKILL_ICON_MAX_NAMES_PER_REQUEST"),
368
371
  SendAiSessionCredentialEventValidator: /* @__PURE__ */ __name(() => SendAiSessionCredentialEventValidator, "SendAiSessionCredentialEventValidator"),
369
372
  SendBoostInputValidator: /* @__PURE__ */ __name(() => SendBoostInputValidator, "SendBoostInputValidator"),
370
373
  SendBoostResponseValidator: /* @__PURE__ */ __name(() => SendBoostResponseValidator, "SendBoostResponseValidator"),
@@ -417,6 +420,7 @@ var require_types_cjs_development = __commonJS({
417
420
  SkillFrameworkQueryValidator: /* @__PURE__ */ __name(() => SkillFrameworkQueryValidator, "SkillFrameworkQueryValidator"),
418
421
  SkillFrameworkStatusEnum: /* @__PURE__ */ __name(() => SkillFrameworkStatusEnum, "SkillFrameworkStatusEnum"),
419
422
  SkillFrameworkValidator: /* @__PURE__ */ __name(() => SkillFrameworkValidator, "SkillFrameworkValidator"),
423
+ SkillIconNamesValidator: /* @__PURE__ */ __name(() => SkillIconNamesValidator, "SkillIconNamesValidator"),
420
424
  SkillQueryValidator: /* @__PURE__ */ __name(() => SkillQueryValidator, "SkillQueryValidator"),
421
425
  SkillSemanticSearchInputValidator: /* @__PURE__ */ __name(() => SkillSemanticSearchInputValidator, "SkillSemanticSearchInputValidator"),
422
426
  SkillSemanticSearchResultItemValidator: /* @__PURE__ */ __name(() => SkillSemanticSearchResultItemValidator, "SkillSemanticSearchResultItemValidator"),
@@ -574,7 +578,7 @@ var require_types_cjs_development = __commonJS({
574
578
  _function: /* @__PURE__ */ __name(() => _function, "_function"),
575
579
  any: /* @__PURE__ */ __name(() => any, "any"),
576
580
  array: /* @__PURE__ */ __name(() => array, "array"),
577
- base64: /* @__PURE__ */ __name(() => base642, "base64"),
581
+ base64: /* @__PURE__ */ __name(() => base6422, "base64"),
578
582
  base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
579
583
  bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
580
584
  boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
@@ -615,7 +619,7 @@ var require_types_cjs_development = __commonJS({
615
619
  gt: /* @__PURE__ */ __name(() => _gt, "gt"),
616
620
  gte: /* @__PURE__ */ __name(() => _gte, "gte"),
617
621
  guid: /* @__PURE__ */ __name(() => guid2, "guid"),
618
- hash: /* @__PURE__ */ __name(() => hash, "hash"),
622
+ hash: /* @__PURE__ */ __name(() => hash2, "hash"),
619
623
  hex: /* @__PURE__ */ __name(() => hex22, "hex"),
620
624
  hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
621
625
  httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
@@ -664,7 +668,7 @@ var require_types_cjs_development = __commonJS({
664
668
  nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
665
669
  nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
666
670
  number: /* @__PURE__ */ __name(() => number2, "number"),
667
- object: /* @__PURE__ */ __name(() => object, "object"),
671
+ object: /* @__PURE__ */ __name(() => object2, "object"),
668
672
  optional: /* @__PURE__ */ __name(() => optional, "optional"),
669
673
  overwrite: /* @__PURE__ */ __name(() => _overwrite, "overwrite"),
670
674
  parse: /* @__PURE__ */ __name(() => parse2, "parse"),
@@ -1003,7 +1007,7 @@ var require_types_cjs_development = __commonJS({
1003
1007
  util: /* @__PURE__ */ __name(() => util_exports, "util"),
1004
1008
  version: /* @__PURE__ */ __name(() => version, "version")
1005
1009
  });
1006
- var _a;
1010
+ var _a2;
1007
1011
  var NEVER = /* @__PURE__ */ Object.freeze({
1008
1012
  status: "aborted"
1009
1013
  });
@@ -1026,9 +1030,9 @@ var require_types_cjs_development = __commonJS({
1026
1030
  inst._zod.traits.add(name);
1027
1031
  initializer3(inst, def);
1028
1032
  const proto = _.prototype;
1029
- const keys = Object.keys(proto);
1030
- for (let i = 0; i < keys.length; i++) {
1031
- const k = keys[i];
1033
+ const keys2 = Object.keys(proto);
1034
+ for (let i = 0; i < keys2.length; i++) {
1035
+ const k = keys2[i];
1032
1036
  if (!(k in inst)) {
1033
1037
  inst[k] = proto[k].bind(inst);
1034
1038
  }
@@ -1095,7 +1099,7 @@ var require_types_cjs_development = __commonJS({
1095
1099
  this.name = "ZodEncodeError";
1096
1100
  }
1097
1101
  };
1098
- (_a = globalThis).__zod_globalConfig ?? (_a.__zod_globalConfig = {});
1102
+ (_a2 = globalThis).__zod_globalConfig ?? (_a2.__zod_globalConfig = {});
1099
1103
  var globalConfig = globalThis.__zod_globalConfig;
1100
1104
  function config(newConfig) {
1101
1105
  if (newConfig)
@@ -1250,9 +1254,9 @@ var require_types_cjs_development = __commonJS({
1250
1254
  __name(floatSafeRemainder, "floatSafeRemainder");
1251
1255
  __name2(floatSafeRemainder, "floatSafeRemainder");
1252
1256
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
1253
- function defineLazy(object2, key, getter) {
1257
+ function defineLazy(object22, key, getter) {
1254
1258
  let value = void 0;
1255
- Object.defineProperty(object2, key, {
1259
+ Object.defineProperty(object22, key, {
1256
1260
  get() {
1257
1261
  if (value === EVALUATING) {
1258
1262
  return void 0;
@@ -1264,7 +1268,7 @@ var require_types_cjs_development = __commonJS({
1264
1268
  return value;
1265
1269
  },
1266
1270
  set(v) {
1267
- Object.defineProperty(object2, key, {
1271
+ Object.defineProperty(object22, key, {
1268
1272
  value: v
1269
1273
  // configurable: true,
1270
1274
  });
@@ -1312,12 +1316,12 @@ var require_types_cjs_development = __commonJS({
1312
1316
  __name(getElementAtPath, "getElementAtPath");
1313
1317
  __name2(getElementAtPath, "getElementAtPath");
1314
1318
  function promiseAllObject(promisesObj) {
1315
- const keys = Object.keys(promisesObj);
1316
- const promises = keys.map((key) => promisesObj[key]);
1319
+ const keys2 = Object.keys(promisesObj);
1320
+ const promises = keys2.map((key) => promisesObj[key]);
1317
1321
  return Promise.all(promises).then((results) => {
1318
1322
  const resolvedObj = {};
1319
- for (let i = 0; i < keys.length; i++) {
1320
- resolvedObj[keys[i]] = results[i];
1323
+ for (let i = 0; i < keys2.length; i++) {
1324
+ resolvedObj[keys2[i]] = results[i];
1321
1325
  }
1322
1326
  return resolvedObj;
1323
1327
  });
@@ -1857,18 +1861,18 @@ var require_types_cjs_development = __commonJS({
1857
1861
  __name2(cleanEnum, "cleanEnum");
1858
1862
  function base64ToUint8Array(base643) {
1859
1863
  const binaryString = atob(base643);
1860
- const bytes2 = new Uint8Array(binaryString.length);
1864
+ const bytes3 = new Uint8Array(binaryString.length);
1861
1865
  for (let i = 0; i < binaryString.length; i++) {
1862
- bytes2[i] = binaryString.charCodeAt(i);
1866
+ bytes3[i] = binaryString.charCodeAt(i);
1863
1867
  }
1864
- return bytes2;
1868
+ return bytes3;
1865
1869
  }
1866
1870
  __name(base64ToUint8Array, "base64ToUint8Array");
1867
1871
  __name2(base64ToUint8Array, "base64ToUint8Array");
1868
- function uint8ArrayToBase64(bytes2) {
1872
+ function uint8ArrayToBase64(bytes3) {
1869
1873
  let binaryString = "";
1870
- for (let i = 0; i < bytes2.length; i++) {
1871
- binaryString += String.fromCharCode(bytes2[i]);
1874
+ for (let i = 0; i < bytes3.length; i++) {
1875
+ binaryString += String.fromCharCode(bytes3[i]);
1872
1876
  }
1873
1877
  return btoa(binaryString);
1874
1878
  }
@@ -1881,8 +1885,8 @@ var require_types_cjs_development = __commonJS({
1881
1885
  }
1882
1886
  __name(base64urlToUint8Array, "base64urlToUint8Array");
1883
1887
  __name2(base64urlToUint8Array, "base64urlToUint8Array");
1884
- function uint8ArrayToBase64url(bytes2) {
1885
- return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1888
+ function uint8ArrayToBase64url(bytes3) {
1889
+ return uint8ArrayToBase64(bytes3).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1886
1890
  }
1887
1891
  __name(uint8ArrayToBase64url, "uint8ArrayToBase64url");
1888
1892
  __name2(uint8ArrayToBase64url, "uint8ArrayToBase64url");
@@ -1891,16 +1895,16 @@ var require_types_cjs_development = __commonJS({
1891
1895
  if (cleanHex.length % 2 !== 0) {
1892
1896
  throw new Error("Invalid hex string length");
1893
1897
  }
1894
- const bytes2 = new Uint8Array(cleanHex.length / 2);
1898
+ const bytes3 = new Uint8Array(cleanHex.length / 2);
1895
1899
  for (let i = 0; i < cleanHex.length; i += 2) {
1896
- bytes2[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1900
+ bytes3[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1897
1901
  }
1898
- return bytes2;
1902
+ return bytes3;
1899
1903
  }
1900
1904
  __name(hexToUint8Array, "hexToUint8Array");
1901
1905
  __name2(hexToUint8Array, "hexToUint8Array");
1902
- function uint8ArrayToHex(bytes2) {
1903
- return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
1906
+ function uint8ArrayToHex(bytes3) {
1907
+ return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
1904
1908
  }
1905
1909
  __name(uint8ArrayToHex, "uint8ArrayToHex");
1906
1910
  __name2(uint8ArrayToHex, "uint8ArrayToHex");
@@ -2149,7 +2153,7 @@ var require_types_cjs_development = __commonJS({
2149
2153
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
2150
2154
  var regexes_exports = {};
2151
2155
  __export2(regexes_exports, {
2152
- base64: /* @__PURE__ */ __name(() => base64, "base64"),
2156
+ base64: /* @__PURE__ */ __name(() => base642, "base64"),
2153
2157
  base64url: /* @__PURE__ */ __name(() => base64url, "base64url"),
2154
2158
  bigint: /* @__PURE__ */ __name(() => bigint, "bigint"),
2155
2159
  boolean: /* @__PURE__ */ __name(() => boolean, "boolean"),
@@ -2172,7 +2176,7 @@ var require_types_cjs_development = __commonJS({
2172
2176
  html5Email: /* @__PURE__ */ __name(() => html5Email, "html5Email"),
2173
2177
  httpProtocol: /* @__PURE__ */ __name(() => httpProtocol, "httpProtocol"),
2174
2178
  idnEmail: /* @__PURE__ */ __name(() => idnEmail, "idnEmail"),
2175
- integer: /* @__PURE__ */ __name(() => integer, "integer"),
2179
+ integer: /* @__PURE__ */ __name(() => integer3, "integer"),
2176
2180
  ipv4: /* @__PURE__ */ __name(() => ipv4, "ipv4"),
2177
2181
  ipv6: /* @__PURE__ */ __name(() => ipv6, "ipv6"),
2178
2182
  ksuid: /* @__PURE__ */ __name(() => ksuid, "ksuid"),
@@ -2246,7 +2250,7 @@ var require_types_cjs_development = __commonJS({
2246
2250
  }, "mac");
2247
2251
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
2248
2252
  var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
2249
- var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
2253
+ var base642 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
2250
2254
  var base64url = /^[A-Za-z0-9_-]*$/;
2251
2255
  var hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
2252
2256
  var domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
@@ -2283,7 +2287,7 @@ var require_types_cjs_development = __commonJS({
2283
2287
  return new RegExp(`^${regex}$`);
2284
2288
  }, "string");
2285
2289
  var bigint = /^-?\d+n?$/;
2286
- var integer = /^-?\d+$/;
2290
+ var integer3 = /^-?\d+$/;
2287
2291
  var number = /^-?\d+(?:\.\d+)?$/;
2288
2292
  var boolean = /^(?:true|false)$/i;
2289
2293
  var _null = /^null$/i;
@@ -2417,7 +2421,7 @@ var require_types_cjs_development = __commonJS({
2417
2421
  bag.minimum = minimum;
2418
2422
  bag.maximum = maximum;
2419
2423
  if (isInt)
2420
- bag.pattern = integer;
2424
+ bag.pattern = integer3;
2421
2425
  });
2422
2426
  inst._zod.check = (payload) => {
2423
2427
  const input = payload.value;
@@ -3257,7 +3261,7 @@ var require_types_cjs_development = __commonJS({
3257
3261
  __name(isValidBase64, "isValidBase64");
3258
3262
  __name2(isValidBase64, "isValidBase64");
3259
3263
  var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
3260
- def.pattern ?? (def.pattern = base64);
3264
+ def.pattern ?? (def.pattern = base642);
3261
3265
  $ZodStringFormat.init(inst, def);
3262
3266
  inst._zod.bag.contentEncoding = "base64";
3263
3267
  inst._zod.check = (payload) => {
@@ -3603,8 +3607,8 @@ var require_types_cjs_development = __commonJS({
3603
3607
  __name(handlePropertyResult, "handlePropertyResult");
3604
3608
  __name2(handlePropertyResult, "handlePropertyResult");
3605
3609
  function normalizeDef(def) {
3606
- const keys = Object.keys(def.shape);
3607
- for (const k of keys) {
3610
+ const keys2 = Object.keys(def.shape);
3611
+ for (const k of keys2) {
3608
3612
  if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
3609
3613
  throw new Error(`Invalid element at key "${k}": expected a Zod schema`);
3610
3614
  }
@@ -3612,9 +3616,9 @@ var require_types_cjs_development = __commonJS({
3612
3616
  const okeys = optionalKeys(def.shape);
3613
3617
  return {
3614
3618
  ...def,
3615
- keys,
3616
- keySet: new Set(keys),
3617
- numKeys: keys.length,
3619
+ keys: keys2,
3620
+ keySet: new Set(keys2),
3621
+ numKeys: keys2.length,
3618
3622
  optionalKeys: new Set(okeys)
3619
3623
  };
3620
3624
  }
@@ -8376,8 +8380,8 @@ var require_types_cjs_development = __commonJS({
8376
8380
  }
8377
8381
  __name(ko_default, "ko_default");
8378
8382
  __name2(ko_default, "default");
8379
- var capitalizeFirstCharacter = /* @__PURE__ */ __name2((text) => {
8380
- return text.charAt(0).toUpperCase() + text.slice(1);
8383
+ var capitalizeFirstCharacter = /* @__PURE__ */ __name2((text2) => {
8384
+ return text2.charAt(0).toUpperCase() + text2.slice(1);
8381
8385
  }, "capitalizeFirstCharacter");
8382
8386
  function getUnitTypeFromNumber(number4) {
8383
8387
  const abs = Math.abs(number4);
@@ -11109,7 +11113,7 @@ var require_types_cjs_development = __commonJS({
11109
11113
  }
11110
11114
  __name(yo_default, "yo_default");
11111
11115
  __name2(yo_default, "default");
11112
- var _a2;
11116
+ var _a22;
11113
11117
  var $output = /* @__PURE__ */ Symbol("ZodOutput");
11114
11118
  var $input = /* @__PURE__ */ Symbol("ZodInput");
11115
11119
  var $ZodRegistry = class {
@@ -11163,7 +11167,7 @@ var require_types_cjs_development = __commonJS({
11163
11167
  }
11164
11168
  __name(registry, "registry");
11165
11169
  __name2(registry, "registry");
11166
- (_a2 = globalThis).__zod_globalRegistry ?? (_a2.__zod_globalRegistry = registry());
11170
+ (_a22 = globalThis).__zod_globalRegistry ?? (_a22.__zod_globalRegistry = registry());
11167
11171
  var globalRegistry = globalThis.__zod_globalRegistry;
11168
11172
  // @__NO_SIDE_EFFECTS__
11169
11173
  function _string(Class2, params) {
@@ -13497,7 +13501,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13497
13501
  _function: /* @__PURE__ */ __name(() => _function, "_function"),
13498
13502
  any: /* @__PURE__ */ __name(() => any, "any"),
13499
13503
  array: /* @__PURE__ */ __name(() => array, "array"),
13500
- base64: /* @__PURE__ */ __name(() => base642, "base64"),
13504
+ base64: /* @__PURE__ */ __name(() => base6422, "base64"),
13501
13505
  base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
13502
13506
  bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
13503
13507
  boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
@@ -13522,7 +13526,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13522
13526
  float64: /* @__PURE__ */ __name(() => float64, "float64"),
13523
13527
  function: /* @__PURE__ */ __name(() => _function, "function"),
13524
13528
  guid: /* @__PURE__ */ __name(() => guid2, "guid"),
13525
- hash: /* @__PURE__ */ __name(() => hash, "hash"),
13529
+ hash: /* @__PURE__ */ __name(() => hash2, "hash"),
13526
13530
  hex: /* @__PURE__ */ __name(() => hex22, "hex"),
13527
13531
  hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
13528
13532
  httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
@@ -13554,7 +13558,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13554
13558
  nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
13555
13559
  nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
13556
13560
  number: /* @__PURE__ */ __name(() => number2, "number"),
13557
- object: /* @__PURE__ */ __name(() => object, "object"),
13561
+ object: /* @__PURE__ */ __name(() => object2, "object"),
13558
13562
  optional: /* @__PURE__ */ __name(() => optional, "optional"),
13559
13563
  partialRecord: /* @__PURE__ */ __name(() => partialRecord, "partialRecord"),
13560
13564
  pipe: /* @__PURE__ */ __name(() => pipe, "pipe"),
@@ -14155,11 +14159,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14155
14159
  $ZodBase64.init(inst, def);
14156
14160
  ZodStringFormat.init(inst, def);
14157
14161
  });
14158
- function base642(params) {
14162
+ function base6422(params) {
14159
14163
  return /* @__PURE__ */ _base64(ZodBase64, params);
14160
14164
  }
14161
- __name(base642, "base642");
14162
- __name2(base642, "base64");
14165
+ __name(base6422, "base642");
14166
+ __name2(base6422, "base64");
14163
14167
  var ZodBase64URL = /* @__PURE__ */ $constructor("ZodBase64URL", (inst, def) => {
14164
14168
  $ZodBase64URL.init(inst, def);
14165
14169
  ZodStringFormat.init(inst, def);
@@ -14206,7 +14210,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14206
14210
  }
14207
14211
  __name(hex22, "hex2");
14208
14212
  __name2(hex22, "hex");
14209
- function hash(alg, params) {
14213
+ function hash2(alg, params) {
14210
14214
  const enc = params?.enc ?? "hex";
14211
14215
  const format = `${alg}_${enc}`;
14212
14216
  const regex = regexes_exports[format];
@@ -14214,8 +14218,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14214
14218
  throw new Error(`Unrecognized hash format: ${format}`);
14215
14219
  return /* @__PURE__ */ _stringFormat(ZodCustomStringFormat, format, regex, params);
14216
14220
  }
14217
- __name(hash, "hash");
14218
- __name2(hash, "hash");
14221
+ __name(hash2, "hash");
14222
+ __name2(hash2, "hash");
14219
14223
  var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
14220
14224
  $ZodNumber.init(inst, def);
14221
14225
  ZodType.init(inst, def);
@@ -14527,7 +14531,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14527
14531
  }
14528
14532
  });
14529
14533
  });
14530
- function object(shape, params) {
14534
+ function object2(shape, params) {
14531
14535
  const def = {
14532
14536
  type: "object",
14533
14537
  shape: shape ?? {},
@@ -14535,8 +14539,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14535
14539
  };
14536
14540
  return new ZodObject(def);
14537
14541
  }
14538
- __name(object, "object");
14539
- __name2(object, "object");
14542
+ __name(object2, "object");
14543
+ __name2(object2, "object");
14540
14544
  function strictObject(shape, params) {
14541
14545
  return new ZodObject({
14542
14546
  type: "object",
@@ -14731,11 +14735,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14731
14735
  inst._zod.processJSONSchema = (ctx, json2, params) => enumProcessor(inst, ctx, json2, params);
14732
14736
  inst.enum = def.entries;
14733
14737
  inst.options = Object.values(def.entries);
14734
- const keys = new Set(Object.keys(def.entries));
14738
+ const keys2 = new Set(Object.keys(def.entries));
14735
14739
  inst.extract = (values, params) => {
14736
14740
  const newEntries = {};
14737
14741
  for (const value of values) {
14738
- if (keys.has(value)) {
14742
+ if (keys2.has(value)) {
14739
14743
  newEntries[value] = def.entries[value];
14740
14744
  } else
14741
14745
  throw new Error(`Key ${value} not found in enum`);
@@ -14750,7 +14754,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14750
14754
  inst.exclude = (values, params) => {
14751
14755
  const newEntries = { ...def.entries };
14752
14756
  for (const value of values) {
14753
- if (keys.has(value)) {
14757
+ if (keys2.has(value)) {
14754
14758
  delete newEntries[value];
14755
14759
  } else
14756
14760
  throw new Error(`Key ${value} not found in enum`);
@@ -15886,7 +15890,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15886
15890
  verificationMethod: external_exports.string(),
15887
15891
  jws: external_exports.string().optional()
15888
15892
  }).catchall(external_exports.any()).superRefine((proof, ctx) => {
15889
- if (proof.created === void 0 && (proof.type !== "DataIntegrityProof" || proof.cryptosuite !== "ecdsa-rdfc-2019")) {
15893
+ if (proof.created === void 0 && // These standardized Data Integrity suites make created optional.
15894
+ // Keep the prior requirement for legacy and unknown proof suites.
15895
+ // https://www.w3.org/TR/vc-di-eddsa/#proof-configuration-eddsa-jcs-2022
15896
+ // https://www.w3.org/TR/vc-di-bbs/#proof-configuration
15897
+ (proof.type !== "DataIntegrityProof" || ![
15898
+ "ecdsa-rdfc-2019",
15899
+ "ecdsa-jcs-2019",
15900
+ "ecdsa-sd-2023",
15901
+ "eddsa-rdfc-2022",
15902
+ "eddsa-jcs-2022",
15903
+ "bbs-2023"
15904
+ ].includes(proof.cryptosuite))) {
15890
15905
  ctx.addIssue({
15891
15906
  code: "custom",
15892
15907
  path: ["created"],
@@ -16143,6 +16158,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16143
16158
  term: external_exports.string().optional()
16144
16159
  }).catchall(external_exports.any());
16145
16160
  var UnsignedAchievementCredentialValidator = UnsignedVCValidator.extend({
16161
+ awardedDate: external_exports.string().optional(),
16146
16162
  name: external_exports.string().optional(),
16147
16163
  description: external_exports.string().optional(),
16148
16164
  image: ImageValidator.optional(),
@@ -18525,12 +18541,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18525
18541
  }
18526
18542
  return table;
18527
18543
  })();
18528
- var encodeBase64Url = /* @__PURE__ */ __name2((bytes2) => {
18544
+ var encodeBase64Url = /* @__PURE__ */ __name2((bytes3) => {
18529
18545
  let output = "";
18530
- for (let index = 0; index < bytes2.length; index += 3) {
18531
- const first = bytes2[index];
18532
- const second = bytes2[index + 1];
18533
- const third = bytes2[index + 2];
18546
+ for (let index = 0; index < bytes3.length; index += 3) {
18547
+ const first = bytes3[index];
18548
+ const second = bytes3[index + 1];
18549
+ const third = bytes3[index + 2];
18534
18550
  output += BASE64URL_ALPHABET[first >> 2];
18535
18551
  output += BASE64URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
18536
18552
  if (second === void 0) break;
@@ -18571,8 +18587,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18571
18587
  }, "isCanonicalBase64Url");
18572
18588
  var decodedBase64UrlByteLength = /* @__PURE__ */ __name2((value) => decodeBase64Url(value)?.length ?? null, "decodedBase64UrlByteLength");
18573
18589
  var utf8ByteLength = /* @__PURE__ */ __name2((value) => new TextEncoder().encode(value).length, "utf8ByteLength");
18574
- var canonicalBase64Url = /* @__PURE__ */ __name2((bytes2) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes2), {
18575
- message: `must be canonical base64url for exactly ${bytes2} bytes`
18590
+ var canonicalBase64Url = /* @__PURE__ */ __name2((bytes3) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes3), {
18591
+ message: `must be canonical base64url for exactly ${bytes3} bytes`
18576
18592
  }), "canonicalBase64Url");
18577
18593
  var ShareLinkIdValidator = canonicalBase64Url(SHARE_LINK_ID_BYTES);
18578
18594
  var ShareContentKeyValidator = canonicalBase64Url(SHARE_CONTENT_KEY_BYTES);
@@ -18999,6 +19015,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18999
19015
  contentUrl: external_exports.string(),
19000
19016
  receipt: external_exports.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/)
19001
19017
  }).strict();
19018
+ var SKILL_ICON_MAX_NAMES_PER_REQUEST = 100;
19019
+ var SKILL_ICON_MAX_CHARACTERS_PER_REQUEST = 2500;
19020
+ var SkillIconNamesValidator = external_exports.array(external_exports.string().nonempty()).min(1).max(SKILL_ICON_MAX_NAMES_PER_REQUEST, {
19021
+ message: `A maximum of ${SKILL_ICON_MAX_NAMES_PER_REQUEST} skill names can be sent per request`
19022
+ }).refine(
19023
+ (names) => names.reduce((total, name) => total + name.length, 0) <= SKILL_ICON_MAX_CHARACTERS_PER_REQUEST,
19024
+ {
19025
+ message: `Skill names may total at most ${SKILL_ICON_MAX_CHARACTERS_PER_REQUEST} characters per request`
19026
+ }
19027
+ );
19028
+ var GenerateSkillIconsInputValidator = external_exports.object({ names: SkillIconNamesValidator });
19002
19029
  }
19003
19030
  });
19004
19031
 
@@ -19025,9 +19052,11 @@ __export(index_exports, {
19025
19052
  ESCROW_ALGORITHM: () => ESCROW_ALGORITHM,
19026
19053
  ESCROW_BLOB_INFO: () => ESCROW_BLOB_INFO,
19027
19054
  ESCROW_CLIENT_KEY_ID: () => ESCROW_CLIENT_KEY_ID,
19055
+ ESCROW_ENROLLMENT_INTENT_DOMAIN: () => ESCROW_ENROLLMENT_INTENT_DOMAIN,
19028
19056
  ESCROW_ENVELOPE_VERSION: () => ESCROW_ENVELOPE_VERSION,
19029
19057
  ESCROW_PIN_MAX_ATTEMPTS: () => ESCROW_PIN_MAX_ATTEMPTS,
19030
19058
  ESCROW_RELEASE_INFO: () => ESCROW_RELEASE_INFO,
19059
+ EscrowEvidenceError: () => EscrowEvidenceError,
19031
19060
  EscrowHoldRestartThrottledError: () => EscrowHoldRestartThrottledError,
19032
19061
  EscrowPinLockedError: () => EscrowPinLockedError,
19033
19062
  EscrowPinMismatchError: () => EscrowPinMismatchError,
@@ -19055,6 +19084,7 @@ __export(index_exports, {
19055
19084
  constantTimeEqualHex: () => constantTimeEqualHex,
19056
19085
  countWords: () => countWords,
19057
19086
  createAdaptiveStorage: () => createAdaptiveStorage,
19087
+ createEscrowEnrollmentIntent: () => createEscrowEnrollmentIntent,
19058
19088
  createPasskeyCredential: () => createPasskeyCredential,
19059
19089
  createQrLoginSession: () => createQrLoginSession,
19060
19090
  createSSSKeyManager: () => createSSSKeyManager,
@@ -19068,6 +19098,7 @@ __export(index_exports, {
19068
19098
  deriveKeyFromPasskey: () => deriveKeyFromPasskey,
19069
19099
  deriveKeyFromPassword: () => deriveKeyFromPassword,
19070
19100
  derivePinProof: () => derivePinProof,
19101
+ encodeEscrowEnrollmentIntent: () => encodeEscrowEnrollmentIntent,
19071
19102
  encryptEmailRelayPayload: () => encryptEmailRelayPayload,
19072
19103
  encryptEscrowBlob: () => encryptEscrowBlob,
19073
19104
  encryptShareForTransfer: () => encryptShareForTransfer,
@@ -19080,6 +19111,7 @@ __export(index_exports, {
19080
19111
  generatePinSalt: () => generatePinSalt,
19081
19112
  generateRecoveryPhrase: () => generateRecoveryPhrase,
19082
19113
  getDeviceShare: () => getDeviceShare,
19114
+ getEscrowBlobIdentity: () => getEscrowBlobIdentity,
19083
19115
  getQrLoginSessionInfo: () => getQrLoginSessionInfo,
19084
19116
  getShareVersion: () => getShareVersion,
19085
19117
  hasDeviceShare: () => hasDeviceShare,
@@ -19101,9 +19133,11 @@ __export(index_exports, {
19101
19133
  reconstructFromShares: () => reconstructFromShares,
19102
19134
  reconstructPrivateKey: () => reconstructPrivateKey,
19103
19135
  recoveryPhraseToShare: () => recoveryPhraseToShare,
19136
+ resolveEscrowEnrollmentAction: () => resolveEscrowEnrollmentAction,
19104
19137
  sealEscrowRelease: () => sealEscrowRelease,
19105
19138
  setPublicComputerMode: () => setPublicComputerMode,
19106
19139
  shareToRecoveryPhrase: () => shareToRecoveryPhrase,
19140
+ signEscrowEnrollmentIntent: () => signEscrowEnrollmentIntent,
19107
19141
  splitAndVerify: () => splitAndVerify,
19108
19142
  splitPrivateKey: () => splitPrivateKey,
19109
19143
  storeDeviceShare: () => storeDeviceShare,
@@ -19111,8 +19145,13 @@ __export(index_exports, {
19111
19145
  validatePin: () => validatePin,
19112
19146
  validateRecoveryPhrase: () => validateRecoveryPhrase,
19113
19147
  verifyEnclaveAttestation: () => verifyEnclaveAttestation,
19148
+ verifyEscrowAuthorityState: () => verifyEscrowAuthorityState,
19149
+ verifyEscrowCodeDelivery: () => verifyEscrowCodeDelivery,
19150
+ verifyEscrowEnrollmentCommit: () => verifyEscrowEnrollmentCommit,
19151
+ verifyEscrowHoldState: () => verifyEscrowHoldState,
19114
19152
  verifyNitroAttestationDocument: () => verifyNitroAttestationDocument,
19115
- verifyStoredShares: () => verifyStoredShares
19153
+ verifyStoredShares: () => verifyStoredShares,
19154
+ violatesCarryContactRule: () => violatesCarryContactRule
19116
19155
  });
19117
19156
  module.exports = __toCommonJS(index_exports);
19118
19157
 
@@ -19273,37 +19312,37 @@ var DEFAULT_KDF_PARAMS = {
19273
19312
  parallelism: ARGON2_PARALLELISM
19274
19313
  };
19275
19314
  function bufferToBase64(buf) {
19276
- const bytes2 = new Uint8Array(buf);
19315
+ const bytes3 = new Uint8Array(buf);
19277
19316
  let binary = "";
19278
- for (let i = 0; i < bytes2.byteLength; i++) {
19279
- binary += String.fromCharCode(bytes2[i]);
19317
+ for (let i = 0; i < bytes3.byteLength; i++) {
19318
+ binary += String.fromCharCode(bytes3[i]);
19280
19319
  }
19281
19320
  return btoa(binary);
19282
19321
  }
19283
19322
  __name(bufferToBase64, "bufferToBase64");
19284
19323
  function base64ToBuffer(b64) {
19285
19324
  const binary = atob(b64);
19286
- const bytes2 = new Uint8Array(binary.length);
19325
+ const bytes3 = new Uint8Array(binary.length);
19287
19326
  for (let i = 0; i < binary.length; i++) {
19288
- bytes2[i] = binary.charCodeAt(i);
19327
+ bytes3[i] = binary.charCodeAt(i);
19289
19328
  }
19290
- return bytes2;
19329
+ return bytes3;
19291
19330
  }
19292
19331
  __name(base64ToBuffer, "base64ToBuffer");
19293
19332
  function hexToBytes(hex2) {
19294
- const bytes2 = new Uint8Array(hex2.length / 2);
19333
+ const bytes3 = new Uint8Array(hex2.length / 2);
19295
19334
  for (let i = 0; i < hex2.length; i += 2) {
19296
- bytes2[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
19335
+ bytes3[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
19297
19336
  }
19298
- return bytes2;
19337
+ return bytes3;
19299
19338
  }
19300
19339
  __name(hexToBytes, "hexToBytes");
19301
- function bytesToHex(bytes2) {
19302
- return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
19340
+ function bytesToHex(bytes3) {
19341
+ return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
19303
19342
  }
19304
19343
  __name(bytesToHex, "bytesToHex");
19305
19344
  async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS) {
19306
- const hash = await (0, import_hash_wasm.argon2id)({
19345
+ const hash2 = await (0, import_hash_wasm.argon2id)({
19307
19346
  password,
19308
19347
  salt,
19309
19348
  iterations: params.timeCost,
@@ -19312,7 +19351,7 @@ async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS
19312
19351
  hashLength: ARGON2_HASH_LENGTH,
19313
19352
  outputType: "binary"
19314
19353
  });
19315
- return Uint8Array.from(hash);
19354
+ return Uint8Array.from(hash2);
19316
19355
  }
19317
19356
  __name(deriveKeyFromPassword, "deriveKeyFromPassword");
19318
19357
  async function encryptWithPassword(plaintext, password) {
@@ -19466,21 +19505,21 @@ async function getOrCreateMasterKey() {
19466
19505
  }
19467
19506
  __name(getOrCreateMasterKey, "getOrCreateMasterKey");
19468
19507
  function bufferToBase642(buf) {
19469
- const bytes2 = new Uint8Array(buf);
19508
+ const bytes3 = new Uint8Array(buf);
19470
19509
  let binary = "";
19471
- for (let i = 0; i < bytes2.byteLength; i++) {
19472
- binary += String.fromCharCode(bytes2[i]);
19510
+ for (let i = 0; i < bytes3.byteLength; i++) {
19511
+ binary += String.fromCharCode(bytes3[i]);
19473
19512
  }
19474
19513
  return btoa(binary);
19475
19514
  }
19476
19515
  __name(bufferToBase642, "bufferToBase64");
19477
19516
  function base64ToBuffer2(b64) {
19478
19517
  const binary = atob(b64);
19479
- const bytes2 = new Uint8Array(binary.length);
19518
+ const bytes3 = new Uint8Array(binary.length);
19480
19519
  for (let i = 0; i < binary.length; i++) {
19481
- bytes2[i] = binary.charCodeAt(i);
19520
+ bytes3[i] = binary.charCodeAt(i);
19482
19521
  }
19483
- return bytes2.buffer;
19522
+ return bytes3.buffer;
19484
19523
  }
19485
19524
  __name(base64ToBuffer2, "base64ToBuffer");
19486
19525
  async function encryptShare(share, id) {
@@ -19888,21 +19927,21 @@ async function getWordlist() {
19888
19927
  return wordlistPromise;
19889
19928
  }
19890
19929
  __name(getWordlist, "getWordlist");
19891
- function bytesToBits(bytes2) {
19892
- return Array.from(bytes2).map((b) => b.toString(2).padStart(8, "0")).join("");
19930
+ function bytesToBits(bytes3) {
19931
+ return Array.from(bytes3).map((b) => b.toString(2).padStart(8, "0")).join("");
19893
19932
  }
19894
19933
  __name(bytesToBits, "bytesToBits");
19895
19934
  function bitsToBytes(bits) {
19896
- const bytes2 = new Uint8Array(Math.ceil(bits.length / 8));
19897
- for (let i = 0; i < bytes2.length; i++) {
19898
- bytes2[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, "0"), 2);
19935
+ const bytes3 = new Uint8Array(Math.ceil(bits.length / 8));
19936
+ for (let i = 0; i < bytes3.length; i++) {
19937
+ bytes3[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, "0"), 2);
19899
19938
  }
19900
- return bytes2;
19939
+ return bytes3;
19901
19940
  }
19902
19941
  __name(bitsToBytes, "bitsToBytes");
19903
19942
  async function computeChecksum(data) {
19904
- const hash = await crypto.subtle.digest("SHA-256", data);
19905
- const hashBits = bytesToBits(new Uint8Array(hash));
19943
+ const hash2 = await crypto.subtle.digest("SHA-256", data);
19944
+ const hashBits = bytesToBits(new Uint8Array(hash2));
19906
19945
  const checksumLength = Math.floor(data.length / 4);
19907
19946
  return hashBits.slice(0, checksumLength);
19908
19947
  }
@@ -19935,12 +19974,12 @@ async function recoveryPhraseToShare(phrase) {
19935
19974
  bits += index.toString(2).padStart(11, "0");
19936
19975
  }
19937
19976
  let dataByteCount = 0;
19938
- for (let bytes2 = 1; bytes2 <= 64; bytes2++) {
19939
- const checksumBits2 = Math.floor(bytes2 / 4);
19940
- const totalBits = bytes2 * 8 + checksumBits2;
19977
+ for (let bytes3 = 1; bytes3 <= 64; bytes3++) {
19978
+ const checksumBits2 = Math.floor(bytes3 / 4);
19979
+ const totalBits = bytes3 * 8 + checksumBits2;
19941
19980
  const wordsNeeded = Math.ceil(totalBits / 11);
19942
19981
  if (wordsNeeded === words.length) {
19943
- dataByteCount = bytes2;
19982
+ dataByteCount = bytes3;
19944
19983
  } else if (wordsNeeded > words.length) {
19945
19984
  break;
19946
19985
  }
@@ -20234,9 +20273,9 @@ __name(createSSSKeyManager, "createSSSKeyManager");
20234
20273
  var EMAIL_RELAY_ENVELOPE_VERSION = 1;
20235
20274
  var EMAIL_RELAY_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
20236
20275
  var encodeUtf8 = /* @__PURE__ */ __name((value) => {
20237
- const bytes2 = new TextEncoder().encode(value);
20238
- const copy = new Uint8Array(new ArrayBuffer(bytes2.byteLength));
20239
- copy.set(bytes2);
20276
+ const bytes3 = new TextEncoder().encode(value);
20277
+ const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
20278
+ copy.set(bytes3);
20240
20279
  return copy;
20241
20280
  }, "encodeUtf8");
20242
20281
  var EMAIL_RELAY_INFO = encodeUtf8("learncard-email-relay-v1");
@@ -20255,7 +20294,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
20255
20294
  if (value === void 0) return void 0;
20256
20295
  if (!isRecord(value)) throw new Error("Invalid email relay branding");
20257
20296
  const branding = {};
20258
- const keys = [
20297
+ const keys2 = [
20259
20298
  "brandName",
20260
20299
  "logoUrl",
20261
20300
  "logoAlt",
@@ -20267,7 +20306,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
20267
20306
  "fromDomain",
20268
20307
  "copyrightHolder"
20269
20308
  ];
20270
- for (const key of keys) {
20309
+ for (const key of keys2) {
20271
20310
  const field = value[key];
20272
20311
  if (field === void 0) continue;
20273
20312
  if (typeof field !== "string" || field.length > 2048) {
@@ -20320,7 +20359,7 @@ var parseEmailRelayPlaintext = /* @__PURE__ */ __name((value) => {
20320
20359
  branding: parseBranding(value.branding)
20321
20360
  };
20322
20361
  }, "parseEmailRelayPlaintext");
20323
- var getAad = /* @__PURE__ */ __name((envelope) => encodeUtf8(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
20362
+ var getAad = /* @__PURE__ */ __name((envelope2) => encodeUtf8(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
20324
20363
  var deriveAesKey = /* @__PURE__ */ __name(async (sharedSecret, salt, usage) => {
20325
20364
  const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
20326
20365
  "deriveKey"
@@ -20392,7 +20431,7 @@ var encryptEmailRelayPayload = /* @__PURE__ */ __name(async (input, publicKeyBas
20392
20431
  };
20393
20432
  }, "encryptEmailRelayPayload");
20394
20433
  var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBase64) => {
20395
- const envelope = parseEmailRelayEnvelope(value);
20434
+ const envelope2 = parseEmailRelayEnvelope(value);
20396
20435
  const privateKey = await crypto.subtle.importKey(
20397
20436
  "pkcs8",
20398
20437
  base64ToBuffer(privateKeyBase64.trim()).buffer,
@@ -20402,7 +20441,7 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
20402
20441
  );
20403
20442
  const ephemeralPublicKey = await crypto.subtle.importKey(
20404
20443
  "raw",
20405
- base64ToBuffer(envelope.ephemeralPublicKey).buffer,
20444
+ base64ToBuffer(envelope2.ephemeralPublicKey).buffer,
20406
20445
  { name: "ECDH", namedCurve: "P-256" },
20407
20446
  false,
20408
20447
  []
@@ -20412,13 +20451,13 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
20412
20451
  privateKey,
20413
20452
  256
20414
20453
  );
20415
- const salt = base64ToBuffer(envelope.salt);
20416
- const iv = base64ToBuffer(envelope.iv);
20454
+ const salt = base64ToBuffer(envelope2.salt);
20455
+ const iv = base64ToBuffer(envelope2.iv);
20417
20456
  const aesKey = await deriveAesKey(sharedSecret, salt, "decrypt");
20418
20457
  const decrypted = await crypto.subtle.decrypt(
20419
- { name: "AES-GCM", iv, additionalData: getAad(envelope) },
20458
+ { name: "AES-GCM", iv, additionalData: getAad(envelope2) },
20420
20459
  aesKey,
20421
- base64ToBuffer(envelope.ciphertext)
20460
+ base64ToBuffer(envelope2.ciphertext)
20422
20461
  );
20423
20462
  const parsed = JSON.parse(new TextDecoder().decode(decrypted));
20424
20463
  return parseEmailRelayPlaintext(parsed);
@@ -20430,10 +20469,11 @@ var ESCROW_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
20430
20469
  var ESCROW_BLOB_INFO = "learncard-escrow-blob-v1";
20431
20470
  var ESCROW_RELEASE_INFO = "learncard-escrow-release-v1";
20432
20471
  var ESCROW_CLIENT_KEY_ID = "client";
20472
+ var RECOVERY_LANGUAGES = ["en", "es", "fr", "ar"];
20433
20473
  var encodeUtf82 = /* @__PURE__ */ __name((value) => {
20434
- const bytes2 = new TextEncoder().encode(value);
20435
- const copy = new Uint8Array(new ArrayBuffer(bytes2.byteLength));
20436
- copy.set(bytes2);
20474
+ const bytes3 = new TextEncoder().encode(value);
20475
+ const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
20476
+ copy.set(bytes3);
20437
20477
  return copy;
20438
20478
  }, "encodeUtf8");
20439
20479
  var isRecord2 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
@@ -20469,6 +20509,22 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
20469
20509
  if (typeof value.shareVersion !== "number" || !Number.isInteger(value.shareVersion) || value.shareVersion <= 0) {
20470
20510
  throw new Error("Invalid escrow shareVersion");
20471
20511
  }
20512
+ if (value.recoveryEmail !== void 0 !== (value.recoveryLanguage !== void 0)) {
20513
+ throw new Error("Invalid escrow recoveryEmail");
20514
+ }
20515
+ let recoveryContact = {};
20516
+ if (value.recoveryEmail !== void 0) {
20517
+ const email = requireString2(value, "recoveryEmail", { min: 3, max: 254 }).trim().toLowerCase();
20518
+ const at = email.split("@");
20519
+ if (!/^[\x21-\x7e]+$/.test(email) || at.length !== 2 || at[0].length === 0 || at[1].length === 0 || !at[1].includes(".") || at[1].startsWith(".") || at[1].endsWith(".")) {
20520
+ throw new Error("Invalid escrow recoveryEmail");
20521
+ }
20522
+ const language = requireString2(value, "recoveryLanguage", { min: 2, max: 2 });
20523
+ if (!RECOVERY_LANGUAGES.includes(language)) {
20524
+ throw new Error("Invalid escrow recoveryLanguage");
20525
+ }
20526
+ recoveryContact = { recoveryEmail: email, recoveryLanguage: language };
20527
+ }
20472
20528
  return {
20473
20529
  version: ESCROW_ENVELOPE_VERSION,
20474
20530
  recoveryShare: requireString2(value, "recoveryShare", {
@@ -20484,7 +20540,8 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
20484
20540
  max: 64,
20485
20541
  pattern: /^[0-9a-f]{64}$/i
20486
20542
  }).toLowerCase()
20487
- } : {}
20543
+ } : {},
20544
+ ...recoveryContact
20488
20545
  };
20489
20546
  }, "parseEscrowBlobPlaintext");
20490
20547
  var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
@@ -20495,7 +20552,7 @@ var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
20495
20552
  holdId: requireString2(value, "holdId", { max: 128, pattern: /^[A-Za-z0-9._-]+$/ })
20496
20553
  };
20497
20554
  }, "parseEscrowReleasePlaintext");
20498
- var getAad2 = /* @__PURE__ */ __name((envelope) => encodeUtf82(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
20555
+ var getAad2 = /* @__PURE__ */ __name((envelope2) => encodeUtf82(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
20499
20556
  var deriveAesKey2 = /* @__PURE__ */ __name(async (sharedSecret, salt, usage, info) => {
20500
20557
  const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
20501
20558
  "deriveKey"
@@ -20566,7 +20623,7 @@ var encryptToRecipient = /* @__PURE__ */ __name(async (plaintextJson, spki, keyI
20566
20623
  };
20567
20624
  }, "encryptToRecipient");
20568
20625
  var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20569
- const envelope = parseEscrowEnvelope(value);
20626
+ const envelope2 = parseEscrowEnvelope(value);
20570
20627
  const privateKey = await crypto.subtle.importKey(
20571
20628
  "pkcs8",
20572
20629
  base64ToBuffer(pkcs8.trim()),
@@ -20576,7 +20633,7 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20576
20633
  );
20577
20634
  const ephemeralPublicKey = await crypto.subtle.importKey(
20578
20635
  "raw",
20579
- base64ToBuffer(envelope.ephemeralPublicKey),
20636
+ base64ToBuffer(envelope2.ephemeralPublicKey),
20580
20637
  { name: "ECDH", namedCurve: "P-256" },
20581
20638
  false,
20582
20639
  []
@@ -20586,13 +20643,13 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20586
20643
  privateKey,
20587
20644
  256
20588
20645
  );
20589
- const salt = base64ToBuffer(envelope.salt);
20590
- const iv = base64ToBuffer(envelope.iv);
20646
+ const salt = base64ToBuffer(envelope2.salt);
20647
+ const iv = base64ToBuffer(envelope2.iv);
20591
20648
  const aesKey = await deriveAesKey2(sharedSecret, salt, "decrypt", info);
20592
20649
  const decrypted = await crypto.subtle.decrypt(
20593
- { name: "AES-GCM", iv, additionalData: getAad2(envelope) },
20650
+ { name: "AES-GCM", iv, additionalData: getAad2(envelope2) },
20594
20651
  aesKey,
20595
- base64ToBuffer(envelope.ciphertext)
20652
+ base64ToBuffer(envelope2.ciphertext)
20596
20653
  );
20597
20654
  const parsed = JSON.parse(new TextDecoder().decode(decrypted));
20598
20655
  return parsed;
@@ -20606,8 +20663,8 @@ var encryptEscrowBlob = /* @__PURE__ */ __name(async (input, enclavePublicKeySpk
20606
20663
  ESCROW_BLOB_INFO
20607
20664
  );
20608
20665
  }, "encryptEscrowBlob");
20609
- var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
20610
- await decryptFromEnvelope(envelope, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
20666
+ var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope2, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
20667
+ await decryptFromEnvelope(envelope2, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
20611
20668
  ), "decryptEscrowBlob");
20612
20669
  var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPublicKeySpkiB64) => {
20613
20670
  const plaintext = parseEscrowReleasePlaintext({ ...input, version: ESCROW_ENVELOPE_VERSION });
@@ -20618,10 +20675,626 @@ var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPubl
20618
20675
  ESCROW_RELEASE_INFO
20619
20676
  );
20620
20677
  }, "sealEscrowRelease");
20621
- var openEscrowRelease = /* @__PURE__ */ __name(async (envelope, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
20622
- await decryptFromEnvelope(envelope, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
20678
+ var openEscrowRelease = /* @__PURE__ */ __name(async (envelope2, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
20679
+ await decryptFromEnvelope(envelope2, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
20623
20680
  ), "openEscrowRelease");
20624
20681
 
20682
+ // ../../node_modules/@noble/ed25519/index.js
20683
+ var ed25519_CURVE = {
20684
+ p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
20685
+ n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
20686
+ h: 8n,
20687
+ a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
20688
+ d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
20689
+ Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
20690
+ Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n
20691
+ };
20692
+ var { p: P, n: N, Gx, Gy, a: _a, d: _d } = ed25519_CURVE;
20693
+ var h = 8n;
20694
+ var L = 32;
20695
+ var L2 = 64;
20696
+ var err = /* @__PURE__ */ __name((m = "") => {
20697
+ throw new Error(m);
20698
+ }, "err");
20699
+ var isBig = /* @__PURE__ */ __name((n) => typeof n === "bigint", "isBig");
20700
+ var isStr = /* @__PURE__ */ __name((s) => typeof s === "string", "isStr");
20701
+ var isBytes = /* @__PURE__ */ __name((a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array", "isBytes");
20702
+ var abytes = /* @__PURE__ */ __name((a, l) => !isBytes(a) || typeof l === "number" && l > 0 && a.length !== l ? err("Uint8Array expected") : a, "abytes");
20703
+ var u8n = /* @__PURE__ */ __name((len) => new Uint8Array(len), "u8n");
20704
+ var u8fr = /* @__PURE__ */ __name((buf) => Uint8Array.from(buf), "u8fr");
20705
+ var padh = /* @__PURE__ */ __name((n, pad) => n.toString(16).padStart(pad, "0"), "padh");
20706
+ var bytesToHex3 = /* @__PURE__ */ __name((b) => Array.from(abytes(b)).map((e) => padh(e, 2)).join(""), "bytesToHex");
20707
+ var C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
20708
+ var _ch = /* @__PURE__ */ __name((ch) => {
20709
+ if (ch >= C._0 && ch <= C._9)
20710
+ return ch - C._0;
20711
+ if (ch >= C.A && ch <= C.F)
20712
+ return ch - (C.A - 10);
20713
+ if (ch >= C.a && ch <= C.f)
20714
+ return ch - (C.a - 10);
20715
+ return;
20716
+ }, "_ch");
20717
+ var hexToBytes3 = /* @__PURE__ */ __name((hex2) => {
20718
+ const e = "hex invalid";
20719
+ if (!isStr(hex2))
20720
+ return err(e);
20721
+ const hl = hex2.length;
20722
+ const al = hl / 2;
20723
+ if (hl % 2)
20724
+ return err(e);
20725
+ const array = u8n(al);
20726
+ for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
20727
+ const n1 = _ch(hex2.charCodeAt(hi));
20728
+ const n2 = _ch(hex2.charCodeAt(hi + 1));
20729
+ if (n1 === void 0 || n2 === void 0)
20730
+ return err(e);
20731
+ array[ai] = n1 * 16 + n2;
20732
+ }
20733
+ return array;
20734
+ }, "hexToBytes");
20735
+ var toU8 = /* @__PURE__ */ __name((a, len) => abytes(isStr(a) ? hexToBytes3(a) : u8fr(abytes(a)), len), "toU8");
20736
+ var cr = /* @__PURE__ */ __name(() => globalThis?.crypto, "cr");
20737
+ var subtle = /* @__PURE__ */ __name(() => cr()?.subtle ?? err("crypto.subtle must be defined"), "subtle");
20738
+ var concatBytes = /* @__PURE__ */ __name((...arrs) => {
20739
+ const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0));
20740
+ let pad = 0;
20741
+ arrs.forEach((a) => {
20742
+ r.set(a, pad);
20743
+ pad += a.length;
20744
+ });
20745
+ return r;
20746
+ }, "concatBytes");
20747
+ var randomBytes = /* @__PURE__ */ __name((len = L) => {
20748
+ const c = cr();
20749
+ return c.getRandomValues(u8n(len));
20750
+ }, "randomBytes");
20751
+ var big = BigInt;
20752
+ var arange = /* @__PURE__ */ __name((n, min, max, msg = "bad number: out of range") => isBig(n) && min <= n && n < max ? n : err(msg), "arange");
20753
+ var M = /* @__PURE__ */ __name((a, b = P) => {
20754
+ const r = a % b;
20755
+ return r >= 0n ? r : b + r;
20756
+ }, "M");
20757
+ var modN = /* @__PURE__ */ __name((a) => M(a, N), "modN");
20758
+ var invert = /* @__PURE__ */ __name((num, md) => {
20759
+ if (num === 0n || md <= 0n)
20760
+ err("no inverse n=" + num + " mod=" + md);
20761
+ let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
20762
+ while (a !== 0n) {
20763
+ const q = b / a, r = b % a;
20764
+ const m = x - u * q, n = y - v * q;
20765
+ b = a, a = r, x = u, y = v, u = m, v = n;
20766
+ }
20767
+ return b === 1n ? M(x, md) : err("no inverse");
20768
+ }, "invert");
20769
+ var apoint = /* @__PURE__ */ __name((p) => p instanceof Point ? p : err("Point expected"), "apoint");
20770
+ var B256 = 2n ** 256n;
20771
+ var Point = class _Point {
20772
+ static {
20773
+ __name(this, "Point");
20774
+ }
20775
+ static BASE;
20776
+ static ZERO;
20777
+ ex;
20778
+ ey;
20779
+ ez;
20780
+ et;
20781
+ constructor(ex, ey, ez, et) {
20782
+ const max = B256;
20783
+ this.ex = arange(ex, 0n, max);
20784
+ this.ey = arange(ey, 0n, max);
20785
+ this.ez = arange(ez, 1n, max);
20786
+ this.et = arange(et, 0n, max);
20787
+ Object.freeze(this);
20788
+ }
20789
+ static fromAffine(p) {
20790
+ return new _Point(p.x, p.y, 1n, M(p.x * p.y));
20791
+ }
20792
+ /** RFC8032 5.1.3: Uint8Array to Point. */
20793
+ static fromBytes(hex2, zip215 = false) {
20794
+ const d = _d;
20795
+ const normed = u8fr(abytes(hex2, L));
20796
+ const lastByte = hex2[31];
20797
+ normed[31] = lastByte & ~128;
20798
+ const y = bytesToNumLE(normed);
20799
+ const max = zip215 ? B256 : P;
20800
+ arange(y, 0n, max);
20801
+ const y2 = M(y * y);
20802
+ const u = M(y2 - 1n);
20803
+ const v = M(d * y2 + 1n);
20804
+ let { isValid, value: x } = uvRatio(u, v);
20805
+ if (!isValid)
20806
+ err("bad point: y not sqrt");
20807
+ const isXOdd = (x & 1n) === 1n;
20808
+ const isLastByteOdd = (lastByte & 128) !== 0;
20809
+ if (!zip215 && x === 0n && isLastByteOdd)
20810
+ err("bad point: x==0, isLastByteOdd");
20811
+ if (isLastByteOdd !== isXOdd)
20812
+ x = M(-x);
20813
+ return new _Point(x, y, 1n, M(x * y));
20814
+ }
20815
+ /** Checks if the point is valid and on-curve. */
20816
+ assertValidity() {
20817
+ const a = _a;
20818
+ const d = _d;
20819
+ const p = this;
20820
+ if (p.is0())
20821
+ throw new Error("bad point: ZERO");
20822
+ const { ex: X, ey: Y, ez: Z, et: T } = p;
20823
+ const X2 = M(X * X);
20824
+ const Y2 = M(Y * Y);
20825
+ const Z2 = M(Z * Z);
20826
+ const Z4 = M(Z2 * Z2);
20827
+ const aX2 = M(X2 * a);
20828
+ const left = M(Z2 * M(aX2 + Y2));
20829
+ const right = M(Z4 + M(d * M(X2 * Y2)));
20830
+ if (left !== right)
20831
+ throw new Error("bad point: equation left != right (1)");
20832
+ const XY = M(X * Y);
20833
+ const ZT = M(Z * T);
20834
+ if (XY !== ZT)
20835
+ throw new Error("bad point: equation left != right (2)");
20836
+ return this;
20837
+ }
20838
+ /** Equality check: compare points P&Q. */
20839
+ equals(other) {
20840
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
20841
+ const { ex: X2, ey: Y2, ez: Z2 } = apoint(other);
20842
+ const X1Z2 = M(X1 * Z2);
20843
+ const X2Z1 = M(X2 * Z1);
20844
+ const Y1Z2 = M(Y1 * Z2);
20845
+ const Y2Z1 = M(Y2 * Z1);
20846
+ return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
20847
+ }
20848
+ is0() {
20849
+ return this.equals(I);
20850
+ }
20851
+ /** Flip point over y coordinate. */
20852
+ negate() {
20853
+ return new _Point(M(-this.ex), this.ey, this.ez, M(-this.et));
20854
+ }
20855
+ /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */
20856
+ double() {
20857
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
20858
+ const a = _a;
20859
+ const A = M(X1 * X1);
20860
+ const B = M(Y1 * Y1);
20861
+ const C2 = M(2n * M(Z1 * Z1));
20862
+ const D = M(a * A);
20863
+ const x1y1 = X1 + Y1;
20864
+ const E = M(M(x1y1 * x1y1) - A - B);
20865
+ const G2 = D + B;
20866
+ const F = G2 - C2;
20867
+ const H = D - B;
20868
+ const X3 = M(E * F);
20869
+ const Y3 = M(G2 * H);
20870
+ const T3 = M(E * H);
20871
+ const Z3 = M(F * G2);
20872
+ return new _Point(X3, Y3, Z3, T3);
20873
+ }
20874
+ /** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */
20875
+ add(other) {
20876
+ const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;
20877
+ const { ex: X2, ey: Y2, ez: Z2, et: T2 } = apoint(other);
20878
+ const a = _a;
20879
+ const d = _d;
20880
+ const A = M(X1 * X2);
20881
+ const B = M(Y1 * Y2);
20882
+ const C2 = M(T1 * d * T2);
20883
+ const D = M(Z1 * Z2);
20884
+ const E = M((X1 + Y1) * (X2 + Y2) - A - B);
20885
+ const F = M(D - C2);
20886
+ const G2 = M(D + C2);
20887
+ const H = M(B - a * A);
20888
+ const X3 = M(E * F);
20889
+ const Y3 = M(G2 * H);
20890
+ const T3 = M(E * H);
20891
+ const Z3 = M(F * G2);
20892
+ return new _Point(X3, Y3, Z3, T3);
20893
+ }
20894
+ /**
20895
+ * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
20896
+ * Uses {@link wNAF} for base point.
20897
+ * Uses fake point to mitigate side-channel leakage.
20898
+ * @param n scalar by which point is multiplied
20899
+ * @param safe safe mode guards against timing attacks; unsafe mode is faster
20900
+ */
20901
+ multiply(n, safe = true) {
20902
+ if (!safe && (n === 0n || this.is0()))
20903
+ return I;
20904
+ arange(n, 1n, N);
20905
+ if (n === 1n)
20906
+ return this;
20907
+ if (this.equals(G))
20908
+ return wNAF(n).p;
20909
+ let p = I;
20910
+ let f = G;
20911
+ for (let d = this; n > 0n; d = d.double(), n >>= 1n) {
20912
+ if (n & 1n)
20913
+ p = p.add(d);
20914
+ else if (safe)
20915
+ f = f.add(d);
20916
+ }
20917
+ return p;
20918
+ }
20919
+ /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
20920
+ toAffine() {
20921
+ const { ex: x, ey: y, ez: z } = this;
20922
+ if (this.equals(I))
20923
+ return { x: 0n, y: 1n };
20924
+ const iz = invert(z, P);
20925
+ if (M(z * iz) !== 1n)
20926
+ err("invalid inverse");
20927
+ return { x: M(x * iz), y: M(y * iz) };
20928
+ }
20929
+ toBytes() {
20930
+ const { x, y } = this.assertValidity().toAffine();
20931
+ const b = numTo32bLE(y);
20932
+ b[31] |= x & 1n ? 128 : 0;
20933
+ return b;
20934
+ }
20935
+ toHex() {
20936
+ return bytesToHex3(this.toBytes());
20937
+ }
20938
+ // encode to hex string
20939
+ clearCofactor() {
20940
+ return this.multiply(big(h), false);
20941
+ }
20942
+ isSmallOrder() {
20943
+ return this.clearCofactor().is0();
20944
+ }
20945
+ isTorsionFree() {
20946
+ let p = this.multiply(N / 2n, false).double();
20947
+ if (N % 2n)
20948
+ p = p.add(this);
20949
+ return p.is0();
20950
+ }
20951
+ static fromHex(hex2, zip215) {
20952
+ return _Point.fromBytes(toU8(hex2), zip215);
20953
+ }
20954
+ get x() {
20955
+ return this.toAffine().x;
20956
+ }
20957
+ get y() {
20958
+ return this.toAffine().y;
20959
+ }
20960
+ toRawBytes() {
20961
+ return this.toBytes();
20962
+ }
20963
+ };
20964
+ var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
20965
+ var I = new Point(0n, 1n, 1n, 0n);
20966
+ Point.BASE = G;
20967
+ Point.ZERO = I;
20968
+ var numTo32bLE = /* @__PURE__ */ __name((num) => hexToBytes3(padh(arange(num, 0n, B256), L2)).reverse(), "numTo32bLE");
20969
+ var bytesToNumLE = /* @__PURE__ */ __name((b) => big("0x" + bytesToHex3(u8fr(abytes(b)).reverse())), "bytesToNumLE");
20970
+ var pow2 = /* @__PURE__ */ __name((x, power) => {
20971
+ let r = x;
20972
+ while (power-- > 0n) {
20973
+ r *= r;
20974
+ r %= P;
20975
+ }
20976
+ return r;
20977
+ }, "pow2");
20978
+ var pow_2_252_3 = /* @__PURE__ */ __name((x) => {
20979
+ const x2 = x * x % P;
20980
+ const b2 = x2 * x % P;
20981
+ const b4 = pow2(b2, 2n) * b2 % P;
20982
+ const b5 = pow2(b4, 1n) * x % P;
20983
+ const b10 = pow2(b5, 5n) * b5 % P;
20984
+ const b20 = pow2(b10, 10n) * b10 % P;
20985
+ const b40 = pow2(b20, 20n) * b20 % P;
20986
+ const b80 = pow2(b40, 40n) * b40 % P;
20987
+ const b160 = pow2(b80, 80n) * b80 % P;
20988
+ const b240 = pow2(b160, 80n) * b80 % P;
20989
+ const b250 = pow2(b240, 10n) * b10 % P;
20990
+ const pow_p_5_8 = pow2(b250, 2n) * x % P;
20991
+ return { pow_p_5_8, b2 };
20992
+ }, "pow_2_252_3");
20993
+ var RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n;
20994
+ var uvRatio = /* @__PURE__ */ __name((u, v) => {
20995
+ const v3 = M(v * v * v);
20996
+ const v7 = M(v3 * v3 * v);
20997
+ const pow = pow_2_252_3(u * v7).pow_p_5_8;
20998
+ let x = M(u * v3 * pow);
20999
+ const vx2 = M(v * x * x);
21000
+ const root1 = x;
21001
+ const root2 = M(x * RM1);
21002
+ const useRoot1 = vx2 === u;
21003
+ const useRoot2 = vx2 === M(-u);
21004
+ const noRoot = vx2 === M(-u * RM1);
21005
+ if (useRoot1)
21006
+ x = root1;
21007
+ if (useRoot2 || noRoot)
21008
+ x = root2;
21009
+ if ((M(x) & 1n) === 1n)
21010
+ x = M(-x);
21011
+ return { isValid: useRoot1 || useRoot2, value: x };
21012
+ }, "uvRatio");
21013
+ var modL_LE = /* @__PURE__ */ __name((hash2) => modN(bytesToNumLE(hash2)), "modL_LE");
21014
+ var sha512a = /* @__PURE__ */ __name((...m) => etc.sha512Async(...m), "sha512a");
21015
+ var hash2extK = /* @__PURE__ */ __name((hashed) => {
21016
+ const head = hashed.slice(0, L);
21017
+ head[0] &= 248;
21018
+ head[31] &= 127;
21019
+ head[31] |= 64;
21020
+ const prefix = hashed.slice(L, L2);
21021
+ const scalar = modL_LE(head);
21022
+ const point = G.multiply(scalar);
21023
+ const pointBytes = point.toBytes();
21024
+ return { head, prefix, scalar, point, pointBytes };
21025
+ }, "hash2extK");
21026
+ var getExtendedPublicKeyAsync = /* @__PURE__ */ __name((priv) => sha512a(toU8(priv, L)).then(hash2extK), "getExtendedPublicKeyAsync");
21027
+ var getPublicKeyAsync = /* @__PURE__ */ __name((priv) => getExtendedPublicKeyAsync(priv).then((p) => p.pointBytes), "getPublicKeyAsync");
21028
+ var hashFinishA = /* @__PURE__ */ __name((res) => sha512a(res.hashable).then(res.finish), "hashFinishA");
21029
+ var _sign = /* @__PURE__ */ __name((e, rBytes, msg) => {
21030
+ const { pointBytes: P2, scalar: s } = e;
21031
+ const r = modL_LE(rBytes);
21032
+ const R = G.multiply(r).toBytes();
21033
+ const hashable = concatBytes(R, P2, msg);
21034
+ const finish = /* @__PURE__ */ __name((hashed) => {
21035
+ const S = modN(r + modL_LE(hashed) * s);
21036
+ return abytes(concatBytes(R, numTo32bLE(S)), L2);
21037
+ }, "finish");
21038
+ return { hashable, finish };
21039
+ }, "_sign");
21040
+ var signAsync = /* @__PURE__ */ __name(async (msg, privKey) => {
21041
+ const m = toU8(msg);
21042
+ const e = await getExtendedPublicKeyAsync(privKey);
21043
+ const rBytes = await sha512a(e.prefix, m);
21044
+ return hashFinishA(_sign(e, rBytes, m));
21045
+ }, "signAsync");
21046
+ var etc = {
21047
+ sha512Async: /* @__PURE__ */ __name(async (...messages) => {
21048
+ const s = subtle();
21049
+ const m = concatBytes(...messages);
21050
+ return u8n(await s.digest("SHA-512", m.buffer));
21051
+ }, "sha512Async"),
21052
+ sha512Sync: void 0,
21053
+ bytesToHex: bytesToHex3,
21054
+ hexToBytes: hexToBytes3,
21055
+ concatBytes,
21056
+ mod: M,
21057
+ invert,
21058
+ randomBytes
21059
+ };
21060
+ var W = 8;
21061
+ var scalarBits = 256;
21062
+ var pwindows = Math.ceil(scalarBits / W) + 1;
21063
+ var pwindowSize = 2 ** (W - 1);
21064
+ var precompute = /* @__PURE__ */ __name(() => {
21065
+ const points = [];
21066
+ let p = G;
21067
+ let b = p;
21068
+ for (let w = 0; w < pwindows; w++) {
21069
+ b = p;
21070
+ points.push(b);
21071
+ for (let i = 1; i < pwindowSize; i++) {
21072
+ b = b.add(p);
21073
+ points.push(b);
21074
+ }
21075
+ p = b.double();
21076
+ }
21077
+ return points;
21078
+ }, "precompute");
21079
+ var Gpows = void 0;
21080
+ var ctneg = /* @__PURE__ */ __name((cnd, p) => {
21081
+ const n = p.negate();
21082
+ return cnd ? n : p;
21083
+ }, "ctneg");
21084
+ var wNAF = /* @__PURE__ */ __name((n) => {
21085
+ const comp = Gpows || (Gpows = precompute());
21086
+ let p = I;
21087
+ let f = G;
21088
+ const pow_2_w = 2 ** W;
21089
+ const maxNum = pow_2_w;
21090
+ const mask = big(pow_2_w - 1);
21091
+ const shiftBy = big(W);
21092
+ for (let w = 0; w < pwindows; w++) {
21093
+ let wbits = Number(n & mask);
21094
+ n >>= shiftBy;
21095
+ if (wbits > pwindowSize) {
21096
+ wbits -= maxNum;
21097
+ n += 1n;
21098
+ }
21099
+ const off = w * pwindowSize;
21100
+ const offF = off;
21101
+ const offP = off + Math.abs(wbits) - 1;
21102
+ const isEven = w % 2 !== 0;
21103
+ const isNeg = wbits < 0;
21104
+ if (wbits === 0) {
21105
+ f = f.add(ctneg(isEven, comp[offF]));
21106
+ } else {
21107
+ p = p.add(ctneg(isNeg, comp[offP]));
21108
+ }
21109
+ }
21110
+ return { p, f };
21111
+ }, "wNAF");
21112
+
21113
+ // src/escrow-enrollment-intent.ts
21114
+ var ESCROW_ENROLLMENT_INTENT_DOMAIN = "learncard-escrow-enrollment-intent-v2\0";
21115
+ var BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
21116
+ var FIELDS = [
21117
+ "version",
21118
+ "tenant",
21119
+ "did",
21120
+ "authorityGeneration",
21121
+ "expectedEnrollmentVersion",
21122
+ "action",
21123
+ "sourceBlobIdentity",
21124
+ "targetBlobIdentity",
21125
+ "pinAction",
21126
+ "shareVersion",
21127
+ "enrollmentEpoch",
21128
+ "requestId",
21129
+ "allowRewrap",
21130
+ "recoveryEmail",
21131
+ "recoveryLanguage"
21132
+ ];
21133
+ var ACTIONS = ["enroll", "replace", "disable", "carry"];
21134
+ var PIN_ACTIONS = ["set", "change", "clear", "keep"];
21135
+ var RECOVERY_LANGUAGES2 = ["en", "es", "fr", "ar"];
21136
+ var requireIntent = /* @__PURE__ */ __name((condition) => {
21137
+ if (!condition) throw new Error("Invalid escrow enrollment intent");
21138
+ }, "requireIntent");
21139
+ var matches = /* @__PURE__ */ __name((value, pattern) => typeof value === "string" && pattern.exec(value)?.[0] === value, "matches");
21140
+ var utf8 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
21141
+ var integer = /* @__PURE__ */ __name((value, width) => {
21142
+ requireIntent(
21143
+ Number.isSafeInteger(value) && value >= 0 && (width === 8 || value <= 4294967295)
21144
+ );
21145
+ const bytes3 = new Uint8Array(width);
21146
+ const view = new DataView(bytes3.buffer);
21147
+ if (width === 4) view.setUint32(0, value, false);
21148
+ else view.setBigUint64(0, BigInt(value), false);
21149
+ return bytes3;
21150
+ }, "integer");
21151
+ var join = /* @__PURE__ */ __name((fields) => {
21152
+ const result = new Uint8Array(fields.reduce((length, field) => length + field.length, 0));
21153
+ let offset = 0;
21154
+ for (const field of fields) {
21155
+ result.set(field, offset);
21156
+ offset += field.length;
21157
+ }
21158
+ return result;
21159
+ }, "join");
21160
+ var hashBytes = /* @__PURE__ */ __name((value) => {
21161
+ if (value === null) return new Uint8Array();
21162
+ requireIntent(matches(value, /^[0-9a-f]{64}$/));
21163
+ return new Uint8Array(hexToBytes(value));
21164
+ }, "hashBytes");
21165
+ var didPublicKey = /* @__PURE__ */ __name((did) => {
21166
+ requireIntent(typeof did === "string" && did.startsWith("did:key:z") && did.length === 56);
21167
+ let value = 0n;
21168
+ for (const char of did.slice(9)) {
21169
+ const digit = BASE58.indexOf(char);
21170
+ requireIntent(digit >= 0);
21171
+ value = value * 58n + BigInt(digit);
21172
+ }
21173
+ const bytes3 = new Uint8Array(34);
21174
+ for (let i = 33; i >= 0; i--) {
21175
+ bytes3[i] = Number(value & 255n);
21176
+ value >>= 8n;
21177
+ }
21178
+ requireIntent(value === 0n && bytes3[0] === 237 && bytes3[1] === 1);
21179
+ const key = bytes3.slice(2);
21180
+ try {
21181
+ requireIntent(!Point.fromHex(key, false).isSmallOrder());
21182
+ } catch {
21183
+ throw new Error("Invalid escrow enrollment intent");
21184
+ }
21185
+ return key;
21186
+ }, "didPublicKey");
21187
+ var encodeEscrowEnrollmentIntent = /* @__PURE__ */ __name((intent) => {
21188
+ requireIntent(typeof intent === "object" && intent !== null && !Array.isArray(intent));
21189
+ requireIntent(
21190
+ Object.keys(intent).length === FIELDS.length && FIELDS.every((field) => Object.prototype.hasOwnProperty.call(intent, field))
21191
+ );
21192
+ requireIntent(intent.version === 2 && typeof intent.allowRewrap === "boolean");
21193
+ requireIntent(matches(intent.tenant, /^[A-Za-z0-9_-]{1,128}$/));
21194
+ requireIntent(matches(intent.authorityGeneration, /^[A-Za-z0-9_-]{1,128}$/));
21195
+ requireIntent(matches(intent.requestId, /^[A-Za-z0-9._-]{1,112}$/));
21196
+ didPublicKey(intent.did);
21197
+ const action = ACTIONS.indexOf(intent.action);
21198
+ const pin = PIN_ACTIONS.indexOf(intent.pinAction);
21199
+ requireIntent(action >= 0 && pin >= 0 && intent.shareVersion > 0 && intent.enrollmentEpoch > 0);
21200
+ const source = hashBytes(intent.sourceBlobIdentity);
21201
+ const target = hashBytes(intent.targetBlobIdentity);
21202
+ if (intent.action === "enroll") requireIntent(source.length === 0 && target.length === 32);
21203
+ else if (intent.action === "disable")
21204
+ requireIntent(
21205
+ source.length === 32 && target.length === 0 && intent.pinAction === "keep" && !intent.allowRewrap
21206
+ );
21207
+ else
21208
+ requireIntent(
21209
+ source.length === 32 && target.length === 32 && intent.sourceBlobIdentity !== intent.targetBlobIdentity
21210
+ );
21211
+ if (intent.action === "carry") requireIntent(intent.pinAction === "keep");
21212
+ if (intent.recoveryEmail === null) {
21213
+ requireIntent(
21214
+ intent.recoveryLanguage === null && (intent.action === "disable" || intent.action === "carry")
21215
+ );
21216
+ } else {
21217
+ requireIntent(intent.action === "enroll" || intent.action === "replace");
21218
+ requireIntent(
21219
+ matches(intent.recoveryEmail, /^[\x21-\x7e]{3,254}$/) && intent.recoveryEmail === intent.recoveryEmail.trim().toLowerCase()
21220
+ );
21221
+ const at = intent.recoveryEmail.split("@");
21222
+ requireIntent(
21223
+ at.length === 2 && at[0].length > 0 && at[1].length > 0 && at[1].includes(".") && !at[1].startsWith(".") && !at[1].endsWith(".")
21224
+ );
21225
+ requireIntent(
21226
+ intent.recoveryLanguage !== null && RECOVERY_LANGUAGES2.includes(intent.recoveryLanguage)
21227
+ );
21228
+ }
21229
+ const fields = [
21230
+ integer(intent.version, 4),
21231
+ utf8(intent.tenant),
21232
+ utf8(intent.did),
21233
+ utf8(intent.authorityGeneration),
21234
+ integer(intent.expectedEnrollmentVersion, 8),
21235
+ Uint8Array.of(action),
21236
+ source,
21237
+ target,
21238
+ Uint8Array.of(pin),
21239
+ integer(intent.shareVersion, 4),
21240
+ integer(intent.enrollmentEpoch, 8),
21241
+ utf8(intent.requestId),
21242
+ Uint8Array.of(Number(intent.allowRewrap)),
21243
+ intent.recoveryEmail === null ? new Uint8Array() : utf8(intent.recoveryEmail),
21244
+ intent.recoveryLanguage === null ? new Uint8Array() : utf8(intent.recoveryLanguage)
21245
+ ];
21246
+ return join([
21247
+ utf8(ESCROW_ENROLLMENT_INTENT_DOMAIN),
21248
+ ...fields.flatMap((field) => [integer(field.length, 4), field])
21249
+ ]);
21250
+ }, "encodeEscrowEnrollmentIntent");
21251
+ var signEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (intent, privateKey) => {
21252
+ encodeEscrowEnrollmentIntent(intent);
21253
+ const snapshot = { ...intent };
21254
+ const message = encodeEscrowEnrollmentIntent(snapshot);
21255
+ requireIntent(matches(privateKey, /^[0-9a-f]{64}$/i));
21256
+ const seed = hexToBytes(privateKey);
21257
+ try {
21258
+ const publicKey = await getPublicKeyAsync(seed);
21259
+ const expected = didPublicKey(snapshot.did);
21260
+ requireIntent(publicKey.every((byte, index) => byte === expected[index]));
21261
+ const signature = await signAsync(message, seed);
21262
+ return { intent: snapshot, signature: bufferToBase64(new Uint8Array(signature).buffer) };
21263
+ } finally {
21264
+ seed.fill(0);
21265
+ }
21266
+ }, "signEscrowEnrollmentIntent");
21267
+ var getEscrowBlobIdentity = /* @__PURE__ */ __name(async (input) => {
21268
+ const envelope2 = parseEscrowEnvelope(input);
21269
+ const decode2 = /* @__PURE__ */ __name((value) => {
21270
+ const bytes3 = new Uint8Array(base64ToBuffer(value));
21271
+ requireIntent(bufferToBase64(bytes3.buffer) === value);
21272
+ return bytes3;
21273
+ }, "decode");
21274
+ const point = decode2(envelope2.ephemeralPublicKey);
21275
+ const salt = decode2(envelope2.salt);
21276
+ const iv = decode2(envelope2.iv);
21277
+ const ciphertext = decode2(envelope2.ciphertext);
21278
+ requireIntent(
21279
+ point.length === 65 && point[0] === 4 && salt.length === 32 && iv.length === 12 && ciphertext.length >= 16
21280
+ );
21281
+ await crypto.subtle.importKey("raw", point, { name: "ECDH", namedCurve: "P-256" }, false, []);
21282
+ const fields = [
21283
+ Uint8Array.of(1),
21284
+ utf8(envelope2.algorithm),
21285
+ utf8(envelope2.keyId),
21286
+ point.slice(1, 33),
21287
+ salt,
21288
+ iv,
21289
+ ciphertext
21290
+ ];
21291
+ const message = join([
21292
+ utf8("learncard-escrow-blob-id-v1\0"),
21293
+ ...fields.flatMap((field) => [integer(field.length, 8), field])
21294
+ ]);
21295
+ return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", message)));
21296
+ }, "getEscrowBlobIdentity");
21297
+
20625
21298
  // src/escrow-nitro-attestation.ts
20626
21299
  var import_reflect_metadata = require("reflect-metadata");
20627
21300
 
@@ -20819,11 +21492,11 @@ var slice = useBuffer ? (
20819
21492
  * @param {number} end
20820
21493
  */
20821
21494
  // Buffer.slice() returns a view, not a copy, so we need special handling
20822
- (bytes2, start, end) => {
20823
- if (isBuffer(bytes2)) {
20824
- return new Uint8Array(bytes2.subarray(start, end));
21495
+ (bytes3, start, end) => {
21496
+ if (isBuffer(bytes3)) {
21497
+ return new Uint8Array(bytes3.subarray(start, end));
20825
21498
  }
20826
- return bytes2.slice(start, end);
21499
+ return bytes3.slice(start, end);
20827
21500
  }
20828
21501
  ) : (
20829
21502
  // eslint-disable-line operator-linebreak
@@ -20832,8 +21505,8 @@ var slice = useBuffer ? (
20832
21505
  * @param {number} start
20833
21506
  * @param {number} end
20834
21507
  */
20835
- (bytes2, start, end) => {
20836
- return bytes2.slice(start, end);
21508
+ (bytes3, start, end) => {
21509
+ return bytes3.slice(start, end);
20837
21510
  }
20838
21511
  );
20839
21512
  var concat = useBuffer ? (
@@ -20982,12 +21655,12 @@ var Bl = class {
20982
21655
  /**
20983
21656
  * @param {ByteView|number[]} bytes
20984
21657
  */
20985
- push(bytes2) {
21658
+ push(bytes3) {
20986
21659
  let topChunk = this.chunks[this.chunks.length - 1];
20987
- const newMax = this.cursor + bytes2.length;
21660
+ const newMax = this.cursor + bytes3.length;
20988
21661
  if (newMax <= this.maxCursor + 1) {
20989
21662
  const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
20990
- topChunk.set(bytes2, chunkPos);
21663
+ topChunk.set(bytes3, chunkPos);
20991
21664
  } else {
20992
21665
  if (topChunk) {
20993
21666
  const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
@@ -20996,20 +21669,20 @@ var Bl = class {
20996
21669
  this.maxCursor = this.cursor - 1;
20997
21670
  }
20998
21671
  }
20999
- if (bytes2.length < 64 && bytes2.length < this.chunkSize) {
21672
+ if (bytes3.length < 64 && bytes3.length < this.chunkSize) {
21000
21673
  topChunk = alloc(this.chunkSize);
21001
21674
  this.chunks.push(topChunk);
21002
21675
  this.maxCursor += topChunk.length;
21003
21676
  if (this._initReuseChunk === null) {
21004
21677
  this._initReuseChunk = topChunk;
21005
21678
  }
21006
- topChunk.set(bytes2, 0);
21679
+ topChunk.set(bytes3, 0);
21007
21680
  } else {
21008
- this.chunks.push(bytes2);
21009
- this.maxCursor += bytes2.length;
21681
+ this.chunks.push(bytes3);
21682
+ this.maxCursor += bytes3.length;
21010
21683
  }
21011
21684
  }
21012
- this.cursor += bytes2.length;
21685
+ this.cursor += bytes3.length;
21013
21686
  }
21014
21687
  /**
21015
21688
  * @param {boolean} [reset]
@@ -21062,12 +21735,12 @@ var U8Bl = class {
21062
21735
  /**
21063
21736
  * @param {ByteView|number[]} bytes
21064
21737
  */
21065
- push(bytes2) {
21066
- if (this.cursor + bytes2.length > this.dest.length) {
21738
+ push(bytes3) {
21739
+ if (this.cursor + bytes3.length > this.dest.length) {
21067
21740
  throw new Error("write out of bounds, destination buffer is too small");
21068
21741
  }
21069
- this.dest.set(bytes2, this.cursor);
21070
- this.cursor += bytes2.length;
21742
+ this.dest.set(bytes3, this.cursor);
21743
+ this.cursor += bytes3.length;
21071
21744
  }
21072
21745
  /**
21073
21746
  * @param {boolean} [reset]
@@ -21321,14 +21994,14 @@ function tokenBytes(token) {
21321
21994
  }
21322
21995
  __name(tokenBytes, "tokenBytes");
21323
21996
  function encodeBytes(writer, token) {
21324
- const bytes2 = tokenBytes(token);
21325
- encodeUintValue(writer, token.type.majorEncoded, bytes2.length);
21326
- writer.push(bytes2);
21997
+ const bytes3 = tokenBytes(token);
21998
+ encodeUintValue(writer, token.type.majorEncoded, bytes3.length);
21999
+ writer.push(bytes3);
21327
22000
  }
21328
22001
  __name(encodeBytes, "encodeBytes");
21329
22002
  encodeBytes.encodedSize = /* @__PURE__ */ __name(function encodedSize4(token) {
21330
- const bytes2 = tokenBytes(token);
21331
- return encodeUintValue.encodedSize(bytes2.length) + bytes2.length;
22003
+ const bytes3 = tokenBytes(token);
22004
+ return encodeUintValue.encodedSize(bytes3.length) + bytes3.length;
21332
22005
  }, "encodedSize");
21333
22006
  encodeBytes.compareTokens = /* @__PURE__ */ __name(function compareTokens3(tok1, tok2) {
21334
22007
  return compareBytes(tokenBytes(tok1), tokenBytes(tok2));
@@ -21341,20 +22014,20 @@ __name(compareBytes, "compareBytes");
21341
22014
  // ../../node_modules/cborg/lib/3string.js
21342
22015
  var textDecoder = new TextDecoder();
21343
22016
  var ASCII_THRESHOLD = 32;
21344
- function toStr(bytes2, start, end) {
22017
+ function toStr(bytes3, start, end) {
21345
22018
  const len = end - start;
21346
22019
  if (len < ASCII_THRESHOLD) {
21347
22020
  let str = "";
21348
22021
  for (let i = start; i < end; i++) {
21349
- const c = bytes2[i];
22022
+ const c = bytes3[i];
21350
22023
  if (c & 128) {
21351
- return textDecoder.decode(bytes2.subarray(start, end));
22024
+ return textDecoder.decode(bytes3.subarray(start, end));
21352
22025
  }
21353
22026
  str += String.fromCharCode(c);
21354
22027
  }
21355
22028
  return str;
21356
22029
  }
21357
- return textDecoder.decode(bytes2.subarray(start, end));
22030
+ return textDecoder.decode(bytes3.subarray(start, end));
21358
22031
  }
21359
22032
  __name(toStr, "toStr");
21360
22033
  function toToken2(data, pos, prefix, length, options) {
@@ -21534,7 +22207,7 @@ function decodeBreak(_data, _pos, _minor, options) {
21534
22207
  return new Token(Type.break, void 0, 1);
21535
22208
  }
21536
22209
  __name(decodeBreak, "decodeBreak");
21537
- function createToken(value, bytes2, options) {
22210
+ function createToken(value, bytes3, options) {
21538
22211
  if (options) {
21539
22212
  if (options.allowNaN === false && Number.isNaN(value)) {
21540
22213
  throw new Error(`${decodeErrPrefix} NaN values are not supported`);
@@ -21543,7 +22216,7 @@ function createToken(value, bytes2, options) {
21543
22216
  throw new Error(`${decodeErrPrefix} Infinity values are not supported`);
21544
22217
  }
21545
22218
  }
21546
- return new Token(Type.float, value, bytes2);
22219
+ return new Token(Type.float, value, bytes3);
21547
22220
  }
21548
22221
  __name(createToken, "createToken");
21549
22222
  function decodeFloat16(data, pos, _minor, options) {
@@ -21741,13 +22414,13 @@ function majorSevenBytes(token, options) {
21741
22414
  if (cached !== void 0) {
21742
22415
  return cached;
21743
22416
  }
21744
- const bytes2 = encodeMajorSevenBytes(token, float64);
22417
+ const bytes3 = encodeMajorSevenBytes(token, float64);
21745
22418
  if (float64) {
21746
- tokenEx._keyBytesFloat64 = bytes2;
22419
+ tokenEx._keyBytesFloat64 = bytes3;
21747
22420
  } else {
21748
- tokenEx._keyBytes = bytes2;
22421
+ tokenEx._keyBytes = bytes3;
21749
22422
  }
21750
- return bytes2;
22423
+ return bytes3;
21751
22424
  }
21752
22425
  __name(majorSevenBytes, "majorSevenBytes");
21753
22426
  encodeFloat.compareTokens = /* @__PURE__ */ __name(function compareTokens4(tok1, tok2, options) {
@@ -22123,15 +22796,15 @@ var typeEncoders = {
22123
22796
  */
22124
22797
  Object(obj, typ, options, refStack) {
22125
22798
  const isMap = typ !== "Object";
22126
- const keys = isMap ? obj.keys() : Object.keys(obj);
22127
- const maxLength = isMap ? obj.size : keys.length;
22799
+ const keys2 = isMap ? obj.keys() : Object.keys(obj);
22800
+ const maxLength = isMap ? obj.size : keys2.length;
22128
22801
  let entries;
22129
22802
  if (maxLength) {
22130
22803
  entries = new Array(maxLength);
22131
22804
  refStack = Ref.createCheck(refStack, obj);
22132
22805
  const skipUndefined = !isMap && options.ignoreUndefinedProperties;
22133
22806
  let i = 0;
22134
- for (const key of keys) {
22807
+ for (const key of keys2) {
22135
22808
  const value = isMap ? obj.get(key) : obj[key];
22136
22809
  if (skipUndefined && value === void 0) {
22137
22810
  continue;
@@ -22282,8 +22955,8 @@ function canDirectEncode(options) {
22282
22955
  __name(canDirectEncode, "canDirectEncode");
22283
22956
  function directEncodeMap(writer, data, typ, options, refStack) {
22284
22957
  const isMap = typ === "Map";
22285
- const keys = isMap ? data.keys() : Object.keys(data);
22286
- const maxLength = isMap ? data.size : keys.length;
22958
+ const keys2 = isMap ? data.keys() : Object.keys(data);
22959
+ const maxLength = isMap ? data.size : keys2.length;
22287
22960
  if (!maxLength) {
22288
22961
  writer.pushByte(MAJOR_MAP);
22289
22962
  return;
@@ -22292,7 +22965,7 @@ function directEncodeMap(writer, data, typ, options, refStack) {
22292
22965
  const skipUndefined = !isMap && options.ignoreUndefinedProperties;
22293
22966
  const entries = new Array(maxLength);
22294
22967
  let length = 0;
22295
- for (const key of keys) {
22968
+ for (const key of keys2) {
22296
22969
  const value = isMap ? data.get(key) : data[key];
22297
22970
  if (skipUndefined && value === void 0) {
22298
22971
  continue;
@@ -22351,9 +23024,9 @@ function directEncode(writer, data, options, refStack) {
22351
23024
  }
22352
23025
  return;
22353
23026
  case "string": {
22354
- const bytes2 = fromString(data);
22355
- directEncodeUintValue(writer, MAJOR_STRING, bytes2.length);
22356
- writer.push(bytes2);
23027
+ const bytes3 = fromString(data);
23028
+ directEncodeUintValue(writer, MAJOR_STRING, bytes3.length);
23029
+ writer.push(bytes3);
22357
23030
  return;
22358
23031
  }
22359
23032
  case "Uint8Array":
@@ -22716,15 +23389,15 @@ var AWS_ROOT_SHA256 = "641a0321a3e244efe456463195d606317ed7cdcc3c1756e09893f3c68
22716
23389
  var fail = /* @__PURE__ */ __name((reason) => {
22717
23390
  throw new NitroAttestationError(reason);
22718
23391
  }, "fail");
22719
- var hex = /* @__PURE__ */ __name((bytes2) => Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
23392
+ var hex = /* @__PURE__ */ __name((bytes3) => Array.from(bytes3, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
22720
23393
  var bytes = /* @__PURE__ */ __name((value, reason) => value instanceof Uint8Array && value.length > 0 ? value : fail(reason), "bytes");
22721
23394
  var map = /* @__PURE__ */ __name((value, reason) => value instanceof Map ? value : fail(reason), "map");
22722
- var decodeCbor = /* @__PURE__ */ __name((value) => {
23395
+ var decodeCbor = /* @__PURE__ */ __name((value, { allowIndefinite = false } = {}) => {
22723
23396
  try {
22724
23397
  return decode(value, {
22725
23398
  useMaps: true,
22726
23399
  rejectDuplicateMapKeys: true,
22727
- allowIndefinite: false,
23400
+ allowIndefinite,
22728
23401
  allowUndefined: false,
22729
23402
  allowNaN: false,
22730
23403
  allowInfinity: false,
@@ -22782,7 +23455,7 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
22782
23455
  const payloadBytes = bytes(payloadValue, "cose");
22783
23456
  const signature = bytes(signatureValue, "signature");
22784
23457
  if (signature.length !== 96) fail("signature");
22785
- const payload = map(decodeCbor(payloadBytes), "cbor");
23458
+ const payload = map(decodeCbor(payloadBytes, { allowIndefinite: true }), "cbor");
22786
23459
  const moduleId = payload.get("module_id");
22787
23460
  const timestamp = payload.get("timestamp");
22788
23461
  if (typeof moduleId !== "string" || !moduleId || payload.get("digest") !== "SHA384")
@@ -22872,13 +23545,36 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
22872
23545
  } catch {
22873
23546
  return fail("user-data");
22874
23547
  }
23548
+ const rawLedgerKey = payload.get("public_key");
23549
+ let ledgerPublicKey;
23550
+ let measurementHash;
23551
+ if (rawLedgerKey !== void 0 && rawLedgerKey !== null) {
23552
+ const ledger = new Uint8Array(bytes(rawLedgerKey, "user-data"));
23553
+ if (ledger.length !== 65 || ledger[0] !== 4) fail("user-data");
23554
+ try {
23555
+ await crypto.subtle.importKey(
23556
+ "raw",
23557
+ ledger,
23558
+ { name: "ECDSA", namedCurve: "P-256" },
23559
+ false,
23560
+ ["verify"]
23561
+ );
23562
+ } catch {
23563
+ return fail("user-data");
23564
+ }
23565
+ const tuple = new Uint8Array(144);
23566
+ for (let i = 0; i < 3; i++) tuple.set(bytes(rawPcrs.get(i), "pcr"), i * 48);
23567
+ measurementHash = hex(new Uint8Array(await crypto.subtle.digest("SHA-256", tuple)));
23568
+ ledgerPublicKey = bufferToBase64(ledger.buffer);
23569
+ }
22875
23570
  return {
22876
23571
  escrowPublicKeySpkiB64: bufferToBase64(new Uint8Array(spki).buffer),
22877
23572
  keyId: newFormat?.keyId,
22878
23573
  previousKeyIds: newFormat?.previousKeyIds ?? [],
22879
23574
  pcrs,
22880
23575
  timestamp,
22881
- moduleId
23576
+ moduleId,
23577
+ ...ledgerPublicKey ? { ledgerPublicKey, measurementHash } : {}
22882
23578
  };
22883
23579
  }, "verifyNitroAttestationDocument");
22884
23580
 
@@ -22932,7 +23628,13 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
22932
23628
  publicKey: verified.escrowPublicKeySpkiB64,
22933
23629
  keyId: attestation.keyId,
22934
23630
  previousKeyIds: verified.previousKeyIds,
22935
- mode: "nitro"
23631
+ mode: "nitro",
23632
+ ...verified.keyId && verified.ledgerPublicKey && verified.measurementHash ? {
23633
+ authority: {
23634
+ ledgerPublicKey: verified.ledgerPublicKey,
23635
+ measurement: verified.measurementHash
23636
+ }
23637
+ } : {}
22936
23638
  };
22937
23639
  }
22938
23640
  const publicKey = normalizePublicKey(attestation.publicKey);
@@ -22954,6 +23656,424 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
22954
23656
  };
22955
23657
  }, "verifyEnclaveAttestation");
22956
23658
 
23659
+ // src/escrow-authority.types.ts
23660
+ var EscrowEvidenceError = class extends Error {
23661
+ static {
23662
+ __name(this, "EscrowEvidenceError");
23663
+ }
23664
+ constructor() {
23665
+ super("Automatic recovery evidence could not be verified.");
23666
+ this.name = "EscrowEvidenceError";
23667
+ }
23668
+ };
23669
+
23670
+ // src/escrow-authority.ts
23671
+ var fail2 = /* @__PURE__ */ __name(() => {
23672
+ throw new EscrowEvidenceError();
23673
+ }, "fail");
23674
+ var verifyEscrowHoldState = /* @__PURE__ */ __name(async (response, nonce, expected, identity) => {
23675
+ requireEvidence(/^[0-9a-f]{64}$/.test(nonce));
23676
+ const { payload } = await verifyRecord(response.proof, "snapshot", identity);
23677
+ requireEvidence(Array.isArray(payload) && payload.length === 12);
23678
+ const p = payload;
23679
+ requireEvidence(
23680
+ p[0] === "learncard-authority-hold-state-v3" && p[1] === nonce && p[2] === expected.tenant && p[3] === expected.authorityGeneration && p[4] === expected.did && p[5] === expected.holdId && p[6] === expected.holdDigest
23681
+ );
23682
+ const status = p[7];
23683
+ if (status !== "awaitingConfirmation" && status !== "pending" && status !== "released" && status !== "cancelled")
23684
+ return fail2();
23685
+ const confirmedHiMs = p[8] === null ? null : integer2(p[8]);
23686
+ const releaseWarningSentHiMs = p[9] === null ? null : integer2(p[9]);
23687
+ const attemptsRemaining = integer2(p[10], 0, 5);
23688
+ const codeSendStatus = p[11];
23689
+ if (codeSendStatus !== "unknown" && codeSendStatus !== "notRequired") return fail2();
23690
+ requireEvidence(
23691
+ status !== "awaitingConfirmation" || confirmedHiMs === null && releaseWarningSentHiMs === null
23692
+ );
23693
+ requireEvidence(status !== "pending" && status !== "released" || confirmedHiMs !== null);
23694
+ return { status, confirmedHiMs, releaseWarningSentHiMs, attemptsRemaining, codeSendStatus };
23695
+ }, "verifyEscrowHoldState");
23696
+ var verifyEscrowCodeDelivery = /* @__PURE__ */ __name(async (delivery, expected, identity) => {
23697
+ const { payload } = await verifyRecord(delivery.proof, "snapshot", identity);
23698
+ requireEvidence(Array.isArray(payload) && payload.length === 5);
23699
+ const values = payload;
23700
+ requireEvidence(
23701
+ values[0] === "learncard-authority-code-delivery-v1" && values[1] === expected.tenant && values[2] === expected.authorityGeneration && values[3] === expected.holdDigest && typeof values[4] === "boolean" && values[4] === delivery.codeSent
23702
+ );
23703
+ return delivery.codeSent;
23704
+ }, "verifyEscrowCodeDelivery");
23705
+ var requireEvidence = /* @__PURE__ */ __name((condition) => {
23706
+ if (!condition) fail2();
23707
+ }, "requireEvidence");
23708
+ var object = /* @__PURE__ */ __name((value) => {
23709
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail2();
23710
+ return value;
23711
+ }, "object");
23712
+ var keys = /* @__PURE__ */ __name((value, names) => {
23713
+ requireEvidence(
23714
+ Object.keys(value).length === names.length && names.every((name) => Object.prototype.hasOwnProperty.call(value, name))
23715
+ );
23716
+ }, "keys");
23717
+ var integer2 = /* @__PURE__ */ __name((value, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) => {
23718
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum || value > maximum)
23719
+ return fail2();
23720
+ return value;
23721
+ }, "integer");
23722
+ var text = /* @__PURE__ */ __name((value, maximum) => {
23723
+ if (typeof value !== "string" || !value.length || value.length > maximum) return fail2();
23724
+ return value;
23725
+ }, "text");
23726
+ var bytes2 = /* @__PURE__ */ __name((value, length) => {
23727
+ if (!Array.isArray(value) || value.length !== length || !value.every(
23728
+ (byte) => typeof byte === "number" && Number.isInteger(byte) && byte >= 0 && byte <= 255
23729
+ ))
23730
+ return fail2();
23731
+ return Uint8Array.from(value);
23732
+ }, "bytes");
23733
+ var base64 = /* @__PURE__ */ __name((value, maximum) => {
23734
+ const encoded = text(value, maximum);
23735
+ try {
23736
+ const decoded = new Uint8Array(base64ToBuffer(encoded));
23737
+ requireEvidence(bufferToBase64(decoded.buffer) === encoded);
23738
+ return decoded;
23739
+ } catch {
23740
+ return fail2();
23741
+ }
23742
+ }, "base64");
23743
+ var frame = /* @__PURE__ */ __name((value) => {
23744
+ const result = new Uint8Array(4 + value.length);
23745
+ new DataView(result.buffer).setUint32(0, value.length, false);
23746
+ result.set(value, 4);
23747
+ return result;
23748
+ }, "frame");
23749
+ var join2 = /* @__PURE__ */ __name((...values) => {
23750
+ const result = new Uint8Array(values.reduce((n, v) => n + v.length, 0));
23751
+ let offset = 0;
23752
+ for (const value of values) {
23753
+ result.set(value, offset);
23754
+ offset += value.length;
23755
+ }
23756
+ return result;
23757
+ }, "join");
23758
+ var hash = /* @__PURE__ */ __name(async (value) => bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", new Uint8Array(value)))), "hash");
23759
+ var utf82 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
23760
+ var escrowAuthorityMeasurements = /* @__PURE__ */ __name(async (policy) => {
23761
+ if (policy.mode !== "nitro") return [];
23762
+ const hashes = [];
23763
+ for (const pin of policy.pinnedMeasurements) {
23764
+ const tuple = [pin.pcr0, pin.pcr1, pin.pcr2];
23765
+ if (!tuple.every((pcr) => typeof pcr === "string" && /^[0-9a-f]{96}$/i.test(pcr))) continue;
23766
+ if (pin.pcr0 === "00".repeat(48)) continue;
23767
+ const encoded = tuple.join("");
23768
+ const decoded = Uint8Array.from(
23769
+ { length: 144 },
23770
+ (_, i) => parseInt(encoded.slice(i * 2, i * 2 + 2), 16)
23771
+ );
23772
+ hashes.push(await hash(decoded));
23773
+ }
23774
+ return hashes;
23775
+ }, "escrowAuthorityMeasurements");
23776
+ var P256_ORDER = BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
23777
+ var verifyRecord = /* @__PURE__ */ __name(async (input, kind, identity, historical) => {
23778
+ requireEvidence(identity.mode === "nitro" && !!identity.authority);
23779
+ const raw = object(input);
23780
+ keys(raw, ["version", "kind", "keyId", "measurement", "payload", "signature"]);
23781
+ requireEvidence(raw.version === 1 && raw.kind === kind);
23782
+ const keyId = text(raw.keyId, 128);
23783
+ requireEvidence(
23784
+ historical ? [identity.keyId, ...identity.previousKeyIds].includes(keyId) : keyId === identity.keyId
23785
+ );
23786
+ const measurement = bytes2(raw.measurement, 32);
23787
+ requireEvidence(
23788
+ historical ? historical.allowedMeasurements.includes(bytesToHex(measurement)) : bytesToHex(measurement) === identity.authority?.measurement
23789
+ );
23790
+ const payloadB64 = text(raw.payload, kind === "snapshot" ? 49152 : 8192);
23791
+ const signatureB64 = text(raw.signature, 88);
23792
+ const payload = base64(payloadB64, kind === "snapshot" ? 49152 : 8192);
23793
+ const signature = base64(signatureB64, 88);
23794
+ const ledgerKey = base64(identity.authority?.ledgerPublicKey, 88);
23795
+ requireEvidence(ledgerKey.length === 65 && ledgerKey[0] === 4);
23796
+ requireEvidence(signature.length === 64);
23797
+ const s = BigInt(`0x${bytesToHex(signature.slice(32))}`);
23798
+ requireEvidence(s > 0n && s <= P256_ORDER / 2n);
23799
+ const message = join2(
23800
+ utf82("learncard-authority-signed-record-v1\0"),
23801
+ Uint8Array.of(kind === "snapshot" ? 2 : 1),
23802
+ frame(utf82(keyId)),
23803
+ measurement,
23804
+ frame(payload)
23805
+ );
23806
+ try {
23807
+ const key = await crypto.subtle.importKey(
23808
+ "raw",
23809
+ ledgerKey,
23810
+ { name: "ECDSA", namedCurve: "P-256" },
23811
+ false,
23812
+ ["verify"]
23813
+ );
23814
+ requireEvidence(
23815
+ await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, signature, message)
23816
+ );
23817
+ const decoded = JSON.parse(
23818
+ new TextDecoder("utf-8", { fatal: true }).decode(payload)
23819
+ );
23820
+ const record = {
23821
+ version: 1,
23822
+ kind,
23823
+ keyId,
23824
+ measurement: Array.from(measurement),
23825
+ payload: payloadB64,
23826
+ signature: signatureB64
23827
+ };
23828
+ return { record, payload: decoded };
23829
+ } catch {
23830
+ return fail2();
23831
+ }
23832
+ }, "verifyRecord");
23833
+ var envelope = /* @__PURE__ */ __name((value) => {
23834
+ try {
23835
+ const e = parseEscrowEnvelope(value);
23836
+ return {
23837
+ version: e.version,
23838
+ algorithm: e.algorithm,
23839
+ keyId: e.keyId,
23840
+ ephemeralPublicKey: e.ephemeralPublicKey,
23841
+ salt: e.salt,
23842
+ iv: e.iv,
23843
+ ciphertext: e.ciphertext
23844
+ };
23845
+ } catch {
23846
+ return fail2();
23847
+ }
23848
+ }, "envelope");
23849
+ var state = /* @__PURE__ */ __name((value) => {
23850
+ const raw = object(value);
23851
+ keys(raw, [
23852
+ "tenant",
23853
+ "authorityGeneration",
23854
+ "did",
23855
+ "enrollmentVersion",
23856
+ "enrollmentEpoch",
23857
+ "status",
23858
+ "envelope",
23859
+ "shareVersion",
23860
+ "hasPin",
23861
+ "pinGeneration",
23862
+ "attemptsUsed"
23863
+ ]);
23864
+ if (raw.status !== "empty" && raw.status !== "active" && raw.status !== "disabled")
23865
+ return fail2();
23866
+ if (typeof raw.hasPin !== "boolean") return fail2();
23867
+ const result = {
23868
+ tenant: text(raw.tenant, 128),
23869
+ authorityGeneration: text(raw.authorityGeneration, 128),
23870
+ did: text(raw.did, 8192),
23871
+ enrollmentVersion: integer2(raw.enrollmentVersion),
23872
+ enrollmentEpoch: integer2(raw.enrollmentEpoch),
23873
+ status: raw.status,
23874
+ envelope: raw.envelope === null ? null : envelope(raw.envelope),
23875
+ shareVersion: raw.shareVersion === null ? null : integer2(raw.shareVersion, 1, 4294967295),
23876
+ hasPin: raw.hasPin,
23877
+ pinGeneration: integer2(raw.pinGeneration),
23878
+ attemptsUsed: integer2(raw.attemptsUsed, 0, 10)
23879
+ };
23880
+ requireEvidence(
23881
+ result.pinGeneration <= result.enrollmentVersion && result.enrollmentEpoch <= result.enrollmentVersion && (!result.hasPin || result.pinGeneration > 0) && (result.hasPin || result.attemptsUsed === 0)
23882
+ );
23883
+ if (result.status === "empty")
23884
+ requireEvidence(
23885
+ result.enrollmentVersion === 0 && result.enrollmentEpoch === 0 && !result.envelope && result.shareVersion === null && !result.hasPin
23886
+ );
23887
+ else requireEvidence(result.enrollmentVersion > 0 && result.enrollmentEpoch > 0);
23888
+ if (result.status === "active")
23889
+ requireEvidence(!!result.envelope && result.shareVersion !== null);
23890
+ else requireEvidence(result.envelope === null && result.shareVersion === null);
23891
+ return result;
23892
+ }, "state");
23893
+ var verifyEscrowAuthorityState = /* @__PURE__ */ __name(async (response, nonce, tenant, did, identity) => {
23894
+ requireEvidence(/^[0-9a-f]{64}$/.test(nonce) && nonce.length === 64);
23895
+ const raw = object(response);
23896
+ keys(raw, ["state", "proof"]);
23897
+ const { payload } = await verifyRecord(raw.proof, "snapshot", identity);
23898
+ if (!Array.isArray(payload) || payload.length !== 2 || payload[0] !== nonce) return fail2();
23899
+ const signed = state(payload[1]);
23900
+ requireEvidence(signed.tenant === tenant && signed.did === did);
23901
+ requireEvidence(JSON.stringify(signed) === JSON.stringify(state(raw.state)));
23902
+ if (signed.envelope) {
23903
+ requireEvidence(
23904
+ [identity.keyId, ...identity.previousKeyIds].includes(signed.envelope.keyId)
23905
+ );
23906
+ await getEscrowBlobIdentity(signed.envelope);
23907
+ }
23908
+ return signed;
23909
+ }, "verifyEscrowAuthorityState");
23910
+ var verifyEscrowEnrollmentCommit = /* @__PURE__ */ __name(async (response, intent, identity) => {
23911
+ const raw = object(response);
23912
+ const { record, payload } = await verifyRecord(raw.receipt, "commit", identity);
23913
+ const data = object(payload);
23914
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
23915
+ const commit = object(data.commit);
23916
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
23917
+ const binding = object(commit.binding);
23918
+ keys(binding, ["tenant", "generation", "didHash"]);
23919
+ const revisions = object(commit.revisions);
23920
+ keys(revisions, ["operation", "enrollment"]);
23921
+ requireEvidence(
23922
+ commit.schemaVersion === 1 && binding.tenant === intent.tenant && binding.generation === intent.authorityGeneration
23923
+ );
23924
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(intent.did)));
23925
+ requireEvidence(
23926
+ integer2(revisions.enrollment, 1) === intent.expectedEnrollmentVersion + 1 && integer2(revisions.operation, 1) >= integer2(revisions.enrollment, 1)
23927
+ );
23928
+ bytes2(commit.executionId, 16);
23929
+ bytes2(commit.transactionDigest, 32);
23930
+ bytes2(data.eventHash, 32);
23931
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === intent.enrollmentEpoch);
23932
+ requireEvidence(
23933
+ bytesToHex(bytes2(data.requestDigest, 32)) === await hash(encodeEscrowEnrollmentIntent(intent))
23934
+ );
23935
+ if (intent.action === "disable") {
23936
+ requireEvidence(
23937
+ (raw.envelope === null || raw.envelope === void 0) && data.resultBlobIdentity === null
23938
+ );
23939
+ return { envelope: null, receipt: record };
23940
+ }
23941
+ const output = envelope(raw.envelope);
23942
+ requireEvidence(
23943
+ output.keyId === identity.keyId && bytesToHex(bytes2(data.resultBlobIdentity, 32)) === await getEscrowBlobIdentity(output)
23944
+ );
23945
+ return { envelope: output, receipt: record };
23946
+ }, "verifyEscrowEnrollmentCommit");
23947
+ var holdDigest = /* @__PURE__ */ __name(async (tenant, record) => {
23948
+ const h2 = record.hold;
23949
+ const didHash = await hash(utf82(h2.did));
23950
+ return hash(
23951
+ utf82(
23952
+ JSON.stringify([
23953
+ "learncard-hold-v1",
23954
+ tenant,
23955
+ h2.holdId,
23956
+ didHash,
23957
+ h2.shareVersion,
23958
+ h2.blobHash,
23959
+ h2.enrollmentEpoch,
23960
+ h2.releasePolicy,
23961
+ h2.clientEphemeralPublicKey,
23962
+ h2.createdLo,
23963
+ h2.createdHi,
23964
+ record.holdDurationMs,
23965
+ h2.policyVersion,
23966
+ record.ledgerSeq
23967
+ ])
23968
+ )
23969
+ );
23970
+ }, "holdDigest");
23971
+ var verifyEscrowHoldRecord = /* @__PURE__ */ __name(async (record, expected, identity, historical) => {
23972
+ requireEvidence(
23973
+ record.hold.holdId === expected.holdId && record.hold.did === expected.did && record.hold.clientEphemeralPublicKey === expected.clientEphemeralPublicKey && record.hold.blobHash === expected.blobHash
23974
+ );
23975
+ let signed;
23976
+ try {
23977
+ signed = JSON.parse(
23978
+ new TextDecoder("utf-8", { fatal: true }).decode(base64(record.hold.signature, 8192))
23979
+ );
23980
+ } catch {
23981
+ return fail2();
23982
+ }
23983
+ const { record: receipt, payload } = await verifyRecord(signed, "commit", identity, historical);
23984
+ const data = object(payload);
23985
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
23986
+ const commit = object(data.commit);
23987
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
23988
+ const binding = object(commit.binding);
23989
+ keys(binding, ["tenant", "generation", "didHash"]);
23990
+ requireEvidence(commit.schemaVersion === 1 && binding.tenant === expected.tenant);
23991
+ const authorityGeneration = text(binding.generation, 128);
23992
+ if (historical) requireEvidence(authorityGeneration === historical.authorityGeneration);
23993
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
23994
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
23995
+ requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
23996
+ const digest = await holdDigest(expected.tenant, record);
23997
+ requireEvidence(bytesToHex(bytes2(data.requestDigest, 32)) === digest);
23998
+ return { receipt, authorityGeneration, holdDigest: digest };
23999
+ }, "verifyEscrowHoldRecord");
24000
+ var verifyEscrowHoldConfirmation = /* @__PURE__ */ __name(async (receipt, record, expected, identity) => {
24001
+ const raw = object(receipt);
24002
+ const kind = raw.kind;
24003
+ if (kind !== "commit" && kind !== "snapshot") return fail2();
24004
+ const { record: verified, payload } = await verifyRecord(raw, kind, identity);
24005
+ if (kind === "snapshot") {
24006
+ if (!Array.isArray(payload) || payload.length !== 7) return fail2();
24007
+ const [tag, holdId, digestBytes] = payload;
24008
+ requireEvidence(
24009
+ tag === "learncard-authority-hold-snapshot-v2" && holdId === record.hold.holdId && payload[6] === expected.authorityGeneration
24010
+ );
24011
+ requireEvidence(
24012
+ bytesToHex(bytes2(digestBytes, 32)) === await holdDigest(expected.tenant, record)
24013
+ );
24014
+ requireEvidence(payload[3] === "pending");
24015
+ integer2(payload[4], 1);
24016
+ return verified;
24017
+ }
24018
+ const data = object(payload);
24019
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
24020
+ const commit = object(data.commit);
24021
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
24022
+ const binding = object(commit.binding);
24023
+ keys(binding, ["tenant", "generation", "didHash"]);
24024
+ requireEvidence(
24025
+ commit.schemaVersion === 1 && binding.tenant === expected.tenant && binding.generation === expected.authorityGeneration
24026
+ );
24027
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
24028
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
24029
+ requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
24030
+ bytes2(data.requestDigest, 32);
24031
+ return verified;
24032
+ }, "verifyEscrowHoldConfirmation");
24033
+ var resolveEscrowEnrollmentAction = /* @__PURE__ */ __name((current, input) => {
24034
+ const disabling = input === "disable";
24035
+ const pinAction = disabling ? "keep" : input === "set" ? current.hasPin ? "change" : "set" : input === "clear" ? current.hasPin ? "clear" : "keep" : "keep";
24036
+ const action = disabling ? "disable" : current.status !== "active" ? "enroll" : current.hasPin && pinAction === "keep" ? "carry" : "replace";
24037
+ return { action, pinAction, bindsRecoveryContact: action === "enroll" || action === "replace" };
24038
+ }, "resolveEscrowEnrollmentAction");
24039
+ var violatesCarryContactRule = /* @__PURE__ */ __name((action, target) => action === "carry" && !!target && (!!target.recoveryEmail || !!target.recoveryLanguage), "violatesCarryContactRule");
24040
+ var createEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (input) => {
24041
+ const current = state(input.state);
24042
+ const target = input.target === null ? null : envelope(input.target);
24043
+ const disabling = input.pinAction === "disable";
24044
+ requireEvidence(
24045
+ current.enrollmentVersion < Number.MAX_SAFE_INTEGER && (disabling || current.enrollmentEpoch < Number.MAX_SAFE_INTEGER)
24046
+ );
24047
+ if (disabling && current.status !== "active") return fail2();
24048
+ if (current.status === "disabled" && current.hasPin && input.pinAction === "automatic")
24049
+ return fail2();
24050
+ const { action, pinAction, bindsRecoveryContact } = resolveEscrowEnrollmentAction(
24051
+ current,
24052
+ input.pinAction
24053
+ );
24054
+ requireEvidence(!disabling || input.target === null);
24055
+ requireEvidence(disabling || input.target !== null);
24056
+ if (action === "carry") requireEvidence(input.shareVersion > (current.shareVersion ?? 0));
24057
+ const intent = {
24058
+ version: 2,
24059
+ tenant: current.tenant,
24060
+ did: current.did,
24061
+ authorityGeneration: current.authorityGeneration,
24062
+ expectedEnrollmentVersion: current.enrollmentVersion,
24063
+ action,
24064
+ sourceBlobIdentity: current.envelope ? await getEscrowBlobIdentity(current.envelope) : null,
24065
+ targetBlobIdentity: target ? await getEscrowBlobIdentity(target) : null,
24066
+ pinAction,
24067
+ shareVersion: disabling ? current.shareVersion : input.shareVersion,
24068
+ enrollmentEpoch: current.enrollmentEpoch + (disabling ? 0 : 1),
24069
+ requestId: crypto.randomUUID(),
24070
+ allowRewrap: !disabling,
24071
+ recoveryEmail: bindsRecoveryContact ? input.recoveryEmail : null,
24072
+ recoveryLanguage: bindsRecoveryContact ? input.recoveryLanguage : null
24073
+ };
24074
+ return signEscrowEnrollmentIntent(intent, input.privateKey);
24075
+ }, "createEscrowEnrollmentIntent");
24076
+
22957
24077
  // src/types.ts
22958
24078
  var import_types = __toESM(require_dist());
22959
24079
  var EscrowPinUnavailableError = class extends Error {
@@ -23250,9 +24370,10 @@ var SERVER_REQUEST_TIMEOUT_MS = 3e4;
23250
24370
  var requestTimeoutSignal = /* @__PURE__ */ __name((ms = SERVER_REQUEST_TIMEOUT_MS) => typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(ms) : void 0, "requestTimeoutSignal");
23251
24371
  var describeHttpStatus = /* @__PURE__ */ __name((response) => response.statusText ? `${response.status} ${response.statusText}` : `${response.status}`, "describeHttpStatus");
23252
24372
  var EscrowRequestError = class extends Error {
23253
- constructor(status) {
24373
+ constructor(status, reason) {
23254
24374
  super("Escrow request failed");
23255
24375
  this.status = status;
24376
+ this.reason = reason;
23256
24377
  this.name = "EscrowRequestError";
23257
24378
  }
23258
24379
  static {
@@ -23698,6 +24819,10 @@ function createSSSStrategy(config) {
23698
24819
  const localWrites = /* @__PURE__ */ new Set();
23699
24820
  const guardedStorage = /* @__PURE__ */ __name(() => {
23700
24821
  const generation = storageGeneration;
24822
+ const assertCurrent = /* @__PURE__ */ __name(() => {
24823
+ if (generation !== storageGeneration)
24824
+ throw new Error("This recovery request was cancelled.");
24825
+ }, "assertCurrent");
23701
24826
  const write = /* @__PURE__ */ __name((operation) => {
23702
24827
  if (generation !== storageGeneration) {
23703
24828
  return Promise.reject(new Error("This recovery request was cancelled."));
@@ -23708,6 +24833,7 @@ function createSSSStrategy(config) {
23708
24833
  }, "write");
23709
24834
  const guarded = {
23710
24835
  ...storage,
24836
+ assertCurrent,
23711
24837
  storeDeviceShare: /* @__PURE__ */ __name((share, id) => write(() => storage.storeDeviceShare(share, id)), "storeDeviceShare"),
23712
24838
  storeShareVersion: /* @__PURE__ */ __name((version, id) => write(() => storage.storeShareVersion(version, id)), "storeShareVersion"),
23713
24839
  clearAllShares: /* @__PURE__ */ __name((id) => write(() => storage.clearAllShares(id)), "clearAllShares"),
@@ -23725,6 +24851,7 @@ function createSSSStrategy(config) {
23725
24851
  let lastServerSnapshot = null;
23726
24852
  let escrowEnrollmentInFlight;
23727
24853
  let staleEscrowReenrollAttempted = false;
24854
+ let verifiedEscrowEnvelope;
23728
24855
  let unenrolledRotation;
23729
24856
  const escrowRequest = /* @__PURE__ */ __name(async (path, init, pinAttempt = false) => {
23730
24857
  const response = await fetch(`${serverUrl}/keys/escrow${path}`, {
@@ -23732,6 +24859,14 @@ function createSSSStrategy(config) {
23732
24859
  ...init
23733
24860
  });
23734
24861
  if (!response.ok) {
24862
+ if (path === "/confirm" && response.status === 403) {
24863
+ const body = await response.json().catch(() => void 0);
24864
+ const reason = body && typeof body === "object" && "message" in body && typeof body.message === "string" ? body.message : void 0;
24865
+ throw new EscrowRequestError(
24866
+ response.status,
24867
+ reason === "codeMismatch" || reason === "codeExpired" || reason === "codeLocked" ? reason : void 0
24868
+ );
24869
+ }
23735
24870
  if (!pinAttempt && path === "/recover" && response.status === 429) {
23736
24871
  const body = await response.json().catch(() => void 0);
23737
24872
  const message = body && typeof body === "object" && "message" in body && typeof body.message === "string" ? body.message : "";
@@ -23783,16 +24918,89 @@ function createSSSStrategy(config) {
23783
24918
  );
23784
24919
  return verifyEnclaveAttestation(attestation, config.escrow.attestation, nonce);
23785
24920
  }, "fetchVerifiedEnclaveKey");
23786
- const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false) => {
24921
+ const fetchEscrowHoldStatus = /* @__PURE__ */ __name(async (params) => {
24922
+ const query = new URLSearchParams(
24923
+ "holdId" in params ? { holdId: params.holdId } : { providerType: params.providerType }
24924
+ );
24925
+ const secret = "holdId" in params ? params.resumeToken : params.token;
24926
+ const result = await escrowRequest(`/status?${query}`, {
24927
+ method: "GET",
24928
+ headers: {
24929
+ ...buildHeaders("", void 0, tenantId),
24930
+ "X-Auth-Token": secret
24931
+ }
24932
+ });
24933
+ return result.hold;
24934
+ }, "fetchEscrowHoldStatus");
24935
+ const recoveryExpectations = /* @__PURE__ */ __name((holdId, expected) => {
24936
+ if (!expected || expected.holdId !== holdId || expected.tenant !== (tenantId ?? "learncard") || !expected.did || !expected.clientEphemeralPublicKey || !expected.blobHash || !expected.authorityGeneration || !expected.holdDigest || !expected.ledgerPublicKey || !expected.keyId)
24937
+ throw new EscrowEvidenceError();
24938
+ return { ...expected };
24939
+ }, "recoveryExpectations");
24940
+ const verifyPendingHold = /* @__PURE__ */ __name(async (status, expected, identity) => {
24941
+ if (!config.escrow || identity.mode !== "nitro" || !identity.authority || identity.authority.ledgerPublicKey !== expected.ledgerPublicKey || ![identity.keyId, ...identity.previousKeyIds].includes(expected.keyId) || status.holdId !== expected.holdId || !status.holdRecord)
24942
+ throw new EscrowEvidenceError();
24943
+ const record = status.holdRecord;
24944
+ const verified = await verifyEscrowHoldRecord(record, expected, identity, {
24945
+ historical: true,
24946
+ allowedMeasurements: await escrowAuthorityMeasurements(config.escrow.attestation),
24947
+ authorityGeneration: expected.authorityGeneration
24948
+ });
24949
+ if (verified.holdDigest !== expected.holdDigest || verified.receipt.keyId !== expected.keyId)
24950
+ throw new EscrowEvidenceError();
24951
+ return record;
24952
+ }, "verifyPendingHold");
24953
+ const fetchAuthorityState = /* @__PURE__ */ __name(async (token, providerType, privateKey, did, signer, identity, assertCurrent) => {
24954
+ assertCurrent();
24955
+ if (identity.mode !== "nitro" || !identity.authority)
24956
+ throw new Error("The enclave does not support verified enrollment.");
24957
+ const nonce = Array.from(
24958
+ crypto.getRandomValues(new Uint8Array(32)),
24959
+ (byte) => byte.toString(16).padStart(2, "0")
24960
+ ).join("");
24961
+ const vp = await requestFreshDidAuthVp(serverUrl, privateKey, did, signer, tenantId);
24962
+ assertCurrent();
24963
+ const response = await escrowRequest("/authority-state", {
24964
+ method: "POST",
24965
+ headers: buildHeaders(token, vp, tenantId),
24966
+ body: JSON.stringify({ authToken: token, providerType, nonce })
24967
+ });
24968
+ const result = await verifyEscrowAuthorityState(
24969
+ response,
24970
+ nonce,
24971
+ tenantId ?? "learncard",
24972
+ did,
24973
+ identity
24974
+ );
24975
+ assertCurrent();
24976
+ return result;
24977
+ }, "fetchAuthorityState");
24978
+ const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false, assertCurrent = guardedStorage().assertCurrent, recoveryEmail = "", recoveryLanguage = "") => {
23787
24979
  if (!config.escrow?.enabled) throw new Error("Escrow enrollment is disabled");
23788
24980
  if (!signDidAuthVp) throw new Error("DID proof signing is required for escrow enrollment");
23789
- const { publicKey, keyId } = verifiedKey ?? await fetchVerifiedEnclaveKey();
23790
- const envelope = await encryptEscrowBlob(
24981
+ const identity = verifiedKey ?? await fetchVerifiedEnclaveKey();
24982
+ assertCurrent();
24983
+ const { publicKey, keyId } = identity;
24984
+ const authority = config.escrow.attestation.mode === "nitro" ? await fetchAuthorityState(
24985
+ token,
24986
+ providerType,
24987
+ privateKey,
24988
+ primaryDid,
24989
+ signDidAuthVp,
24990
+ identity,
24991
+ assertCurrent
24992
+ ) : void 0;
24993
+ const bindsRecoveryContact = !authority || resolveEscrowEnrollmentAction(
24994
+ authority,
24995
+ pinMaterial ? "set" : clearPin ? "clear" : "automatic"
24996
+ ).bindsRecoveryContact;
24997
+ const envelope2 = await encryptEscrowBlob(
23791
24998
  {
23792
24999
  recoveryShare: shares.recoveryShare,
23793
25000
  did: primaryDid,
23794
25001
  shareVersion,
23795
- ...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {}
25002
+ ...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {},
25003
+ ...authority && recoveryEmail && bindsRecoveryContact ? { recoveryEmail, recoveryLanguage } : {}
23796
25004
  },
23797
25005
  publicKey,
23798
25006
  keyId
@@ -23804,36 +25012,60 @@ function createSSSStrategy(config) {
23804
25012
  signDidAuthVp,
23805
25013
  tenantId
23806
25014
  );
23807
- await escrowRequest("", {
25015
+ const signedIntent = authority ? await createEscrowEnrollmentIntent({
25016
+ state: authority,
25017
+ target: envelope2,
25018
+ shareVersion,
25019
+ privateKey,
25020
+ pinAction: pinMaterial ? "set" : clearPin ? "clear" : "automatic",
25021
+ recoveryEmail,
25022
+ recoveryLanguage
25023
+ }) : void 0;
25024
+ assertCurrent();
25025
+ verifiedEscrowEnvelope = void 0;
25026
+ const response = await escrowRequest("", {
23808
25027
  method: "POST",
23809
25028
  headers: buildHeaders(token, vp, tenantId),
23810
25029
  body: JSON.stringify({
23811
25030
  authToken: token,
23812
25031
  providerType,
23813
- envelope,
25032
+ envelope: envelope2,
23814
25033
  shareVersion,
23815
25034
  enclaveKeyId: keyId,
23816
25035
  ...pinMaterial ? { pinSalt: pinMaterial.pinSalt } : {},
23817
- ...clearPin ? { clearPin: true } : {}
25036
+ ...(signedIntent ? signedIntent.intent.pinAction === "clear" : clearPin) ? { clearPin: true } : {},
25037
+ ...signedIntent ? { signedIntent, sourceEnvelope: authority?.envelope ?? null } : {}
23818
25038
  })
23819
25039
  });
25040
+ if (signedIntent) {
25041
+ const committed = await verifyEscrowEnrollmentCommit(
25042
+ response,
25043
+ signedIntent.intent,
25044
+ identity
25045
+ );
25046
+ assertCurrent();
25047
+ verifiedEscrowEnvelope = committed.envelope ?? void 0;
25048
+ }
23820
25049
  }, "enrollEscrow");
23821
25050
  const tryEnrollEscrow = /* @__PURE__ */ __name(async (...args) => {
23822
25051
  if (!config.escrow?.enabled) return;
23823
25052
  try {
23824
25053
  await enrollEscrow(...args);
23825
- } catch (err) {
25054
+ } catch (err2) {
23826
25055
  try {
23827
- if (config.onEscrowError) config.onEscrowError(err);
25056
+ if (config.onEscrowError) config.onEscrowError(err2);
23828
25057
  else console.warn("SSS: escrow enrollment failed");
23829
25058
  } catch {
23830
25059
  console.warn("SSS: escrow error reporting failed");
23831
25060
  }
23832
25061
  }
23833
25062
  }, "tryEnrollEscrow");
23834
- const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false) => {
25063
+ const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false, allowDisabledEnrollment = false) => {
25064
+ let clearPinForEnrollment = forceRotate;
23835
25065
  if (!config.escrow?.enabled) return { enrolled: false, reason: "disabled" };
23836
25066
  const pin = params.options?.pin;
25067
+ const recoveryEmail = params.options?.recoveryEmail ?? "";
25068
+ const recoveryLanguage = params.options?.recoveryLanguage ?? "";
23837
25069
  if (pin !== void 0) {
23838
25070
  const validation = validatePin(pin);
23839
25071
  if (!validation.ok)
@@ -23842,12 +25074,35 @@ function createSSSStrategy(config) {
23842
25074
  );
23843
25075
  }
23844
25076
  const status = await self.fetchServerKeyStatus(params.token, params.providerType);
25077
+ storage2.assertCurrent();
23845
25078
  if (status.escrowOptedOut) return { enrolled: false, reason: "opted-out" };
23846
- const currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
25079
+ let currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
23847
25080
  (method) => method.type === "escrow" && method.shareVersion === status.shareVersion && (Boolean(method.confirmedAt) || "confirmationStatus" in method && method.confirmationStatus === "confirmed")
23848
25081
  );
23849
- const repairingStaleBlob = pin === void 0 && !forceRotate && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
23850
- if (!forceRotate && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
25082
+ let verifiedKey;
25083
+ if (config.escrow.attestation.mode === "nitro") {
25084
+ if (!status.primaryDid || !params.signDidAuthVp)
25085
+ throw new Error("Owner proof signing is required for escrow enrollment.");
25086
+ verifiedKey = await fetchVerifiedEnclaveKey();
25087
+ const current = await fetchAuthorityState(
25088
+ params.token,
25089
+ params.providerType,
25090
+ params.privateKey,
25091
+ status.primaryDid,
25092
+ params.signDidAuthVp,
25093
+ verifiedKey,
25094
+ storage2.assertCurrent
25095
+ );
25096
+ if (current.status === "disabled") {
25097
+ verifiedEscrowEnvelope = void 0;
25098
+ if (!allowDisabledEnrollment) return { enrolled: false, reason: "opted-out" };
25099
+ clearPinForEnrollment ||= current.hasPin && pin === void 0;
25100
+ }
25101
+ currentlyEnrolled = currentlyEnrolled && current.status === "active" && current.shareVersion === status.shareVersion && current.envelope?.keyId === verifiedKey.keyId;
25102
+ if (currentlyEnrolled) verifiedEscrowEnvelope = current.envelope ?? void 0;
25103
+ }
25104
+ const repairingStaleBlob = pin === void 0 && !clearPinForEnrollment && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
25105
+ if (!clearPinForEnrollment && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
23851
25106
  return { enrolled: true, changed: false };
23852
25107
  if (repairingStaleBlob) staleEscrowReenrollAttempted = true;
23853
25108
  if (!status.primaryDid) throw new Error("Cannot enroll escrow without a primary DID");
@@ -23855,7 +25110,7 @@ function createSSSStrategy(config) {
23855
25110
  throw new Error("DID proof signing is required for escrow enrollment");
23856
25111
  }
23857
25112
  try {
23858
- if (!forceRotate && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
25113
+ if (!clearPinForEnrollment && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
23859
25114
  const retry = unenrolledRotation;
23860
25115
  await enrollEscrow(
23861
25116
  params.token,
@@ -23867,12 +25122,16 @@ function createSSSStrategy(config) {
23867
25122
  params.signDidAuthVp,
23868
25123
  void 0,
23869
25124
  void 0,
23870
- retry.clearPin
25125
+ retry.clearPin,
25126
+ storage2.assertCurrent,
25127
+ recoveryEmail,
25128
+ recoveryLanguage
23871
25129
  );
23872
25130
  unenrolledRotation = void 0;
23873
25131
  return { enrolled: true, changed: true, shareVersion: retry.shareVersion };
23874
25132
  }
23875
- const verifiedKey = await fetchVerifiedEnclaveKey();
25133
+ verifiedKey ??= await fetchVerifiedEnclaveKey();
25134
+ storage2.assertCurrent();
23876
25135
  const pinSalt = pin !== void 0 ? generatePinSalt() : void 0;
23877
25136
  const pinMaterial = pin !== void 0 && pinSalt !== void 0 ? { pinSalt, pinVerifier: await derivePinProof(pin, pinSalt) } : void 0;
23878
25137
  const storageId = activeStorageId;
@@ -23901,7 +25160,12 @@ function createSSSStrategy(config) {
23901
25160
  authShare: shares.authShare,
23902
25161
  primaryDid: status.primaryDid
23903
25162
  };
23904
- unenrolledRotation = pinMaterial ? void 0 : { shares, shareVersion, primaryDid: status.primaryDid, clearPin: forceRotate };
25163
+ unenrolledRotation = pinMaterial ? void 0 : {
25164
+ shares,
25165
+ shareVersion,
25166
+ primaryDid: status.primaryDid,
25167
+ clearPin: clearPinForEnrollment
25168
+ };
23905
25169
  await enrollEscrow(
23906
25170
  params.token,
23907
25171
  params.providerType,
@@ -23912,14 +25176,17 @@ function createSSSStrategy(config) {
23912
25176
  params.signDidAuthVp,
23913
25177
  verifiedKey,
23914
25178
  pinMaterial,
23915
- forceRotate
25179
+ clearPinForEnrollment,
25180
+ storage2.assertCurrent,
25181
+ recoveryEmail,
25182
+ recoveryLanguage
23916
25183
  );
23917
25184
  unenrolledRotation = void 0;
23918
25185
  return { enrolled: true, changed: true, shareVersion };
23919
- } catch (err) {
23920
- if (!repairingStaleBlob) throw err;
25186
+ } catch (err2) {
25187
+ if (!repairingStaleBlob || config.escrow.attestation.mode === "nitro") throw err2;
23921
25188
  try {
23922
- if (config.onEscrowError) config.onEscrowError(err);
25189
+ if (config.onEscrowError) config.onEscrowError(err2);
23923
25190
  else console.warn("SSS: escrow enrollment failed");
23924
25191
  } catch {
23925
25192
  console.warn("SSS: escrow error reporting failed");
@@ -23958,6 +25225,7 @@ function createSSSStrategy(config) {
23958
25225
  },
23959
25226
  // --- User scoping ---
23960
25227
  setActiveUser(userId) {
25228
+ verifiedEscrowEnvelope = void 0;
23961
25229
  if (activeStorageId !== `sss-device-share:${userId}`) storageGeneration++;
23962
25230
  activeStorageId = `sss-device-share:${userId}`;
23963
25231
  lastServerSnapshot = null;
@@ -24002,6 +25270,7 @@ function createSSSStrategy(config) {
24002
25270
  );
24003
25271
  }
24004
25272
  storageGeneration++;
25273
+ verifiedEscrowEnvelope = void 0;
24005
25274
  await Promise.allSettled(localWrites);
24006
25275
  await clearPendingShareCandidates(storage, storageId);
24007
25276
  return storage.clearAllShares(storageId);
@@ -24300,8 +25569,58 @@ function createSSSStrategy(config) {
24300
25569
  return { state: enrolled ? "enrolled" : "not-enrolled", escrowPin: status.escrowPin };
24301
25570
  },
24302
25571
  async disableEscrowRecovery(params) {
25572
+ const assertCurrent = guardedStorage().assertCurrent;
24303
25573
  const status = await this.fetchServerKeyStatus(params.token, params.providerType);
24304
25574
  if (!status.primaryDid) throw new Error("Cannot disable escrow without a primary DID");
25575
+ if (config.escrow?.attestation.mode === "nitro") {
25576
+ const identity = await fetchVerifiedEnclaveKey();
25577
+ const current = await fetchAuthorityState(
25578
+ params.token,
25579
+ params.providerType,
25580
+ params.privateKey,
25581
+ status.primaryDid,
25582
+ params.signDidAuthVp,
25583
+ identity,
25584
+ assertCurrent
25585
+ );
25586
+ if (current.status === "disabled") {
25587
+ verifiedEscrowEnvelope = void 0;
25588
+ return;
25589
+ }
25590
+ const signedIntent = await createEscrowEnrollmentIntent({
25591
+ state: current,
25592
+ target: null,
25593
+ shareVersion: current.shareVersion ?? 0,
25594
+ privateKey: params.privateKey,
25595
+ pinAction: "disable",
25596
+ // Disable always nulls these server-side regardless of input.
25597
+ recoveryEmail: "",
25598
+ recoveryLanguage: ""
25599
+ });
25600
+ const vp2 = await requestFreshDidAuthVp(
25601
+ serverUrl,
25602
+ params.privateKey,
25603
+ status.primaryDid,
25604
+ params.signDidAuthVp,
25605
+ tenantId
25606
+ );
25607
+ assertCurrent();
25608
+ const response = await escrowRequest("/disable", {
25609
+ method: "POST",
25610
+ headers: buildHeaders(params.token, vp2, tenantId),
25611
+ body: JSON.stringify({
25612
+ authToken: params.token,
25613
+ providerType: params.providerType,
25614
+ optOut: true,
25615
+ signedIntent,
25616
+ sourceEnvelope: current.envelope
25617
+ })
25618
+ });
25619
+ await verifyEscrowEnrollmentCommit(response, signedIntent.intent, identity);
25620
+ assertCurrent();
25621
+ verifiedEscrowEnvelope = void 0;
25622
+ return;
25623
+ }
24305
25624
  const vp = await requestFreshDidAuthVp(
24306
25625
  serverUrl,
24307
25626
  params.privateKey,
@@ -24342,13 +25661,29 @@ function createSSSStrategy(config) {
24342
25661
  providerType: params.providerType
24343
25662
  })
24344
25663
  });
24345
- return ensureEscrowEnrollmentUnguarded(this, params, storage2);
25664
+ return ensureEscrowEnrollmentUnguarded(this, params, storage2, false, true);
24346
25665
  });
24347
25666
  },
24348
25667
  async setEscrowPin({ pin, ...params }) {
24349
25668
  const storage2 = guardedStorage();
24350
25669
  const result = await withRotationLock(
24351
- () => ensureEscrowEnrollmentUnguarded(this, { ...params, options: { pin } }, storage2)
25670
+ () => (
25671
+ // P9.1: preserve the caller's recoveryEmail/recoveryLanguage — do
25672
+ // not replace `params.options` wholesale, or nitro enroll/replace
25673
+ // loses its required recovery contact.
25674
+ ensureEscrowEnrollmentUnguarded(
25675
+ this,
25676
+ {
25677
+ ...params,
25678
+ options: {
25679
+ pin,
25680
+ recoveryEmail: params.options?.recoveryEmail,
25681
+ recoveryLanguage: params.options?.recoveryLanguage
25682
+ }
25683
+ },
25684
+ storage2
25685
+ )
25686
+ )
24352
25687
  );
24353
25688
  if (!result.enrolled || !result.changed) {
24354
25689
  throw new Error("Automatic recovery is not available for this account.");
@@ -24380,8 +25715,15 @@ function createSSSStrategy(config) {
24380
25715
  escrowEnrollmentInFlight = void 0;
24381
25716
  }
24382
25717
  },
25718
+ getVerifiedEscrowEnvelope() {
25719
+ return verifiedEscrowEnvelope ? { ...verifiedEscrowEnvelope } : null;
25720
+ },
24383
25721
  /** Start or explicitly restart a hold with fresh client-bound resume secrets. */
24384
25722
  async startEscrowRecovery(params) {
25723
+ const expectedDid = params.expectedDid;
25724
+ const nitro = config.escrow?.attestation.mode === "nitro";
25725
+ if (nitro && (!expectedDid || (params.tenantId ?? tenantId) !== tenantId))
25726
+ throw new EscrowEvidenceError();
24385
25727
  const sessionProof = params.recoverySessionToken !== void 0;
24386
25728
  if (sessionProof ? params.token !== void 0 || params.providerType !== void 0 : !params.token || !params.providerType) {
24387
25729
  throw new Error("Provide exactly one identity proof");
@@ -24401,25 +25743,102 @@ function createSSSStrategy(config) {
24401
25743
  },
24402
25744
  params.options?.releasePolicy === "pin"
24403
25745
  );
24404
- return { ...result, clientEphemeralPrivateKey: pair.privateKey };
25746
+ let expectations;
25747
+ if (nitro && result.resumeToken !== null) {
25748
+ const identity = await fetchVerifiedEnclaveKey();
25749
+ if (identity.mode !== "nitro" || !identity.authority || !result.holdRecord || !expectedDid)
25750
+ throw new EscrowEvidenceError();
25751
+ const verified = await verifyEscrowHoldRecord(
25752
+ result.holdRecord,
25753
+ {
25754
+ tenant: tenantId ?? "learncard",
25755
+ did: expectedDid,
25756
+ holdId: result.holdId,
25757
+ clientEphemeralPublicKey: pair.publicKey,
25758
+ blobHash: result.holdRecord.hold.blobHash
25759
+ },
25760
+ identity
25761
+ );
25762
+ expectations = {
25763
+ tenant: tenantId ?? "learncard",
25764
+ did: expectedDid,
25765
+ holdId: result.holdId,
25766
+ clientEphemeralPublicKey: pair.publicKey,
25767
+ blobHash: result.holdRecord.hold.blobHash,
25768
+ authorityGeneration: verified.authorityGeneration,
25769
+ holdDigest: verified.holdDigest,
25770
+ ledgerPublicKey: identity.authority.ledgerPublicKey,
25771
+ keyId: verified.receipt.keyId
25772
+ };
25773
+ result.codeSent = result.delivery ? await verifyEscrowCodeDelivery(result.delivery, expectations, identity) : void 0;
25774
+ }
25775
+ return { ...result, clientEphemeralPrivateKey: pair.privateKey, expectations };
24405
25776
  },
24406
25777
  /** Read hold status; secrets (auth or resume token) never travel in a URL. */
24407
25778
  async getEscrowRecoveryStatus(params) {
24408
- const query = new URLSearchParams(
24409
- "holdId" in params ? { holdId: params.holdId } : { providerType: params.providerType }
24410
- );
24411
- const secret = "holdId" in params ? params.resumeToken : params.token;
24412
- const result = await escrowRequest(
24413
- `/status?${query}`,
24414
- {
24415
- method: "GET",
24416
- headers: {
24417
- ...buildHeaders("", void 0, tenantId),
24418
- "X-Auth-Token": secret
24419
- }
25779
+ const expected = config.escrow?.attestation.mode === "nitro" && "holdId" in params ? recoveryExpectations(params.holdId, params.expectations) : void 0;
25780
+ const status = await fetchEscrowHoldStatus(params);
25781
+ if (expected && status)
25782
+ await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
25783
+ return status;
25784
+ },
25785
+ /** Submit the confirmation code emailed by the enclave for an authority-mode hold. */
25786
+ async confirmEscrowRecovery(params) {
25787
+ let pending;
25788
+ if (config.escrow?.attestation.mode === "nitro") {
25789
+ const expected = recoveryExpectations(params.holdId, params.expectations);
25790
+ if ((params.tenantId ?? tenantId) !== tenantId) throw new EscrowEvidenceError();
25791
+ const identity = await fetchVerifiedEnclaveKey();
25792
+ const status = await fetchEscrowHoldStatus({
25793
+ holdId: params.holdId,
25794
+ resumeToken: params.resumeToken
25795
+ });
25796
+ if (!status?.holdRecord) {
25797
+ throw new EscrowEvidenceError();
24420
25798
  }
24421
- );
24422
- return result.hold;
25799
+ const holdRecord = await verifyPendingHold(status, expected, identity);
25800
+ pending = { identity, holdRecord, expected };
25801
+ }
25802
+ const confirm = /* @__PURE__ */ __name(() => escrowRequest("/confirm", {
25803
+ method: "POST",
25804
+ headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
25805
+ body: JSON.stringify({
25806
+ holdId: params.holdId,
25807
+ resumeToken: params.resumeToken,
25808
+ code: params.code
25809
+ })
25810
+ }), "confirm");
25811
+ const result = await confirm();
25812
+ if (pending) {
25813
+ if (!result.receipt) {
25814
+ throw new EscrowEvidenceError();
25815
+ }
25816
+ const receipt = await verifyEscrowHoldConfirmation(
25817
+ result.receipt,
25818
+ pending.holdRecord,
25819
+ pending.expected,
25820
+ pending.identity
25821
+ );
25822
+ if (receipt.kind === "commit") {
25823
+ const readback = await confirm();
25824
+ const snapshot = await verifyEscrowHoldConfirmation(
25825
+ readback.receipt,
25826
+ pending.holdRecord,
25827
+ pending.expected,
25828
+ pending.identity
25829
+ );
25830
+ if (snapshot.kind !== "snapshot") throw new EscrowEvidenceError();
25831
+ }
25832
+ }
25833
+ return { success: true };
25834
+ },
25835
+ /** Request a fresh confirmation code for a hold awaiting confirmation. */
25836
+ async resendEscrowRecoveryCode(params) {
25837
+ return escrowRequest("/resend", {
25838
+ method: "POST",
25839
+ headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
25840
+ body: JSON.stringify({ holdId: params.holdId, resumeToken: params.resumeToken })
25841
+ });
24423
25842
  },
24424
25843
  /** Cancel a pending hold with a fresh DID-owner proof. */
24425
25844
  async cancelEscrowRecovery(params) {
@@ -24451,8 +25870,19 @@ function createSSSStrategy(config) {
24451
25870
  const start = input.method === "escrow-pin" ? await this.startEscrowRecovery({
24452
25871
  token,
24453
25872
  providerType,
25873
+ expectedDid: input.expectedDid,
24454
25874
  options: { releasePolicy: "pin" }
24455
25875
  }) : input;
25876
+ const expected = config.escrow?.attestation.mode === "nitro" ? recoveryExpectations(start.holdId, start.expectations) : void 0;
25877
+ if (expected) {
25878
+ if (!start.resumeToken) throw new EscrowEvidenceError();
25879
+ const status = await fetchEscrowHoldStatus({
25880
+ holdId: start.holdId,
25881
+ resumeToken: start.resumeToken
25882
+ });
25883
+ if (!status) throw new EscrowEvidenceError();
25884
+ await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
25885
+ }
24456
25886
  let pinProof;
24457
25887
  if (input.method === "escrow-pin") {
24458
25888
  if (!("pinSalt" in start) || !start.pinSalt || !start.resumeToken)
@@ -24476,6 +25906,8 @@ function createSSSStrategy(config) {
24476
25906
  material.sealedShare,
24477
25907
  start.clientEphemeralPrivateKey
24478
25908
  );
25909
+ if (expected && (plaintext.did !== expected.did || plaintext.holdId !== expected.holdId))
25910
+ throw new EscrowEvidenceError();
24479
25911
  if (plaintext.holdId !== start.holdId || plaintext.did !== material.primaryDid || plaintext.shareVersion !== material.shareVersion) {
24480
25912
  throw new Error("Escrow recovery material does not match the request");
24481
25913
  }
@@ -24889,10 +26321,10 @@ function createSSSStrategy(config) {
24889
26321
  const pending = pendingPhraseConfirmation;
24890
26322
  if (!pending) throw new Error("Generate a new recovery phrase to continue");
24891
26323
  const phraseWords = pending.phrase.trim().toLowerCase().split(/\s+/);
24892
- const matches = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
26324
+ const matches2 = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
24893
26325
  (wordIndex, answerIndex) => input.challengeWords[answerIndex]?.trim().toLowerCase() === phraseWords[wordIndex]
24894
26326
  );
24895
- if (!matches) {
26327
+ if (!matches2) {
24896
26328
  throw new Error("Those words do not match. Check your phrase and try again.");
24897
26329
  }
24898
26330
  } else if (input.method === "backup") {
@@ -25278,6 +26710,7 @@ function createSSSStrategy(config) {
25278
26710
  },
25279
26711
  async cleanup() {
25280
26712
  storageGeneration++;
26713
+ verifiedEscrowEnvelope = void 0;
25281
26714
  await Promise.allSettled(localWrites);
25282
26715
  }
25283
26716
  };
@@ -25498,3 +26931,8 @@ var notifyDevicesForQrSession = /* @__PURE__ */ __name(async (config, sessionId,
25498
26931
  return { sent: false, deviceCount: 0 };
25499
26932
  }
25500
26933
  }, "notifyDevicesForQrSession");
26934
+ /*! Bundled license information:
26935
+
26936
+ @noble/ed25519/index.js:
26937
+ (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
26938
+ */