@learncard/sss-key-manager 0.2.1 → 0.2.2

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 (44) 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 +112 -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 +1592 -213
  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 +1107 -163
  22. package/dist/sss-key-manager.esm.js.map +4 -4
  23. package/dist/sss-strategy.d.ts.map +1 -1
  24. package/dist/types.d.ts +16 -1
  25. package/dist/types.d.ts.map +1 -1
  26. package/package.json +2 -2
  27. package/src/__fixtures__/escrow-authority-v1.json +96 -0
  28. package/src/__fixtures__/escrow-carry-contact-contract-v1.json +33 -0
  29. package/src/__fixtures__/escrow-enrollment-intent-v1.json +26 -0
  30. package/src/__fixtures__/nitro-attestation-real/staging-nsm-document.json +16 -0
  31. package/src/escrow-attestation.ts +10 -9
  32. package/src/escrow-authority.test.ts +643 -0
  33. package/src/escrow-authority.ts +597 -0
  34. package/src/escrow-authority.types.ts +56 -0
  35. package/src/escrow-crypto.ts +39 -1
  36. package/src/escrow-enrollment-intent.test.ts +224 -0
  37. package/src/escrow-enrollment-intent.ts +236 -0
  38. package/src/escrow-enrollment-intent.types.ts +28 -0
  39. package/src/escrow-nitro-attestation.test.ts +72 -0
  40. package/src/escrow-nitro-attestation.ts +34 -3
  41. package/src/index.ts +27 -0
  42. package/src/sss-authority.test.ts +889 -0
  43. package/src/sss-strategy.ts +479 -38
  44. package/src/types.ts +22 -3
@@ -574,7 +574,7 @@ var require_types_cjs_development = __commonJS({
574
574
  _function: /* @__PURE__ */ __name(() => _function, "_function"),
575
575
  any: /* @__PURE__ */ __name(() => any, "any"),
576
576
  array: /* @__PURE__ */ __name(() => array, "array"),
577
- base64: /* @__PURE__ */ __name(() => base642, "base64"),
577
+ base64: /* @__PURE__ */ __name(() => base6422, "base64"),
578
578
  base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
579
579
  bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
580
580
  boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
@@ -615,7 +615,7 @@ var require_types_cjs_development = __commonJS({
615
615
  gt: /* @__PURE__ */ __name(() => _gt, "gt"),
616
616
  gte: /* @__PURE__ */ __name(() => _gte, "gte"),
617
617
  guid: /* @__PURE__ */ __name(() => guid2, "guid"),
618
- hash: /* @__PURE__ */ __name(() => hash, "hash"),
618
+ hash: /* @__PURE__ */ __name(() => hash2, "hash"),
619
619
  hex: /* @__PURE__ */ __name(() => hex22, "hex"),
620
620
  hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
621
621
  httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
@@ -664,7 +664,7 @@ var require_types_cjs_development = __commonJS({
664
664
  nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
665
665
  nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
666
666
  number: /* @__PURE__ */ __name(() => number2, "number"),
667
- object: /* @__PURE__ */ __name(() => object, "object"),
667
+ object: /* @__PURE__ */ __name(() => object2, "object"),
668
668
  optional: /* @__PURE__ */ __name(() => optional, "optional"),
669
669
  overwrite: /* @__PURE__ */ __name(() => _overwrite, "overwrite"),
670
670
  parse: /* @__PURE__ */ __name(() => parse2, "parse"),
@@ -1003,7 +1003,7 @@ var require_types_cjs_development = __commonJS({
1003
1003
  util: /* @__PURE__ */ __name(() => util_exports, "util"),
1004
1004
  version: /* @__PURE__ */ __name(() => version, "version")
1005
1005
  });
1006
- var _a;
1006
+ var _a2;
1007
1007
  var NEVER = /* @__PURE__ */ Object.freeze({
1008
1008
  status: "aborted"
1009
1009
  });
@@ -1026,9 +1026,9 @@ var require_types_cjs_development = __commonJS({
1026
1026
  inst._zod.traits.add(name);
1027
1027
  initializer3(inst, def);
1028
1028
  const proto = _.prototype;
1029
- const keys = Object.keys(proto);
1030
- for (let i = 0; i < keys.length; i++) {
1031
- const k = keys[i];
1029
+ const keys2 = Object.keys(proto);
1030
+ for (let i = 0; i < keys2.length; i++) {
1031
+ const k = keys2[i];
1032
1032
  if (!(k in inst)) {
1033
1033
  inst[k] = proto[k].bind(inst);
1034
1034
  }
@@ -1095,7 +1095,7 @@ var require_types_cjs_development = __commonJS({
1095
1095
  this.name = "ZodEncodeError";
1096
1096
  }
1097
1097
  };
1098
- (_a = globalThis).__zod_globalConfig ?? (_a.__zod_globalConfig = {});
1098
+ (_a2 = globalThis).__zod_globalConfig ?? (_a2.__zod_globalConfig = {});
1099
1099
  var globalConfig = globalThis.__zod_globalConfig;
1100
1100
  function config(newConfig) {
1101
1101
  if (newConfig)
@@ -1250,9 +1250,9 @@ var require_types_cjs_development = __commonJS({
1250
1250
  __name(floatSafeRemainder, "floatSafeRemainder");
1251
1251
  __name2(floatSafeRemainder, "floatSafeRemainder");
1252
1252
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
1253
- function defineLazy(object2, key, getter) {
1253
+ function defineLazy(object22, key, getter) {
1254
1254
  let value = void 0;
1255
- Object.defineProperty(object2, key, {
1255
+ Object.defineProperty(object22, key, {
1256
1256
  get() {
1257
1257
  if (value === EVALUATING) {
1258
1258
  return void 0;
@@ -1264,7 +1264,7 @@ var require_types_cjs_development = __commonJS({
1264
1264
  return value;
1265
1265
  },
1266
1266
  set(v) {
1267
- Object.defineProperty(object2, key, {
1267
+ Object.defineProperty(object22, key, {
1268
1268
  value: v
1269
1269
  // configurable: true,
1270
1270
  });
@@ -1312,12 +1312,12 @@ var require_types_cjs_development = __commonJS({
1312
1312
  __name(getElementAtPath, "getElementAtPath");
1313
1313
  __name2(getElementAtPath, "getElementAtPath");
1314
1314
  function promiseAllObject(promisesObj) {
1315
- const keys = Object.keys(promisesObj);
1316
- const promises = keys.map((key) => promisesObj[key]);
1315
+ const keys2 = Object.keys(promisesObj);
1316
+ const promises = keys2.map((key) => promisesObj[key]);
1317
1317
  return Promise.all(promises).then((results) => {
1318
1318
  const resolvedObj = {};
1319
- for (let i = 0; i < keys.length; i++) {
1320
- resolvedObj[keys[i]] = results[i];
1319
+ for (let i = 0; i < keys2.length; i++) {
1320
+ resolvedObj[keys2[i]] = results[i];
1321
1321
  }
1322
1322
  return resolvedObj;
1323
1323
  });
@@ -1857,18 +1857,18 @@ var require_types_cjs_development = __commonJS({
1857
1857
  __name2(cleanEnum, "cleanEnum");
1858
1858
  function base64ToUint8Array(base643) {
1859
1859
  const binaryString = atob(base643);
1860
- const bytes2 = new Uint8Array(binaryString.length);
1860
+ const bytes3 = new Uint8Array(binaryString.length);
1861
1861
  for (let i = 0; i < binaryString.length; i++) {
1862
- bytes2[i] = binaryString.charCodeAt(i);
1862
+ bytes3[i] = binaryString.charCodeAt(i);
1863
1863
  }
1864
- return bytes2;
1864
+ return bytes3;
1865
1865
  }
1866
1866
  __name(base64ToUint8Array, "base64ToUint8Array");
1867
1867
  __name2(base64ToUint8Array, "base64ToUint8Array");
1868
- function uint8ArrayToBase64(bytes2) {
1868
+ function uint8ArrayToBase64(bytes3) {
1869
1869
  let binaryString = "";
1870
- for (let i = 0; i < bytes2.length; i++) {
1871
- binaryString += String.fromCharCode(bytes2[i]);
1870
+ for (let i = 0; i < bytes3.length; i++) {
1871
+ binaryString += String.fromCharCode(bytes3[i]);
1872
1872
  }
1873
1873
  return btoa(binaryString);
1874
1874
  }
@@ -1881,8 +1881,8 @@ var require_types_cjs_development = __commonJS({
1881
1881
  }
1882
1882
  __name(base64urlToUint8Array, "base64urlToUint8Array");
1883
1883
  __name2(base64urlToUint8Array, "base64urlToUint8Array");
1884
- function uint8ArrayToBase64url(bytes2) {
1885
- return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1884
+ function uint8ArrayToBase64url(bytes3) {
1885
+ return uint8ArrayToBase64(bytes3).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1886
1886
  }
1887
1887
  __name(uint8ArrayToBase64url, "uint8ArrayToBase64url");
1888
1888
  __name2(uint8ArrayToBase64url, "uint8ArrayToBase64url");
@@ -1891,16 +1891,16 @@ var require_types_cjs_development = __commonJS({
1891
1891
  if (cleanHex.length % 2 !== 0) {
1892
1892
  throw new Error("Invalid hex string length");
1893
1893
  }
1894
- const bytes2 = new Uint8Array(cleanHex.length / 2);
1894
+ const bytes3 = new Uint8Array(cleanHex.length / 2);
1895
1895
  for (let i = 0; i < cleanHex.length; i += 2) {
1896
- bytes2[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1896
+ bytes3[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1897
1897
  }
1898
- return bytes2;
1898
+ return bytes3;
1899
1899
  }
1900
1900
  __name(hexToUint8Array, "hexToUint8Array");
1901
1901
  __name2(hexToUint8Array, "hexToUint8Array");
1902
- function uint8ArrayToHex(bytes2) {
1903
- return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
1902
+ function uint8ArrayToHex(bytes3) {
1903
+ return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
1904
1904
  }
1905
1905
  __name(uint8ArrayToHex, "uint8ArrayToHex");
1906
1906
  __name2(uint8ArrayToHex, "uint8ArrayToHex");
@@ -2149,7 +2149,7 @@ var require_types_cjs_development = __commonJS({
2149
2149
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
2150
2150
  var regexes_exports = {};
2151
2151
  __export2(regexes_exports, {
2152
- base64: /* @__PURE__ */ __name(() => base64, "base64"),
2152
+ base64: /* @__PURE__ */ __name(() => base642, "base64"),
2153
2153
  base64url: /* @__PURE__ */ __name(() => base64url, "base64url"),
2154
2154
  bigint: /* @__PURE__ */ __name(() => bigint, "bigint"),
2155
2155
  boolean: /* @__PURE__ */ __name(() => boolean, "boolean"),
@@ -2172,7 +2172,7 @@ var require_types_cjs_development = __commonJS({
2172
2172
  html5Email: /* @__PURE__ */ __name(() => html5Email, "html5Email"),
2173
2173
  httpProtocol: /* @__PURE__ */ __name(() => httpProtocol, "httpProtocol"),
2174
2174
  idnEmail: /* @__PURE__ */ __name(() => idnEmail, "idnEmail"),
2175
- integer: /* @__PURE__ */ __name(() => integer, "integer"),
2175
+ integer: /* @__PURE__ */ __name(() => integer3, "integer"),
2176
2176
  ipv4: /* @__PURE__ */ __name(() => ipv4, "ipv4"),
2177
2177
  ipv6: /* @__PURE__ */ __name(() => ipv6, "ipv6"),
2178
2178
  ksuid: /* @__PURE__ */ __name(() => ksuid, "ksuid"),
@@ -2246,7 +2246,7 @@ var require_types_cjs_development = __commonJS({
2246
2246
  }, "mac");
2247
2247
  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
2248
  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}=))?$/;
2249
+ var base642 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
2250
2250
  var base64url = /^[A-Za-z0-9_-]*$/;
2251
2251
  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
2252
  var domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
@@ -2283,7 +2283,7 @@ var require_types_cjs_development = __commonJS({
2283
2283
  return new RegExp(`^${regex}$`);
2284
2284
  }, "string");
2285
2285
  var bigint = /^-?\d+n?$/;
2286
- var integer = /^-?\d+$/;
2286
+ var integer3 = /^-?\d+$/;
2287
2287
  var number = /^-?\d+(?:\.\d+)?$/;
2288
2288
  var boolean = /^(?:true|false)$/i;
2289
2289
  var _null = /^null$/i;
@@ -2417,7 +2417,7 @@ var require_types_cjs_development = __commonJS({
2417
2417
  bag.minimum = minimum;
2418
2418
  bag.maximum = maximum;
2419
2419
  if (isInt)
2420
- bag.pattern = integer;
2420
+ bag.pattern = integer3;
2421
2421
  });
2422
2422
  inst._zod.check = (payload) => {
2423
2423
  const input = payload.value;
@@ -3257,7 +3257,7 @@ var require_types_cjs_development = __commonJS({
3257
3257
  __name(isValidBase64, "isValidBase64");
3258
3258
  __name2(isValidBase64, "isValidBase64");
3259
3259
  var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
3260
- def.pattern ?? (def.pattern = base64);
3260
+ def.pattern ?? (def.pattern = base642);
3261
3261
  $ZodStringFormat.init(inst, def);
3262
3262
  inst._zod.bag.contentEncoding = "base64";
3263
3263
  inst._zod.check = (payload) => {
@@ -3603,8 +3603,8 @@ var require_types_cjs_development = __commonJS({
3603
3603
  __name(handlePropertyResult, "handlePropertyResult");
3604
3604
  __name2(handlePropertyResult, "handlePropertyResult");
3605
3605
  function normalizeDef(def) {
3606
- const keys = Object.keys(def.shape);
3607
- for (const k of keys) {
3606
+ const keys2 = Object.keys(def.shape);
3607
+ for (const k of keys2) {
3608
3608
  if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
3609
3609
  throw new Error(`Invalid element at key "${k}": expected a Zod schema`);
3610
3610
  }
@@ -3612,9 +3612,9 @@ var require_types_cjs_development = __commonJS({
3612
3612
  const okeys = optionalKeys(def.shape);
3613
3613
  return {
3614
3614
  ...def,
3615
- keys,
3616
- keySet: new Set(keys),
3617
- numKeys: keys.length,
3615
+ keys: keys2,
3616
+ keySet: new Set(keys2),
3617
+ numKeys: keys2.length,
3618
3618
  optionalKeys: new Set(okeys)
3619
3619
  };
3620
3620
  }
@@ -8376,8 +8376,8 @@ var require_types_cjs_development = __commonJS({
8376
8376
  }
8377
8377
  __name(ko_default, "ko_default");
8378
8378
  __name2(ko_default, "default");
8379
- var capitalizeFirstCharacter = /* @__PURE__ */ __name2((text) => {
8380
- return text.charAt(0).toUpperCase() + text.slice(1);
8379
+ var capitalizeFirstCharacter = /* @__PURE__ */ __name2((text2) => {
8380
+ return text2.charAt(0).toUpperCase() + text2.slice(1);
8381
8381
  }, "capitalizeFirstCharacter");
8382
8382
  function getUnitTypeFromNumber(number4) {
8383
8383
  const abs = Math.abs(number4);
@@ -11109,7 +11109,7 @@ var require_types_cjs_development = __commonJS({
11109
11109
  }
11110
11110
  __name(yo_default, "yo_default");
11111
11111
  __name2(yo_default, "default");
11112
- var _a2;
11112
+ var _a22;
11113
11113
  var $output = /* @__PURE__ */ Symbol("ZodOutput");
11114
11114
  var $input = /* @__PURE__ */ Symbol("ZodInput");
11115
11115
  var $ZodRegistry = class {
@@ -11163,7 +11163,7 @@ var require_types_cjs_development = __commonJS({
11163
11163
  }
11164
11164
  __name(registry, "registry");
11165
11165
  __name2(registry, "registry");
11166
- (_a2 = globalThis).__zod_globalRegistry ?? (_a2.__zod_globalRegistry = registry());
11166
+ (_a22 = globalThis).__zod_globalRegistry ?? (_a22.__zod_globalRegistry = registry());
11167
11167
  var globalRegistry = globalThis.__zod_globalRegistry;
11168
11168
  // @__NO_SIDE_EFFECTS__
11169
11169
  function _string(Class2, params) {
@@ -13497,7 +13497,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13497
13497
  _function: /* @__PURE__ */ __name(() => _function, "_function"),
13498
13498
  any: /* @__PURE__ */ __name(() => any, "any"),
13499
13499
  array: /* @__PURE__ */ __name(() => array, "array"),
13500
- base64: /* @__PURE__ */ __name(() => base642, "base64"),
13500
+ base64: /* @__PURE__ */ __name(() => base6422, "base64"),
13501
13501
  base64url: /* @__PURE__ */ __name(() => base64url2, "base64url"),
13502
13502
  bigint: /* @__PURE__ */ __name(() => bigint2, "bigint"),
13503
13503
  boolean: /* @__PURE__ */ __name(() => boolean2, "boolean"),
@@ -13522,7 +13522,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13522
13522
  float64: /* @__PURE__ */ __name(() => float64, "float64"),
13523
13523
  function: /* @__PURE__ */ __name(() => _function, "function"),
13524
13524
  guid: /* @__PURE__ */ __name(() => guid2, "guid"),
13525
- hash: /* @__PURE__ */ __name(() => hash, "hash"),
13525
+ hash: /* @__PURE__ */ __name(() => hash2, "hash"),
13526
13526
  hex: /* @__PURE__ */ __name(() => hex22, "hex"),
13527
13527
  hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
13528
13528
  httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
@@ -13554,7 +13554,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13554
13554
  nullable: /* @__PURE__ */ __name(() => nullable, "nullable"),
13555
13555
  nullish: /* @__PURE__ */ __name(() => nullish2, "nullish"),
13556
13556
  number: /* @__PURE__ */ __name(() => number2, "number"),
13557
- object: /* @__PURE__ */ __name(() => object, "object"),
13557
+ object: /* @__PURE__ */ __name(() => object2, "object"),
13558
13558
  optional: /* @__PURE__ */ __name(() => optional, "optional"),
13559
13559
  partialRecord: /* @__PURE__ */ __name(() => partialRecord, "partialRecord"),
13560
13560
  pipe: /* @__PURE__ */ __name(() => pipe, "pipe"),
@@ -14155,11 +14155,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14155
14155
  $ZodBase64.init(inst, def);
14156
14156
  ZodStringFormat.init(inst, def);
14157
14157
  });
14158
- function base642(params) {
14158
+ function base6422(params) {
14159
14159
  return /* @__PURE__ */ _base64(ZodBase64, params);
14160
14160
  }
14161
- __name(base642, "base642");
14162
- __name2(base642, "base64");
14161
+ __name(base6422, "base642");
14162
+ __name2(base6422, "base64");
14163
14163
  var ZodBase64URL = /* @__PURE__ */ $constructor("ZodBase64URL", (inst, def) => {
14164
14164
  $ZodBase64URL.init(inst, def);
14165
14165
  ZodStringFormat.init(inst, def);
@@ -14206,7 +14206,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14206
14206
  }
14207
14207
  __name(hex22, "hex2");
14208
14208
  __name2(hex22, "hex");
14209
- function hash(alg, params) {
14209
+ function hash2(alg, params) {
14210
14210
  const enc = params?.enc ?? "hex";
14211
14211
  const format = `${alg}_${enc}`;
14212
14212
  const regex = regexes_exports[format];
@@ -14214,8 +14214,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14214
14214
  throw new Error(`Unrecognized hash format: ${format}`);
14215
14215
  return /* @__PURE__ */ _stringFormat(ZodCustomStringFormat, format, regex, params);
14216
14216
  }
14217
- __name(hash, "hash");
14218
- __name2(hash, "hash");
14217
+ __name(hash2, "hash");
14218
+ __name2(hash2, "hash");
14219
14219
  var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
14220
14220
  $ZodNumber.init(inst, def);
14221
14221
  ZodType.init(inst, def);
@@ -14527,7 +14527,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14527
14527
  }
14528
14528
  });
14529
14529
  });
14530
- function object(shape, params) {
14530
+ function object2(shape, params) {
14531
14531
  const def = {
14532
14532
  type: "object",
14533
14533
  shape: shape ?? {},
@@ -14535,8 +14535,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14535
14535
  };
14536
14536
  return new ZodObject(def);
14537
14537
  }
14538
- __name(object, "object");
14539
- __name2(object, "object");
14538
+ __name(object2, "object");
14539
+ __name2(object2, "object");
14540
14540
  function strictObject(shape, params) {
14541
14541
  return new ZodObject({
14542
14542
  type: "object",
@@ -14731,11 +14731,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14731
14731
  inst._zod.processJSONSchema = (ctx, json2, params) => enumProcessor(inst, ctx, json2, params);
14732
14732
  inst.enum = def.entries;
14733
14733
  inst.options = Object.values(def.entries);
14734
- const keys = new Set(Object.keys(def.entries));
14734
+ const keys2 = new Set(Object.keys(def.entries));
14735
14735
  inst.extract = (values, params) => {
14736
14736
  const newEntries = {};
14737
14737
  for (const value of values) {
14738
- if (keys.has(value)) {
14738
+ if (keys2.has(value)) {
14739
14739
  newEntries[value] = def.entries[value];
14740
14740
  } else
14741
14741
  throw new Error(`Key ${value} not found in enum`);
@@ -14750,7 +14750,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14750
14750
  inst.exclude = (values, params) => {
14751
14751
  const newEntries = { ...def.entries };
14752
14752
  for (const value of values) {
14753
- if (keys.has(value)) {
14753
+ if (keys2.has(value)) {
14754
14754
  delete newEntries[value];
14755
14755
  } else
14756
14756
  throw new Error(`Key ${value} not found in enum`);
@@ -15886,7 +15886,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15886
15886
  verificationMethod: external_exports.string(),
15887
15887
  jws: external_exports.string().optional()
15888
15888
  }).catchall(external_exports.any()).superRefine((proof, ctx) => {
15889
- if (proof.created === void 0 && (proof.type !== "DataIntegrityProof" || proof.cryptosuite !== "ecdsa-rdfc-2019")) {
15889
+ if (proof.created === void 0 && // These standardized Data Integrity suites make created optional.
15890
+ // Keep the prior requirement for legacy and unknown proof suites.
15891
+ // https://www.w3.org/TR/vc-di-eddsa/#proof-configuration-eddsa-jcs-2022
15892
+ // https://www.w3.org/TR/vc-di-bbs/#proof-configuration
15893
+ (proof.type !== "DataIntegrityProof" || ![
15894
+ "ecdsa-rdfc-2019",
15895
+ "ecdsa-jcs-2019",
15896
+ "ecdsa-sd-2023",
15897
+ "eddsa-rdfc-2022",
15898
+ "eddsa-jcs-2022",
15899
+ "bbs-2023"
15900
+ ].includes(proof.cryptosuite))) {
15890
15901
  ctx.addIssue({
15891
15902
  code: "custom",
15892
15903
  path: ["created"],
@@ -18525,12 +18536,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18525
18536
  }
18526
18537
  return table;
18527
18538
  })();
18528
- var encodeBase64Url = /* @__PURE__ */ __name2((bytes2) => {
18539
+ var encodeBase64Url = /* @__PURE__ */ __name2((bytes3) => {
18529
18540
  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];
18541
+ for (let index = 0; index < bytes3.length; index += 3) {
18542
+ const first = bytes3[index];
18543
+ const second = bytes3[index + 1];
18544
+ const third = bytes3[index + 2];
18534
18545
  output += BASE64URL_ALPHABET[first >> 2];
18535
18546
  output += BASE64URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
18536
18547
  if (second === void 0) break;
@@ -18571,8 +18582,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18571
18582
  }, "isCanonicalBase64Url");
18572
18583
  var decodedBase64UrlByteLength = /* @__PURE__ */ __name2((value) => decodeBase64Url(value)?.length ?? null, "decodedBase64UrlByteLength");
18573
18584
  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`
18585
+ var canonicalBase64Url = /* @__PURE__ */ __name2((bytes3) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes3), {
18586
+ message: `must be canonical base64url for exactly ${bytes3} bytes`
18576
18587
  }), "canonicalBase64Url");
18577
18588
  var ShareLinkIdValidator = canonicalBase64Url(SHARE_LINK_ID_BYTES);
18578
18589
  var ShareContentKeyValidator = canonicalBase64Url(SHARE_CONTENT_KEY_BYTES);
@@ -19025,9 +19036,11 @@ __export(index_exports, {
19025
19036
  ESCROW_ALGORITHM: () => ESCROW_ALGORITHM,
19026
19037
  ESCROW_BLOB_INFO: () => ESCROW_BLOB_INFO,
19027
19038
  ESCROW_CLIENT_KEY_ID: () => ESCROW_CLIENT_KEY_ID,
19039
+ ESCROW_ENROLLMENT_INTENT_DOMAIN: () => ESCROW_ENROLLMENT_INTENT_DOMAIN,
19028
19040
  ESCROW_ENVELOPE_VERSION: () => ESCROW_ENVELOPE_VERSION,
19029
19041
  ESCROW_PIN_MAX_ATTEMPTS: () => ESCROW_PIN_MAX_ATTEMPTS,
19030
19042
  ESCROW_RELEASE_INFO: () => ESCROW_RELEASE_INFO,
19043
+ EscrowEvidenceError: () => EscrowEvidenceError,
19031
19044
  EscrowHoldRestartThrottledError: () => EscrowHoldRestartThrottledError,
19032
19045
  EscrowPinLockedError: () => EscrowPinLockedError,
19033
19046
  EscrowPinMismatchError: () => EscrowPinMismatchError,
@@ -19055,6 +19068,7 @@ __export(index_exports, {
19055
19068
  constantTimeEqualHex: () => constantTimeEqualHex,
19056
19069
  countWords: () => countWords,
19057
19070
  createAdaptiveStorage: () => createAdaptiveStorage,
19071
+ createEscrowEnrollmentIntent: () => createEscrowEnrollmentIntent,
19058
19072
  createPasskeyCredential: () => createPasskeyCredential,
19059
19073
  createQrLoginSession: () => createQrLoginSession,
19060
19074
  createSSSKeyManager: () => createSSSKeyManager,
@@ -19068,6 +19082,7 @@ __export(index_exports, {
19068
19082
  deriveKeyFromPasskey: () => deriveKeyFromPasskey,
19069
19083
  deriveKeyFromPassword: () => deriveKeyFromPassword,
19070
19084
  derivePinProof: () => derivePinProof,
19085
+ encodeEscrowEnrollmentIntent: () => encodeEscrowEnrollmentIntent,
19071
19086
  encryptEmailRelayPayload: () => encryptEmailRelayPayload,
19072
19087
  encryptEscrowBlob: () => encryptEscrowBlob,
19073
19088
  encryptShareForTransfer: () => encryptShareForTransfer,
@@ -19080,6 +19095,7 @@ __export(index_exports, {
19080
19095
  generatePinSalt: () => generatePinSalt,
19081
19096
  generateRecoveryPhrase: () => generateRecoveryPhrase,
19082
19097
  getDeviceShare: () => getDeviceShare,
19098
+ getEscrowBlobIdentity: () => getEscrowBlobIdentity,
19083
19099
  getQrLoginSessionInfo: () => getQrLoginSessionInfo,
19084
19100
  getShareVersion: () => getShareVersion,
19085
19101
  hasDeviceShare: () => hasDeviceShare,
@@ -19101,9 +19117,11 @@ __export(index_exports, {
19101
19117
  reconstructFromShares: () => reconstructFromShares,
19102
19118
  reconstructPrivateKey: () => reconstructPrivateKey,
19103
19119
  recoveryPhraseToShare: () => recoveryPhraseToShare,
19120
+ resolveEscrowEnrollmentAction: () => resolveEscrowEnrollmentAction,
19104
19121
  sealEscrowRelease: () => sealEscrowRelease,
19105
19122
  setPublicComputerMode: () => setPublicComputerMode,
19106
19123
  shareToRecoveryPhrase: () => shareToRecoveryPhrase,
19124
+ signEscrowEnrollmentIntent: () => signEscrowEnrollmentIntent,
19107
19125
  splitAndVerify: () => splitAndVerify,
19108
19126
  splitPrivateKey: () => splitPrivateKey,
19109
19127
  storeDeviceShare: () => storeDeviceShare,
@@ -19111,8 +19129,11 @@ __export(index_exports, {
19111
19129
  validatePin: () => validatePin,
19112
19130
  validateRecoveryPhrase: () => validateRecoveryPhrase,
19113
19131
  verifyEnclaveAttestation: () => verifyEnclaveAttestation,
19132
+ verifyEscrowAuthorityState: () => verifyEscrowAuthorityState,
19133
+ verifyEscrowEnrollmentCommit: () => verifyEscrowEnrollmentCommit,
19114
19134
  verifyNitroAttestationDocument: () => verifyNitroAttestationDocument,
19115
- verifyStoredShares: () => verifyStoredShares
19135
+ verifyStoredShares: () => verifyStoredShares,
19136
+ violatesCarryContactRule: () => violatesCarryContactRule
19116
19137
  });
19117
19138
  module.exports = __toCommonJS(index_exports);
19118
19139
 
@@ -19273,37 +19294,37 @@ var DEFAULT_KDF_PARAMS = {
19273
19294
  parallelism: ARGON2_PARALLELISM
19274
19295
  };
19275
19296
  function bufferToBase64(buf) {
19276
- const bytes2 = new Uint8Array(buf);
19297
+ const bytes3 = new Uint8Array(buf);
19277
19298
  let binary = "";
19278
- for (let i = 0; i < bytes2.byteLength; i++) {
19279
- binary += String.fromCharCode(bytes2[i]);
19299
+ for (let i = 0; i < bytes3.byteLength; i++) {
19300
+ binary += String.fromCharCode(bytes3[i]);
19280
19301
  }
19281
19302
  return btoa(binary);
19282
19303
  }
19283
19304
  __name(bufferToBase64, "bufferToBase64");
19284
19305
  function base64ToBuffer(b64) {
19285
19306
  const binary = atob(b64);
19286
- const bytes2 = new Uint8Array(binary.length);
19307
+ const bytes3 = new Uint8Array(binary.length);
19287
19308
  for (let i = 0; i < binary.length; i++) {
19288
- bytes2[i] = binary.charCodeAt(i);
19309
+ bytes3[i] = binary.charCodeAt(i);
19289
19310
  }
19290
- return bytes2;
19311
+ return bytes3;
19291
19312
  }
19292
19313
  __name(base64ToBuffer, "base64ToBuffer");
19293
19314
  function hexToBytes(hex2) {
19294
- const bytes2 = new Uint8Array(hex2.length / 2);
19315
+ const bytes3 = new Uint8Array(hex2.length / 2);
19295
19316
  for (let i = 0; i < hex2.length; i += 2) {
19296
- bytes2[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
19317
+ bytes3[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
19297
19318
  }
19298
- return bytes2;
19319
+ return bytes3;
19299
19320
  }
19300
19321
  __name(hexToBytes, "hexToBytes");
19301
- function bytesToHex(bytes2) {
19302
- return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
19322
+ function bytesToHex(bytes3) {
19323
+ return Array.from(bytes3).map((b) => b.toString(16).padStart(2, "0")).join("");
19303
19324
  }
19304
19325
  __name(bytesToHex, "bytesToHex");
19305
19326
  async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS) {
19306
- const hash = await (0, import_hash_wasm.argon2id)({
19327
+ const hash2 = await (0, import_hash_wasm.argon2id)({
19307
19328
  password,
19308
19329
  salt,
19309
19330
  iterations: params.timeCost,
@@ -19312,7 +19333,7 @@ async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS
19312
19333
  hashLength: ARGON2_HASH_LENGTH,
19313
19334
  outputType: "binary"
19314
19335
  });
19315
- return Uint8Array.from(hash);
19336
+ return Uint8Array.from(hash2);
19316
19337
  }
19317
19338
  __name(deriveKeyFromPassword, "deriveKeyFromPassword");
19318
19339
  async function encryptWithPassword(plaintext, password) {
@@ -19466,21 +19487,21 @@ async function getOrCreateMasterKey() {
19466
19487
  }
19467
19488
  __name(getOrCreateMasterKey, "getOrCreateMasterKey");
19468
19489
  function bufferToBase642(buf) {
19469
- const bytes2 = new Uint8Array(buf);
19490
+ const bytes3 = new Uint8Array(buf);
19470
19491
  let binary = "";
19471
- for (let i = 0; i < bytes2.byteLength; i++) {
19472
- binary += String.fromCharCode(bytes2[i]);
19492
+ for (let i = 0; i < bytes3.byteLength; i++) {
19493
+ binary += String.fromCharCode(bytes3[i]);
19473
19494
  }
19474
19495
  return btoa(binary);
19475
19496
  }
19476
19497
  __name(bufferToBase642, "bufferToBase64");
19477
19498
  function base64ToBuffer2(b64) {
19478
19499
  const binary = atob(b64);
19479
- const bytes2 = new Uint8Array(binary.length);
19500
+ const bytes3 = new Uint8Array(binary.length);
19480
19501
  for (let i = 0; i < binary.length; i++) {
19481
- bytes2[i] = binary.charCodeAt(i);
19502
+ bytes3[i] = binary.charCodeAt(i);
19482
19503
  }
19483
- return bytes2.buffer;
19504
+ return bytes3.buffer;
19484
19505
  }
19485
19506
  __name(base64ToBuffer2, "base64ToBuffer");
19486
19507
  async function encryptShare(share, id) {
@@ -19888,21 +19909,21 @@ async function getWordlist() {
19888
19909
  return wordlistPromise;
19889
19910
  }
19890
19911
  __name(getWordlist, "getWordlist");
19891
- function bytesToBits(bytes2) {
19892
- return Array.from(bytes2).map((b) => b.toString(2).padStart(8, "0")).join("");
19912
+ function bytesToBits(bytes3) {
19913
+ return Array.from(bytes3).map((b) => b.toString(2).padStart(8, "0")).join("");
19893
19914
  }
19894
19915
  __name(bytesToBits, "bytesToBits");
19895
19916
  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);
19917
+ const bytes3 = new Uint8Array(Math.ceil(bits.length / 8));
19918
+ for (let i = 0; i < bytes3.length; i++) {
19919
+ bytes3[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, "0"), 2);
19899
19920
  }
19900
- return bytes2;
19921
+ return bytes3;
19901
19922
  }
19902
19923
  __name(bitsToBytes, "bitsToBytes");
19903
19924
  async function computeChecksum(data) {
19904
- const hash = await crypto.subtle.digest("SHA-256", data);
19905
- const hashBits = bytesToBits(new Uint8Array(hash));
19925
+ const hash2 = await crypto.subtle.digest("SHA-256", data);
19926
+ const hashBits = bytesToBits(new Uint8Array(hash2));
19906
19927
  const checksumLength = Math.floor(data.length / 4);
19907
19928
  return hashBits.slice(0, checksumLength);
19908
19929
  }
@@ -19935,12 +19956,12 @@ async function recoveryPhraseToShare(phrase) {
19935
19956
  bits += index.toString(2).padStart(11, "0");
19936
19957
  }
19937
19958
  let dataByteCount = 0;
19938
- for (let bytes2 = 1; bytes2 <= 64; bytes2++) {
19939
- const checksumBits2 = Math.floor(bytes2 / 4);
19940
- const totalBits = bytes2 * 8 + checksumBits2;
19959
+ for (let bytes3 = 1; bytes3 <= 64; bytes3++) {
19960
+ const checksumBits2 = Math.floor(bytes3 / 4);
19961
+ const totalBits = bytes3 * 8 + checksumBits2;
19941
19962
  const wordsNeeded = Math.ceil(totalBits / 11);
19942
19963
  if (wordsNeeded === words.length) {
19943
- dataByteCount = bytes2;
19964
+ dataByteCount = bytes3;
19944
19965
  } else if (wordsNeeded > words.length) {
19945
19966
  break;
19946
19967
  }
@@ -20234,9 +20255,9 @@ __name(createSSSKeyManager, "createSSSKeyManager");
20234
20255
  var EMAIL_RELAY_ENVELOPE_VERSION = 1;
20235
20256
  var EMAIL_RELAY_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
20236
20257
  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);
20258
+ const bytes3 = new TextEncoder().encode(value);
20259
+ const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
20260
+ copy.set(bytes3);
20240
20261
  return copy;
20241
20262
  }, "encodeUtf8");
20242
20263
  var EMAIL_RELAY_INFO = encodeUtf8("learncard-email-relay-v1");
@@ -20255,7 +20276,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
20255
20276
  if (value === void 0) return void 0;
20256
20277
  if (!isRecord(value)) throw new Error("Invalid email relay branding");
20257
20278
  const branding = {};
20258
- const keys = [
20279
+ const keys2 = [
20259
20280
  "brandName",
20260
20281
  "logoUrl",
20261
20282
  "logoAlt",
@@ -20267,7 +20288,7 @@ var parseBranding = /* @__PURE__ */ __name((value) => {
20267
20288
  "fromDomain",
20268
20289
  "copyrightHolder"
20269
20290
  ];
20270
- for (const key of keys) {
20291
+ for (const key of keys2) {
20271
20292
  const field = value[key];
20272
20293
  if (field === void 0) continue;
20273
20294
  if (typeof field !== "string" || field.length > 2048) {
@@ -20320,7 +20341,7 @@ var parseEmailRelayPlaintext = /* @__PURE__ */ __name((value) => {
20320
20341
  branding: parseBranding(value.branding)
20321
20342
  };
20322
20343
  }, "parseEmailRelayPlaintext");
20323
- var getAad = /* @__PURE__ */ __name((envelope) => encodeUtf8(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
20344
+ var getAad = /* @__PURE__ */ __name((envelope2) => encodeUtf8(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
20324
20345
  var deriveAesKey = /* @__PURE__ */ __name(async (sharedSecret, salt, usage) => {
20325
20346
  const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
20326
20347
  "deriveKey"
@@ -20392,7 +20413,7 @@ var encryptEmailRelayPayload = /* @__PURE__ */ __name(async (input, publicKeyBas
20392
20413
  };
20393
20414
  }, "encryptEmailRelayPayload");
20394
20415
  var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBase64) => {
20395
- const envelope = parseEmailRelayEnvelope(value);
20416
+ const envelope2 = parseEmailRelayEnvelope(value);
20396
20417
  const privateKey = await crypto.subtle.importKey(
20397
20418
  "pkcs8",
20398
20419
  base64ToBuffer(privateKeyBase64.trim()).buffer,
@@ -20402,7 +20423,7 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
20402
20423
  );
20403
20424
  const ephemeralPublicKey = await crypto.subtle.importKey(
20404
20425
  "raw",
20405
- base64ToBuffer(envelope.ephemeralPublicKey).buffer,
20426
+ base64ToBuffer(envelope2.ephemeralPublicKey).buffer,
20406
20427
  { name: "ECDH", namedCurve: "P-256" },
20407
20428
  false,
20408
20429
  []
@@ -20412,13 +20433,13 @@ var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBa
20412
20433
  privateKey,
20413
20434
  256
20414
20435
  );
20415
- const salt = base64ToBuffer(envelope.salt);
20416
- const iv = base64ToBuffer(envelope.iv);
20436
+ const salt = base64ToBuffer(envelope2.salt);
20437
+ const iv = base64ToBuffer(envelope2.iv);
20417
20438
  const aesKey = await deriveAesKey(sharedSecret, salt, "decrypt");
20418
20439
  const decrypted = await crypto.subtle.decrypt(
20419
- { name: "AES-GCM", iv, additionalData: getAad(envelope) },
20440
+ { name: "AES-GCM", iv, additionalData: getAad(envelope2) },
20420
20441
  aesKey,
20421
- base64ToBuffer(envelope.ciphertext)
20442
+ base64ToBuffer(envelope2.ciphertext)
20422
20443
  );
20423
20444
  const parsed = JSON.parse(new TextDecoder().decode(decrypted));
20424
20445
  return parseEmailRelayPlaintext(parsed);
@@ -20430,10 +20451,11 @@ var ESCROW_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
20430
20451
  var ESCROW_BLOB_INFO = "learncard-escrow-blob-v1";
20431
20452
  var ESCROW_RELEASE_INFO = "learncard-escrow-release-v1";
20432
20453
  var ESCROW_CLIENT_KEY_ID = "client";
20454
+ var RECOVERY_LANGUAGES = ["en", "es", "fr", "ar"];
20433
20455
  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);
20456
+ const bytes3 = new TextEncoder().encode(value);
20457
+ const copy = new Uint8Array(new ArrayBuffer(bytes3.byteLength));
20458
+ copy.set(bytes3);
20437
20459
  return copy;
20438
20460
  }, "encodeUtf8");
20439
20461
  var isRecord2 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
@@ -20469,6 +20491,22 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
20469
20491
  if (typeof value.shareVersion !== "number" || !Number.isInteger(value.shareVersion) || value.shareVersion <= 0) {
20470
20492
  throw new Error("Invalid escrow shareVersion");
20471
20493
  }
20494
+ if (value.recoveryEmail !== void 0 !== (value.recoveryLanguage !== void 0)) {
20495
+ throw new Error("Invalid escrow recoveryEmail");
20496
+ }
20497
+ let recoveryContact = {};
20498
+ if (value.recoveryEmail !== void 0) {
20499
+ const email = requireString2(value, "recoveryEmail", { min: 3, max: 254 }).trim().toLowerCase();
20500
+ const at = email.split("@");
20501
+ 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(".")) {
20502
+ throw new Error("Invalid escrow recoveryEmail");
20503
+ }
20504
+ const language = requireString2(value, "recoveryLanguage", { min: 2, max: 2 });
20505
+ if (!RECOVERY_LANGUAGES.includes(language)) {
20506
+ throw new Error("Invalid escrow recoveryLanguage");
20507
+ }
20508
+ recoveryContact = { recoveryEmail: email, recoveryLanguage: language };
20509
+ }
20472
20510
  return {
20473
20511
  version: ESCROW_ENVELOPE_VERSION,
20474
20512
  recoveryShare: requireString2(value, "recoveryShare", {
@@ -20484,7 +20522,8 @@ var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
20484
20522
  max: 64,
20485
20523
  pattern: /^[0-9a-f]{64}$/i
20486
20524
  }).toLowerCase()
20487
- } : {}
20525
+ } : {},
20526
+ ...recoveryContact
20488
20527
  };
20489
20528
  }, "parseEscrowBlobPlaintext");
20490
20529
  var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
@@ -20495,7 +20534,7 @@ var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
20495
20534
  holdId: requireString2(value, "holdId", { max: 128, pattern: /^[A-Za-z0-9._-]+$/ })
20496
20535
  };
20497
20536
  }, "parseEscrowReleasePlaintext");
20498
- var getAad2 = /* @__PURE__ */ __name((envelope) => encodeUtf82(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
20537
+ var getAad2 = /* @__PURE__ */ __name((envelope2) => encodeUtf82(`${envelope2.version}|${envelope2.algorithm}|${envelope2.keyId}`), "getAad");
20499
20538
  var deriveAesKey2 = /* @__PURE__ */ __name(async (sharedSecret, salt, usage, info) => {
20500
20539
  const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
20501
20540
  "deriveKey"
@@ -20566,7 +20605,7 @@ var encryptToRecipient = /* @__PURE__ */ __name(async (plaintextJson, spki, keyI
20566
20605
  };
20567
20606
  }, "encryptToRecipient");
20568
20607
  var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20569
- const envelope = parseEscrowEnvelope(value);
20608
+ const envelope2 = parseEscrowEnvelope(value);
20570
20609
  const privateKey = await crypto.subtle.importKey(
20571
20610
  "pkcs8",
20572
20611
  base64ToBuffer(pkcs8.trim()),
@@ -20576,7 +20615,7 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20576
20615
  );
20577
20616
  const ephemeralPublicKey = await crypto.subtle.importKey(
20578
20617
  "raw",
20579
- base64ToBuffer(envelope.ephemeralPublicKey),
20618
+ base64ToBuffer(envelope2.ephemeralPublicKey),
20580
20619
  { name: "ECDH", namedCurve: "P-256" },
20581
20620
  false,
20582
20621
  []
@@ -20586,13 +20625,13 @@ var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
20586
20625
  privateKey,
20587
20626
  256
20588
20627
  );
20589
- const salt = base64ToBuffer(envelope.salt);
20590
- const iv = base64ToBuffer(envelope.iv);
20628
+ const salt = base64ToBuffer(envelope2.salt);
20629
+ const iv = base64ToBuffer(envelope2.iv);
20591
20630
  const aesKey = await deriveAesKey2(sharedSecret, salt, "decrypt", info);
20592
20631
  const decrypted = await crypto.subtle.decrypt(
20593
- { name: "AES-GCM", iv, additionalData: getAad2(envelope) },
20632
+ { name: "AES-GCM", iv, additionalData: getAad2(envelope2) },
20594
20633
  aesKey,
20595
- base64ToBuffer(envelope.ciphertext)
20634
+ base64ToBuffer(envelope2.ciphertext)
20596
20635
  );
20597
20636
  const parsed = JSON.parse(new TextDecoder().decode(decrypted));
20598
20637
  return parsed;
@@ -20606,8 +20645,8 @@ var encryptEscrowBlob = /* @__PURE__ */ __name(async (input, enclavePublicKeySpk
20606
20645
  ESCROW_BLOB_INFO
20607
20646
  );
20608
20647
  }, "encryptEscrowBlob");
20609
- var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
20610
- await decryptFromEnvelope(envelope, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
20648
+ var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope2, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
20649
+ await decryptFromEnvelope(envelope2, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
20611
20650
  ), "decryptEscrowBlob");
20612
20651
  var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPublicKeySpkiB64) => {
20613
20652
  const plaintext = parseEscrowReleasePlaintext({ ...input, version: ESCROW_ENVELOPE_VERSION });
@@ -20618,10 +20657,626 @@ var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPubl
20618
20657
  ESCROW_RELEASE_INFO
20619
20658
  );
20620
20659
  }, "sealEscrowRelease");
20621
- var openEscrowRelease = /* @__PURE__ */ __name(async (envelope, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
20622
- await decryptFromEnvelope(envelope, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
20660
+ var openEscrowRelease = /* @__PURE__ */ __name(async (envelope2, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
20661
+ await decryptFromEnvelope(envelope2, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
20623
20662
  ), "openEscrowRelease");
20624
20663
 
20664
+ // ../../node_modules/@noble/ed25519/index.js
20665
+ var ed25519_CURVE = {
20666
+ p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
20667
+ n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
20668
+ h: 8n,
20669
+ a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
20670
+ d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
20671
+ Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
20672
+ Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n
20673
+ };
20674
+ var { p: P, n: N, Gx, Gy, a: _a, d: _d } = ed25519_CURVE;
20675
+ var h = 8n;
20676
+ var L = 32;
20677
+ var L2 = 64;
20678
+ var err = /* @__PURE__ */ __name((m = "") => {
20679
+ throw new Error(m);
20680
+ }, "err");
20681
+ var isBig = /* @__PURE__ */ __name((n) => typeof n === "bigint", "isBig");
20682
+ var isStr = /* @__PURE__ */ __name((s) => typeof s === "string", "isStr");
20683
+ var isBytes = /* @__PURE__ */ __name((a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array", "isBytes");
20684
+ var abytes = /* @__PURE__ */ __name((a, l) => !isBytes(a) || typeof l === "number" && l > 0 && a.length !== l ? err("Uint8Array expected") : a, "abytes");
20685
+ var u8n = /* @__PURE__ */ __name((len) => new Uint8Array(len), "u8n");
20686
+ var u8fr = /* @__PURE__ */ __name((buf) => Uint8Array.from(buf), "u8fr");
20687
+ var padh = /* @__PURE__ */ __name((n, pad) => n.toString(16).padStart(pad, "0"), "padh");
20688
+ var bytesToHex3 = /* @__PURE__ */ __name((b) => Array.from(abytes(b)).map((e) => padh(e, 2)).join(""), "bytesToHex");
20689
+ var C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
20690
+ var _ch = /* @__PURE__ */ __name((ch) => {
20691
+ if (ch >= C._0 && ch <= C._9)
20692
+ return ch - C._0;
20693
+ if (ch >= C.A && ch <= C.F)
20694
+ return ch - (C.A - 10);
20695
+ if (ch >= C.a && ch <= C.f)
20696
+ return ch - (C.a - 10);
20697
+ return;
20698
+ }, "_ch");
20699
+ var hexToBytes3 = /* @__PURE__ */ __name((hex2) => {
20700
+ const e = "hex invalid";
20701
+ if (!isStr(hex2))
20702
+ return err(e);
20703
+ const hl = hex2.length;
20704
+ const al = hl / 2;
20705
+ if (hl % 2)
20706
+ return err(e);
20707
+ const array = u8n(al);
20708
+ for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
20709
+ const n1 = _ch(hex2.charCodeAt(hi));
20710
+ const n2 = _ch(hex2.charCodeAt(hi + 1));
20711
+ if (n1 === void 0 || n2 === void 0)
20712
+ return err(e);
20713
+ array[ai] = n1 * 16 + n2;
20714
+ }
20715
+ return array;
20716
+ }, "hexToBytes");
20717
+ var toU8 = /* @__PURE__ */ __name((a, len) => abytes(isStr(a) ? hexToBytes3(a) : u8fr(abytes(a)), len), "toU8");
20718
+ var cr = /* @__PURE__ */ __name(() => globalThis?.crypto, "cr");
20719
+ var subtle = /* @__PURE__ */ __name(() => cr()?.subtle ?? err("crypto.subtle must be defined"), "subtle");
20720
+ var concatBytes = /* @__PURE__ */ __name((...arrs) => {
20721
+ const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0));
20722
+ let pad = 0;
20723
+ arrs.forEach((a) => {
20724
+ r.set(a, pad);
20725
+ pad += a.length;
20726
+ });
20727
+ return r;
20728
+ }, "concatBytes");
20729
+ var randomBytes = /* @__PURE__ */ __name((len = L) => {
20730
+ const c = cr();
20731
+ return c.getRandomValues(u8n(len));
20732
+ }, "randomBytes");
20733
+ var big = BigInt;
20734
+ var arange = /* @__PURE__ */ __name((n, min, max, msg = "bad number: out of range") => isBig(n) && min <= n && n < max ? n : err(msg), "arange");
20735
+ var M = /* @__PURE__ */ __name((a, b = P) => {
20736
+ const r = a % b;
20737
+ return r >= 0n ? r : b + r;
20738
+ }, "M");
20739
+ var modN = /* @__PURE__ */ __name((a) => M(a, N), "modN");
20740
+ var invert = /* @__PURE__ */ __name((num, md) => {
20741
+ if (num === 0n || md <= 0n)
20742
+ err("no inverse n=" + num + " mod=" + md);
20743
+ let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
20744
+ while (a !== 0n) {
20745
+ const q = b / a, r = b % a;
20746
+ const m = x - u * q, n = y - v * q;
20747
+ b = a, a = r, x = u, y = v, u = m, v = n;
20748
+ }
20749
+ return b === 1n ? M(x, md) : err("no inverse");
20750
+ }, "invert");
20751
+ var apoint = /* @__PURE__ */ __name((p) => p instanceof Point ? p : err("Point expected"), "apoint");
20752
+ var B256 = 2n ** 256n;
20753
+ var Point = class _Point {
20754
+ static {
20755
+ __name(this, "Point");
20756
+ }
20757
+ static BASE;
20758
+ static ZERO;
20759
+ ex;
20760
+ ey;
20761
+ ez;
20762
+ et;
20763
+ constructor(ex, ey, ez, et) {
20764
+ const max = B256;
20765
+ this.ex = arange(ex, 0n, max);
20766
+ this.ey = arange(ey, 0n, max);
20767
+ this.ez = arange(ez, 1n, max);
20768
+ this.et = arange(et, 0n, max);
20769
+ Object.freeze(this);
20770
+ }
20771
+ static fromAffine(p) {
20772
+ return new _Point(p.x, p.y, 1n, M(p.x * p.y));
20773
+ }
20774
+ /** RFC8032 5.1.3: Uint8Array to Point. */
20775
+ static fromBytes(hex2, zip215 = false) {
20776
+ const d = _d;
20777
+ const normed = u8fr(abytes(hex2, L));
20778
+ const lastByte = hex2[31];
20779
+ normed[31] = lastByte & ~128;
20780
+ const y = bytesToNumLE(normed);
20781
+ const max = zip215 ? B256 : P;
20782
+ arange(y, 0n, max);
20783
+ const y2 = M(y * y);
20784
+ const u = M(y2 - 1n);
20785
+ const v = M(d * y2 + 1n);
20786
+ let { isValid, value: x } = uvRatio(u, v);
20787
+ if (!isValid)
20788
+ err("bad point: y not sqrt");
20789
+ const isXOdd = (x & 1n) === 1n;
20790
+ const isLastByteOdd = (lastByte & 128) !== 0;
20791
+ if (!zip215 && x === 0n && isLastByteOdd)
20792
+ err("bad point: x==0, isLastByteOdd");
20793
+ if (isLastByteOdd !== isXOdd)
20794
+ x = M(-x);
20795
+ return new _Point(x, y, 1n, M(x * y));
20796
+ }
20797
+ /** Checks if the point is valid and on-curve. */
20798
+ assertValidity() {
20799
+ const a = _a;
20800
+ const d = _d;
20801
+ const p = this;
20802
+ if (p.is0())
20803
+ throw new Error("bad point: ZERO");
20804
+ const { ex: X, ey: Y, ez: Z, et: T } = p;
20805
+ const X2 = M(X * X);
20806
+ const Y2 = M(Y * Y);
20807
+ const Z2 = M(Z * Z);
20808
+ const Z4 = M(Z2 * Z2);
20809
+ const aX2 = M(X2 * a);
20810
+ const left = M(Z2 * M(aX2 + Y2));
20811
+ const right = M(Z4 + M(d * M(X2 * Y2)));
20812
+ if (left !== right)
20813
+ throw new Error("bad point: equation left != right (1)");
20814
+ const XY = M(X * Y);
20815
+ const ZT = M(Z * T);
20816
+ if (XY !== ZT)
20817
+ throw new Error("bad point: equation left != right (2)");
20818
+ return this;
20819
+ }
20820
+ /** Equality check: compare points P&Q. */
20821
+ equals(other) {
20822
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
20823
+ const { ex: X2, ey: Y2, ez: Z2 } = apoint(other);
20824
+ const X1Z2 = M(X1 * Z2);
20825
+ const X2Z1 = M(X2 * Z1);
20826
+ const Y1Z2 = M(Y1 * Z2);
20827
+ const Y2Z1 = M(Y2 * Z1);
20828
+ return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
20829
+ }
20830
+ is0() {
20831
+ return this.equals(I);
20832
+ }
20833
+ /** Flip point over y coordinate. */
20834
+ negate() {
20835
+ return new _Point(M(-this.ex), this.ey, this.ez, M(-this.et));
20836
+ }
20837
+ /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */
20838
+ double() {
20839
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
20840
+ const a = _a;
20841
+ const A = M(X1 * X1);
20842
+ const B = M(Y1 * Y1);
20843
+ const C2 = M(2n * M(Z1 * Z1));
20844
+ const D = M(a * A);
20845
+ const x1y1 = X1 + Y1;
20846
+ const E = M(M(x1y1 * x1y1) - A - B);
20847
+ const G2 = D + B;
20848
+ const F = G2 - C2;
20849
+ const H = D - B;
20850
+ const X3 = M(E * F);
20851
+ const Y3 = M(G2 * H);
20852
+ const T3 = M(E * H);
20853
+ const Z3 = M(F * G2);
20854
+ return new _Point(X3, Y3, Z3, T3);
20855
+ }
20856
+ /** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */
20857
+ add(other) {
20858
+ const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;
20859
+ const { ex: X2, ey: Y2, ez: Z2, et: T2 } = apoint(other);
20860
+ const a = _a;
20861
+ const d = _d;
20862
+ const A = M(X1 * X2);
20863
+ const B = M(Y1 * Y2);
20864
+ const C2 = M(T1 * d * T2);
20865
+ const D = M(Z1 * Z2);
20866
+ const E = M((X1 + Y1) * (X2 + Y2) - A - B);
20867
+ const F = M(D - C2);
20868
+ const G2 = M(D + C2);
20869
+ const H = M(B - a * A);
20870
+ const X3 = M(E * F);
20871
+ const Y3 = M(G2 * H);
20872
+ const T3 = M(E * H);
20873
+ const Z3 = M(F * G2);
20874
+ return new _Point(X3, Y3, Z3, T3);
20875
+ }
20876
+ /**
20877
+ * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
20878
+ * Uses {@link wNAF} for base point.
20879
+ * Uses fake point to mitigate side-channel leakage.
20880
+ * @param n scalar by which point is multiplied
20881
+ * @param safe safe mode guards against timing attacks; unsafe mode is faster
20882
+ */
20883
+ multiply(n, safe = true) {
20884
+ if (!safe && (n === 0n || this.is0()))
20885
+ return I;
20886
+ arange(n, 1n, N);
20887
+ if (n === 1n)
20888
+ return this;
20889
+ if (this.equals(G))
20890
+ return wNAF(n).p;
20891
+ let p = I;
20892
+ let f = G;
20893
+ for (let d = this; n > 0n; d = d.double(), n >>= 1n) {
20894
+ if (n & 1n)
20895
+ p = p.add(d);
20896
+ else if (safe)
20897
+ f = f.add(d);
20898
+ }
20899
+ return p;
20900
+ }
20901
+ /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
20902
+ toAffine() {
20903
+ const { ex: x, ey: y, ez: z } = this;
20904
+ if (this.equals(I))
20905
+ return { x: 0n, y: 1n };
20906
+ const iz = invert(z, P);
20907
+ if (M(z * iz) !== 1n)
20908
+ err("invalid inverse");
20909
+ return { x: M(x * iz), y: M(y * iz) };
20910
+ }
20911
+ toBytes() {
20912
+ const { x, y } = this.assertValidity().toAffine();
20913
+ const b = numTo32bLE(y);
20914
+ b[31] |= x & 1n ? 128 : 0;
20915
+ return b;
20916
+ }
20917
+ toHex() {
20918
+ return bytesToHex3(this.toBytes());
20919
+ }
20920
+ // encode to hex string
20921
+ clearCofactor() {
20922
+ return this.multiply(big(h), false);
20923
+ }
20924
+ isSmallOrder() {
20925
+ return this.clearCofactor().is0();
20926
+ }
20927
+ isTorsionFree() {
20928
+ let p = this.multiply(N / 2n, false).double();
20929
+ if (N % 2n)
20930
+ p = p.add(this);
20931
+ return p.is0();
20932
+ }
20933
+ static fromHex(hex2, zip215) {
20934
+ return _Point.fromBytes(toU8(hex2), zip215);
20935
+ }
20936
+ get x() {
20937
+ return this.toAffine().x;
20938
+ }
20939
+ get y() {
20940
+ return this.toAffine().y;
20941
+ }
20942
+ toRawBytes() {
20943
+ return this.toBytes();
20944
+ }
20945
+ };
20946
+ var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
20947
+ var I = new Point(0n, 1n, 1n, 0n);
20948
+ Point.BASE = G;
20949
+ Point.ZERO = I;
20950
+ var numTo32bLE = /* @__PURE__ */ __name((num) => hexToBytes3(padh(arange(num, 0n, B256), L2)).reverse(), "numTo32bLE");
20951
+ var bytesToNumLE = /* @__PURE__ */ __name((b) => big("0x" + bytesToHex3(u8fr(abytes(b)).reverse())), "bytesToNumLE");
20952
+ var pow2 = /* @__PURE__ */ __name((x, power) => {
20953
+ let r = x;
20954
+ while (power-- > 0n) {
20955
+ r *= r;
20956
+ r %= P;
20957
+ }
20958
+ return r;
20959
+ }, "pow2");
20960
+ var pow_2_252_3 = /* @__PURE__ */ __name((x) => {
20961
+ const x2 = x * x % P;
20962
+ const b2 = x2 * x % P;
20963
+ const b4 = pow2(b2, 2n) * b2 % P;
20964
+ const b5 = pow2(b4, 1n) * x % P;
20965
+ const b10 = pow2(b5, 5n) * b5 % P;
20966
+ const b20 = pow2(b10, 10n) * b10 % P;
20967
+ const b40 = pow2(b20, 20n) * b20 % P;
20968
+ const b80 = pow2(b40, 40n) * b40 % P;
20969
+ const b160 = pow2(b80, 80n) * b80 % P;
20970
+ const b240 = pow2(b160, 80n) * b80 % P;
20971
+ const b250 = pow2(b240, 10n) * b10 % P;
20972
+ const pow_p_5_8 = pow2(b250, 2n) * x % P;
20973
+ return { pow_p_5_8, b2 };
20974
+ }, "pow_2_252_3");
20975
+ var RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n;
20976
+ var uvRatio = /* @__PURE__ */ __name((u, v) => {
20977
+ const v3 = M(v * v * v);
20978
+ const v7 = M(v3 * v3 * v);
20979
+ const pow = pow_2_252_3(u * v7).pow_p_5_8;
20980
+ let x = M(u * v3 * pow);
20981
+ const vx2 = M(v * x * x);
20982
+ const root1 = x;
20983
+ const root2 = M(x * RM1);
20984
+ const useRoot1 = vx2 === u;
20985
+ const useRoot2 = vx2 === M(-u);
20986
+ const noRoot = vx2 === M(-u * RM1);
20987
+ if (useRoot1)
20988
+ x = root1;
20989
+ if (useRoot2 || noRoot)
20990
+ x = root2;
20991
+ if ((M(x) & 1n) === 1n)
20992
+ x = M(-x);
20993
+ return { isValid: useRoot1 || useRoot2, value: x };
20994
+ }, "uvRatio");
20995
+ var modL_LE = /* @__PURE__ */ __name((hash2) => modN(bytesToNumLE(hash2)), "modL_LE");
20996
+ var sha512a = /* @__PURE__ */ __name((...m) => etc.sha512Async(...m), "sha512a");
20997
+ var hash2extK = /* @__PURE__ */ __name((hashed) => {
20998
+ const head = hashed.slice(0, L);
20999
+ head[0] &= 248;
21000
+ head[31] &= 127;
21001
+ head[31] |= 64;
21002
+ const prefix = hashed.slice(L, L2);
21003
+ const scalar = modL_LE(head);
21004
+ const point = G.multiply(scalar);
21005
+ const pointBytes = point.toBytes();
21006
+ return { head, prefix, scalar, point, pointBytes };
21007
+ }, "hash2extK");
21008
+ var getExtendedPublicKeyAsync = /* @__PURE__ */ __name((priv) => sha512a(toU8(priv, L)).then(hash2extK), "getExtendedPublicKeyAsync");
21009
+ var getPublicKeyAsync = /* @__PURE__ */ __name((priv) => getExtendedPublicKeyAsync(priv).then((p) => p.pointBytes), "getPublicKeyAsync");
21010
+ var hashFinishA = /* @__PURE__ */ __name((res) => sha512a(res.hashable).then(res.finish), "hashFinishA");
21011
+ var _sign = /* @__PURE__ */ __name((e, rBytes, msg) => {
21012
+ const { pointBytes: P2, scalar: s } = e;
21013
+ const r = modL_LE(rBytes);
21014
+ const R = G.multiply(r).toBytes();
21015
+ const hashable = concatBytes(R, P2, msg);
21016
+ const finish = /* @__PURE__ */ __name((hashed) => {
21017
+ const S = modN(r + modL_LE(hashed) * s);
21018
+ return abytes(concatBytes(R, numTo32bLE(S)), L2);
21019
+ }, "finish");
21020
+ return { hashable, finish };
21021
+ }, "_sign");
21022
+ var signAsync = /* @__PURE__ */ __name(async (msg, privKey) => {
21023
+ const m = toU8(msg);
21024
+ const e = await getExtendedPublicKeyAsync(privKey);
21025
+ const rBytes = await sha512a(e.prefix, m);
21026
+ return hashFinishA(_sign(e, rBytes, m));
21027
+ }, "signAsync");
21028
+ var etc = {
21029
+ sha512Async: /* @__PURE__ */ __name(async (...messages) => {
21030
+ const s = subtle();
21031
+ const m = concatBytes(...messages);
21032
+ return u8n(await s.digest("SHA-512", m.buffer));
21033
+ }, "sha512Async"),
21034
+ sha512Sync: void 0,
21035
+ bytesToHex: bytesToHex3,
21036
+ hexToBytes: hexToBytes3,
21037
+ concatBytes,
21038
+ mod: M,
21039
+ invert,
21040
+ randomBytes
21041
+ };
21042
+ var W = 8;
21043
+ var scalarBits = 256;
21044
+ var pwindows = Math.ceil(scalarBits / W) + 1;
21045
+ var pwindowSize = 2 ** (W - 1);
21046
+ var precompute = /* @__PURE__ */ __name(() => {
21047
+ const points = [];
21048
+ let p = G;
21049
+ let b = p;
21050
+ for (let w = 0; w < pwindows; w++) {
21051
+ b = p;
21052
+ points.push(b);
21053
+ for (let i = 1; i < pwindowSize; i++) {
21054
+ b = b.add(p);
21055
+ points.push(b);
21056
+ }
21057
+ p = b.double();
21058
+ }
21059
+ return points;
21060
+ }, "precompute");
21061
+ var Gpows = void 0;
21062
+ var ctneg = /* @__PURE__ */ __name((cnd, p) => {
21063
+ const n = p.negate();
21064
+ return cnd ? n : p;
21065
+ }, "ctneg");
21066
+ var wNAF = /* @__PURE__ */ __name((n) => {
21067
+ const comp = Gpows || (Gpows = precompute());
21068
+ let p = I;
21069
+ let f = G;
21070
+ const pow_2_w = 2 ** W;
21071
+ const maxNum = pow_2_w;
21072
+ const mask = big(pow_2_w - 1);
21073
+ const shiftBy = big(W);
21074
+ for (let w = 0; w < pwindows; w++) {
21075
+ let wbits = Number(n & mask);
21076
+ n >>= shiftBy;
21077
+ if (wbits > pwindowSize) {
21078
+ wbits -= maxNum;
21079
+ n += 1n;
21080
+ }
21081
+ const off = w * pwindowSize;
21082
+ const offF = off;
21083
+ const offP = off + Math.abs(wbits) - 1;
21084
+ const isEven = w % 2 !== 0;
21085
+ const isNeg = wbits < 0;
21086
+ if (wbits === 0) {
21087
+ f = f.add(ctneg(isEven, comp[offF]));
21088
+ } else {
21089
+ p = p.add(ctneg(isNeg, comp[offP]));
21090
+ }
21091
+ }
21092
+ return { p, f };
21093
+ }, "wNAF");
21094
+
21095
+ // src/escrow-enrollment-intent.ts
21096
+ var ESCROW_ENROLLMENT_INTENT_DOMAIN = "learncard-escrow-enrollment-intent-v2\0";
21097
+ var BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
21098
+ var FIELDS = [
21099
+ "version",
21100
+ "tenant",
21101
+ "did",
21102
+ "authorityGeneration",
21103
+ "expectedEnrollmentVersion",
21104
+ "action",
21105
+ "sourceBlobIdentity",
21106
+ "targetBlobIdentity",
21107
+ "pinAction",
21108
+ "shareVersion",
21109
+ "enrollmentEpoch",
21110
+ "requestId",
21111
+ "allowRewrap",
21112
+ "recoveryEmail",
21113
+ "recoveryLanguage"
21114
+ ];
21115
+ var ACTIONS = ["enroll", "replace", "disable", "carry"];
21116
+ var PIN_ACTIONS = ["set", "change", "clear", "keep"];
21117
+ var RECOVERY_LANGUAGES2 = ["en", "es", "fr", "ar"];
21118
+ var requireIntent = /* @__PURE__ */ __name((condition) => {
21119
+ if (!condition) throw new Error("Invalid escrow enrollment intent");
21120
+ }, "requireIntent");
21121
+ var matches = /* @__PURE__ */ __name((value, pattern) => typeof value === "string" && pattern.exec(value)?.[0] === value, "matches");
21122
+ var utf8 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
21123
+ var integer = /* @__PURE__ */ __name((value, width) => {
21124
+ requireIntent(
21125
+ Number.isSafeInteger(value) && value >= 0 && (width === 8 || value <= 4294967295)
21126
+ );
21127
+ const bytes3 = new Uint8Array(width);
21128
+ const view = new DataView(bytes3.buffer);
21129
+ if (width === 4) view.setUint32(0, value, false);
21130
+ else view.setBigUint64(0, BigInt(value), false);
21131
+ return bytes3;
21132
+ }, "integer");
21133
+ var join = /* @__PURE__ */ __name((fields) => {
21134
+ const result = new Uint8Array(fields.reduce((length, field) => length + field.length, 0));
21135
+ let offset = 0;
21136
+ for (const field of fields) {
21137
+ result.set(field, offset);
21138
+ offset += field.length;
21139
+ }
21140
+ return result;
21141
+ }, "join");
21142
+ var hashBytes = /* @__PURE__ */ __name((value) => {
21143
+ if (value === null) return new Uint8Array();
21144
+ requireIntent(matches(value, /^[0-9a-f]{64}$/));
21145
+ return new Uint8Array(hexToBytes(value));
21146
+ }, "hashBytes");
21147
+ var didPublicKey = /* @__PURE__ */ __name((did) => {
21148
+ requireIntent(typeof did === "string" && did.startsWith("did:key:z") && did.length === 56);
21149
+ let value = 0n;
21150
+ for (const char of did.slice(9)) {
21151
+ const digit = BASE58.indexOf(char);
21152
+ requireIntent(digit >= 0);
21153
+ value = value * 58n + BigInt(digit);
21154
+ }
21155
+ const bytes3 = new Uint8Array(34);
21156
+ for (let i = 33; i >= 0; i--) {
21157
+ bytes3[i] = Number(value & 255n);
21158
+ value >>= 8n;
21159
+ }
21160
+ requireIntent(value === 0n && bytes3[0] === 237 && bytes3[1] === 1);
21161
+ const key = bytes3.slice(2);
21162
+ try {
21163
+ requireIntent(!Point.fromHex(key, false).isSmallOrder());
21164
+ } catch {
21165
+ throw new Error("Invalid escrow enrollment intent");
21166
+ }
21167
+ return key;
21168
+ }, "didPublicKey");
21169
+ var encodeEscrowEnrollmentIntent = /* @__PURE__ */ __name((intent) => {
21170
+ requireIntent(typeof intent === "object" && intent !== null && !Array.isArray(intent));
21171
+ requireIntent(
21172
+ Object.keys(intent).length === FIELDS.length && FIELDS.every((field) => Object.prototype.hasOwnProperty.call(intent, field))
21173
+ );
21174
+ requireIntent(intent.version === 2 && typeof intent.allowRewrap === "boolean");
21175
+ requireIntent(matches(intent.tenant, /^[A-Za-z0-9_-]{1,128}$/));
21176
+ requireIntent(matches(intent.authorityGeneration, /^[A-Za-z0-9_-]{1,128}$/));
21177
+ requireIntent(matches(intent.requestId, /^[A-Za-z0-9._-]{1,112}$/));
21178
+ didPublicKey(intent.did);
21179
+ const action = ACTIONS.indexOf(intent.action);
21180
+ const pin = PIN_ACTIONS.indexOf(intent.pinAction);
21181
+ requireIntent(action >= 0 && pin >= 0 && intent.shareVersion > 0 && intent.enrollmentEpoch > 0);
21182
+ const source = hashBytes(intent.sourceBlobIdentity);
21183
+ const target = hashBytes(intent.targetBlobIdentity);
21184
+ if (intent.action === "enroll") requireIntent(source.length === 0 && target.length === 32);
21185
+ else if (intent.action === "disable")
21186
+ requireIntent(
21187
+ source.length === 32 && target.length === 0 && intent.pinAction === "keep" && !intent.allowRewrap
21188
+ );
21189
+ else
21190
+ requireIntent(
21191
+ source.length === 32 && target.length === 32 && intent.sourceBlobIdentity !== intent.targetBlobIdentity
21192
+ );
21193
+ if (intent.action === "carry") requireIntent(intent.pinAction === "keep");
21194
+ if (intent.recoveryEmail === null) {
21195
+ requireIntent(
21196
+ intent.recoveryLanguage === null && (intent.action === "disable" || intent.action === "carry")
21197
+ );
21198
+ } else {
21199
+ requireIntent(intent.action === "enroll" || intent.action === "replace");
21200
+ requireIntent(
21201
+ matches(intent.recoveryEmail, /^[\x21-\x7e]{3,254}$/) && intent.recoveryEmail === intent.recoveryEmail.trim().toLowerCase()
21202
+ );
21203
+ const at = intent.recoveryEmail.split("@");
21204
+ requireIntent(
21205
+ at.length === 2 && at[0].length > 0 && at[1].length > 0 && at[1].includes(".") && !at[1].startsWith(".") && !at[1].endsWith(".")
21206
+ );
21207
+ requireIntent(
21208
+ intent.recoveryLanguage !== null && RECOVERY_LANGUAGES2.includes(intent.recoveryLanguage)
21209
+ );
21210
+ }
21211
+ const fields = [
21212
+ integer(intent.version, 4),
21213
+ utf8(intent.tenant),
21214
+ utf8(intent.did),
21215
+ utf8(intent.authorityGeneration),
21216
+ integer(intent.expectedEnrollmentVersion, 8),
21217
+ Uint8Array.of(action),
21218
+ source,
21219
+ target,
21220
+ Uint8Array.of(pin),
21221
+ integer(intent.shareVersion, 4),
21222
+ integer(intent.enrollmentEpoch, 8),
21223
+ utf8(intent.requestId),
21224
+ Uint8Array.of(Number(intent.allowRewrap)),
21225
+ intent.recoveryEmail === null ? new Uint8Array() : utf8(intent.recoveryEmail),
21226
+ intent.recoveryLanguage === null ? new Uint8Array() : utf8(intent.recoveryLanguage)
21227
+ ];
21228
+ return join([
21229
+ utf8(ESCROW_ENROLLMENT_INTENT_DOMAIN),
21230
+ ...fields.flatMap((field) => [integer(field.length, 4), field])
21231
+ ]);
21232
+ }, "encodeEscrowEnrollmentIntent");
21233
+ var signEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (intent, privateKey) => {
21234
+ encodeEscrowEnrollmentIntent(intent);
21235
+ const snapshot = { ...intent };
21236
+ const message = encodeEscrowEnrollmentIntent(snapshot);
21237
+ requireIntent(matches(privateKey, /^[0-9a-f]{64}$/i));
21238
+ const seed = hexToBytes(privateKey);
21239
+ try {
21240
+ const publicKey = await getPublicKeyAsync(seed);
21241
+ const expected = didPublicKey(snapshot.did);
21242
+ requireIntent(publicKey.every((byte, index) => byte === expected[index]));
21243
+ const signature = await signAsync(message, seed);
21244
+ return { intent: snapshot, signature: bufferToBase64(new Uint8Array(signature).buffer) };
21245
+ } finally {
21246
+ seed.fill(0);
21247
+ }
21248
+ }, "signEscrowEnrollmentIntent");
21249
+ var getEscrowBlobIdentity = /* @__PURE__ */ __name(async (input) => {
21250
+ const envelope2 = parseEscrowEnvelope(input);
21251
+ const decode2 = /* @__PURE__ */ __name((value) => {
21252
+ const bytes3 = new Uint8Array(base64ToBuffer(value));
21253
+ requireIntent(bufferToBase64(bytes3.buffer) === value);
21254
+ return bytes3;
21255
+ }, "decode");
21256
+ const point = decode2(envelope2.ephemeralPublicKey);
21257
+ const salt = decode2(envelope2.salt);
21258
+ const iv = decode2(envelope2.iv);
21259
+ const ciphertext = decode2(envelope2.ciphertext);
21260
+ requireIntent(
21261
+ point.length === 65 && point[0] === 4 && salt.length === 32 && iv.length === 12 && ciphertext.length >= 16
21262
+ );
21263
+ await crypto.subtle.importKey("raw", point, { name: "ECDH", namedCurve: "P-256" }, false, []);
21264
+ const fields = [
21265
+ Uint8Array.of(1),
21266
+ utf8(envelope2.algorithm),
21267
+ utf8(envelope2.keyId),
21268
+ point.slice(1, 33),
21269
+ salt,
21270
+ iv,
21271
+ ciphertext
21272
+ ];
21273
+ const message = join([
21274
+ utf8("learncard-escrow-blob-id-v1\0"),
21275
+ ...fields.flatMap((field) => [integer(field.length, 8), field])
21276
+ ]);
21277
+ return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", message)));
21278
+ }, "getEscrowBlobIdentity");
21279
+
20625
21280
  // src/escrow-nitro-attestation.ts
20626
21281
  var import_reflect_metadata = require("reflect-metadata");
20627
21282
 
@@ -20819,11 +21474,11 @@ var slice = useBuffer ? (
20819
21474
  * @param {number} end
20820
21475
  */
20821
21476
  // 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));
21477
+ (bytes3, start, end) => {
21478
+ if (isBuffer(bytes3)) {
21479
+ return new Uint8Array(bytes3.subarray(start, end));
20825
21480
  }
20826
- return bytes2.slice(start, end);
21481
+ return bytes3.slice(start, end);
20827
21482
  }
20828
21483
  ) : (
20829
21484
  // eslint-disable-line operator-linebreak
@@ -20832,8 +21487,8 @@ var slice = useBuffer ? (
20832
21487
  * @param {number} start
20833
21488
  * @param {number} end
20834
21489
  */
20835
- (bytes2, start, end) => {
20836
- return bytes2.slice(start, end);
21490
+ (bytes3, start, end) => {
21491
+ return bytes3.slice(start, end);
20837
21492
  }
20838
21493
  );
20839
21494
  var concat = useBuffer ? (
@@ -20982,12 +21637,12 @@ var Bl = class {
20982
21637
  /**
20983
21638
  * @param {ByteView|number[]} bytes
20984
21639
  */
20985
- push(bytes2) {
21640
+ push(bytes3) {
20986
21641
  let topChunk = this.chunks[this.chunks.length - 1];
20987
- const newMax = this.cursor + bytes2.length;
21642
+ const newMax = this.cursor + bytes3.length;
20988
21643
  if (newMax <= this.maxCursor + 1) {
20989
21644
  const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
20990
- topChunk.set(bytes2, chunkPos);
21645
+ topChunk.set(bytes3, chunkPos);
20991
21646
  } else {
20992
21647
  if (topChunk) {
20993
21648
  const chunkPos = topChunk.length - (this.maxCursor - this.cursor) - 1;
@@ -20996,20 +21651,20 @@ var Bl = class {
20996
21651
  this.maxCursor = this.cursor - 1;
20997
21652
  }
20998
21653
  }
20999
- if (bytes2.length < 64 && bytes2.length < this.chunkSize) {
21654
+ if (bytes3.length < 64 && bytes3.length < this.chunkSize) {
21000
21655
  topChunk = alloc(this.chunkSize);
21001
21656
  this.chunks.push(topChunk);
21002
21657
  this.maxCursor += topChunk.length;
21003
21658
  if (this._initReuseChunk === null) {
21004
21659
  this._initReuseChunk = topChunk;
21005
21660
  }
21006
- topChunk.set(bytes2, 0);
21661
+ topChunk.set(bytes3, 0);
21007
21662
  } else {
21008
- this.chunks.push(bytes2);
21009
- this.maxCursor += bytes2.length;
21663
+ this.chunks.push(bytes3);
21664
+ this.maxCursor += bytes3.length;
21010
21665
  }
21011
21666
  }
21012
- this.cursor += bytes2.length;
21667
+ this.cursor += bytes3.length;
21013
21668
  }
21014
21669
  /**
21015
21670
  * @param {boolean} [reset]
@@ -21062,12 +21717,12 @@ var U8Bl = class {
21062
21717
  /**
21063
21718
  * @param {ByteView|number[]} bytes
21064
21719
  */
21065
- push(bytes2) {
21066
- if (this.cursor + bytes2.length > this.dest.length) {
21720
+ push(bytes3) {
21721
+ if (this.cursor + bytes3.length > this.dest.length) {
21067
21722
  throw new Error("write out of bounds, destination buffer is too small");
21068
21723
  }
21069
- this.dest.set(bytes2, this.cursor);
21070
- this.cursor += bytes2.length;
21724
+ this.dest.set(bytes3, this.cursor);
21725
+ this.cursor += bytes3.length;
21071
21726
  }
21072
21727
  /**
21073
21728
  * @param {boolean} [reset]
@@ -21321,14 +21976,14 @@ function tokenBytes(token) {
21321
21976
  }
21322
21977
  __name(tokenBytes, "tokenBytes");
21323
21978
  function encodeBytes(writer, token) {
21324
- const bytes2 = tokenBytes(token);
21325
- encodeUintValue(writer, token.type.majorEncoded, bytes2.length);
21326
- writer.push(bytes2);
21979
+ const bytes3 = tokenBytes(token);
21980
+ encodeUintValue(writer, token.type.majorEncoded, bytes3.length);
21981
+ writer.push(bytes3);
21327
21982
  }
21328
21983
  __name(encodeBytes, "encodeBytes");
21329
21984
  encodeBytes.encodedSize = /* @__PURE__ */ __name(function encodedSize4(token) {
21330
- const bytes2 = tokenBytes(token);
21331
- return encodeUintValue.encodedSize(bytes2.length) + bytes2.length;
21985
+ const bytes3 = tokenBytes(token);
21986
+ return encodeUintValue.encodedSize(bytes3.length) + bytes3.length;
21332
21987
  }, "encodedSize");
21333
21988
  encodeBytes.compareTokens = /* @__PURE__ */ __name(function compareTokens3(tok1, tok2) {
21334
21989
  return compareBytes(tokenBytes(tok1), tokenBytes(tok2));
@@ -21341,20 +21996,20 @@ __name(compareBytes, "compareBytes");
21341
21996
  // ../../node_modules/cborg/lib/3string.js
21342
21997
  var textDecoder = new TextDecoder();
21343
21998
  var ASCII_THRESHOLD = 32;
21344
- function toStr(bytes2, start, end) {
21999
+ function toStr(bytes3, start, end) {
21345
22000
  const len = end - start;
21346
22001
  if (len < ASCII_THRESHOLD) {
21347
22002
  let str = "";
21348
22003
  for (let i = start; i < end; i++) {
21349
- const c = bytes2[i];
22004
+ const c = bytes3[i];
21350
22005
  if (c & 128) {
21351
- return textDecoder.decode(bytes2.subarray(start, end));
22006
+ return textDecoder.decode(bytes3.subarray(start, end));
21352
22007
  }
21353
22008
  str += String.fromCharCode(c);
21354
22009
  }
21355
22010
  return str;
21356
22011
  }
21357
- return textDecoder.decode(bytes2.subarray(start, end));
22012
+ return textDecoder.decode(bytes3.subarray(start, end));
21358
22013
  }
21359
22014
  __name(toStr, "toStr");
21360
22015
  function toToken2(data, pos, prefix, length, options) {
@@ -21534,7 +22189,7 @@ function decodeBreak(_data, _pos, _minor, options) {
21534
22189
  return new Token(Type.break, void 0, 1);
21535
22190
  }
21536
22191
  __name(decodeBreak, "decodeBreak");
21537
- function createToken(value, bytes2, options) {
22192
+ function createToken(value, bytes3, options) {
21538
22193
  if (options) {
21539
22194
  if (options.allowNaN === false && Number.isNaN(value)) {
21540
22195
  throw new Error(`${decodeErrPrefix} NaN values are not supported`);
@@ -21543,7 +22198,7 @@ function createToken(value, bytes2, options) {
21543
22198
  throw new Error(`${decodeErrPrefix} Infinity values are not supported`);
21544
22199
  }
21545
22200
  }
21546
- return new Token(Type.float, value, bytes2);
22201
+ return new Token(Type.float, value, bytes3);
21547
22202
  }
21548
22203
  __name(createToken, "createToken");
21549
22204
  function decodeFloat16(data, pos, _minor, options) {
@@ -21741,13 +22396,13 @@ function majorSevenBytes(token, options) {
21741
22396
  if (cached !== void 0) {
21742
22397
  return cached;
21743
22398
  }
21744
- const bytes2 = encodeMajorSevenBytes(token, float64);
22399
+ const bytes3 = encodeMajorSevenBytes(token, float64);
21745
22400
  if (float64) {
21746
- tokenEx._keyBytesFloat64 = bytes2;
22401
+ tokenEx._keyBytesFloat64 = bytes3;
21747
22402
  } else {
21748
- tokenEx._keyBytes = bytes2;
22403
+ tokenEx._keyBytes = bytes3;
21749
22404
  }
21750
- return bytes2;
22405
+ return bytes3;
21751
22406
  }
21752
22407
  __name(majorSevenBytes, "majorSevenBytes");
21753
22408
  encodeFloat.compareTokens = /* @__PURE__ */ __name(function compareTokens4(tok1, tok2, options) {
@@ -22123,15 +22778,15 @@ var typeEncoders = {
22123
22778
  */
22124
22779
  Object(obj, typ, options, refStack) {
22125
22780
  const isMap = typ !== "Object";
22126
- const keys = isMap ? obj.keys() : Object.keys(obj);
22127
- const maxLength = isMap ? obj.size : keys.length;
22781
+ const keys2 = isMap ? obj.keys() : Object.keys(obj);
22782
+ const maxLength = isMap ? obj.size : keys2.length;
22128
22783
  let entries;
22129
22784
  if (maxLength) {
22130
22785
  entries = new Array(maxLength);
22131
22786
  refStack = Ref.createCheck(refStack, obj);
22132
22787
  const skipUndefined = !isMap && options.ignoreUndefinedProperties;
22133
22788
  let i = 0;
22134
- for (const key of keys) {
22789
+ for (const key of keys2) {
22135
22790
  const value = isMap ? obj.get(key) : obj[key];
22136
22791
  if (skipUndefined && value === void 0) {
22137
22792
  continue;
@@ -22282,8 +22937,8 @@ function canDirectEncode(options) {
22282
22937
  __name(canDirectEncode, "canDirectEncode");
22283
22938
  function directEncodeMap(writer, data, typ, options, refStack) {
22284
22939
  const isMap = typ === "Map";
22285
- const keys = isMap ? data.keys() : Object.keys(data);
22286
- const maxLength = isMap ? data.size : keys.length;
22940
+ const keys2 = isMap ? data.keys() : Object.keys(data);
22941
+ const maxLength = isMap ? data.size : keys2.length;
22287
22942
  if (!maxLength) {
22288
22943
  writer.pushByte(MAJOR_MAP);
22289
22944
  return;
@@ -22292,7 +22947,7 @@ function directEncodeMap(writer, data, typ, options, refStack) {
22292
22947
  const skipUndefined = !isMap && options.ignoreUndefinedProperties;
22293
22948
  const entries = new Array(maxLength);
22294
22949
  let length = 0;
22295
- for (const key of keys) {
22950
+ for (const key of keys2) {
22296
22951
  const value = isMap ? data.get(key) : data[key];
22297
22952
  if (skipUndefined && value === void 0) {
22298
22953
  continue;
@@ -22351,9 +23006,9 @@ function directEncode(writer, data, options, refStack) {
22351
23006
  }
22352
23007
  return;
22353
23008
  case "string": {
22354
- const bytes2 = fromString(data);
22355
- directEncodeUintValue(writer, MAJOR_STRING, bytes2.length);
22356
- writer.push(bytes2);
23009
+ const bytes3 = fromString(data);
23010
+ directEncodeUintValue(writer, MAJOR_STRING, bytes3.length);
23011
+ writer.push(bytes3);
22357
23012
  return;
22358
23013
  }
22359
23014
  case "Uint8Array":
@@ -22716,15 +23371,15 @@ var AWS_ROOT_SHA256 = "641a0321a3e244efe456463195d606317ed7cdcc3c1756e09893f3c68
22716
23371
  var fail = /* @__PURE__ */ __name((reason) => {
22717
23372
  throw new NitroAttestationError(reason);
22718
23373
  }, "fail");
22719
- var hex = /* @__PURE__ */ __name((bytes2) => Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
23374
+ var hex = /* @__PURE__ */ __name((bytes3) => Array.from(bytes3, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
22720
23375
  var bytes = /* @__PURE__ */ __name((value, reason) => value instanceof Uint8Array && value.length > 0 ? value : fail(reason), "bytes");
22721
23376
  var map = /* @__PURE__ */ __name((value, reason) => value instanceof Map ? value : fail(reason), "map");
22722
- var decodeCbor = /* @__PURE__ */ __name((value) => {
23377
+ var decodeCbor = /* @__PURE__ */ __name((value, { allowIndefinite = false } = {}) => {
22723
23378
  try {
22724
23379
  return decode(value, {
22725
23380
  useMaps: true,
22726
23381
  rejectDuplicateMapKeys: true,
22727
- allowIndefinite: false,
23382
+ allowIndefinite,
22728
23383
  allowUndefined: false,
22729
23384
  allowNaN: false,
22730
23385
  allowInfinity: false,
@@ -22782,7 +23437,7 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
22782
23437
  const payloadBytes = bytes(payloadValue, "cose");
22783
23438
  const signature = bytes(signatureValue, "signature");
22784
23439
  if (signature.length !== 96) fail("signature");
22785
- const payload = map(decodeCbor(payloadBytes), "cbor");
23440
+ const payload = map(decodeCbor(payloadBytes, { allowIndefinite: true }), "cbor");
22786
23441
  const moduleId = payload.get("module_id");
22787
23442
  const timestamp = payload.get("timestamp");
22788
23443
  if (typeof moduleId !== "string" || !moduleId || payload.get("digest") !== "SHA384")
@@ -22872,13 +23527,36 @@ var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64,
22872
23527
  } catch {
22873
23528
  return fail("user-data");
22874
23529
  }
23530
+ const rawLedgerKey = payload.get("public_key");
23531
+ let ledgerPublicKey;
23532
+ let measurementHash;
23533
+ if (rawLedgerKey !== void 0 && rawLedgerKey !== null) {
23534
+ const ledger = new Uint8Array(bytes(rawLedgerKey, "user-data"));
23535
+ if (ledger.length !== 65 || ledger[0] !== 4) fail("user-data");
23536
+ try {
23537
+ await crypto.subtle.importKey(
23538
+ "raw",
23539
+ ledger,
23540
+ { name: "ECDSA", namedCurve: "P-256" },
23541
+ false,
23542
+ ["verify"]
23543
+ );
23544
+ } catch {
23545
+ return fail("user-data");
23546
+ }
23547
+ const tuple = new Uint8Array(144);
23548
+ for (let i = 0; i < 3; i++) tuple.set(bytes(rawPcrs.get(i), "pcr"), i * 48);
23549
+ measurementHash = hex(new Uint8Array(await crypto.subtle.digest("SHA-256", tuple)));
23550
+ ledgerPublicKey = bufferToBase64(ledger.buffer);
23551
+ }
22875
23552
  return {
22876
23553
  escrowPublicKeySpkiB64: bufferToBase64(new Uint8Array(spki).buffer),
22877
23554
  keyId: newFormat?.keyId,
22878
23555
  previousKeyIds: newFormat?.previousKeyIds ?? [],
22879
23556
  pcrs,
22880
23557
  timestamp,
22881
- moduleId
23558
+ moduleId,
23559
+ ...ledgerPublicKey ? { ledgerPublicKey, measurementHash } : {}
22882
23560
  };
22883
23561
  }, "verifyNitroAttestationDocument");
22884
23562
 
@@ -22932,7 +23610,13 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
22932
23610
  publicKey: verified.escrowPublicKeySpkiB64,
22933
23611
  keyId: attestation.keyId,
22934
23612
  previousKeyIds: verified.previousKeyIds,
22935
- mode: "nitro"
23613
+ mode: "nitro",
23614
+ ...verified.keyId && verified.ledgerPublicKey && verified.measurementHash ? {
23615
+ authority: {
23616
+ ledgerPublicKey: verified.ledgerPublicKey,
23617
+ measurement: verified.measurementHash
23618
+ }
23619
+ } : {}
22936
23620
  };
22937
23621
  }
22938
23622
  const publicKey = normalizePublicKey(attestation.publicKey);
@@ -22954,6 +23638,393 @@ var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy
22954
23638
  };
22955
23639
  }, "verifyEnclaveAttestation");
22956
23640
 
23641
+ // src/escrow-authority.types.ts
23642
+ var EscrowEvidenceError = class extends Error {
23643
+ static {
23644
+ __name(this, "EscrowEvidenceError");
23645
+ }
23646
+ constructor() {
23647
+ super("Automatic recovery evidence could not be verified.");
23648
+ this.name = "EscrowEvidenceError";
23649
+ }
23650
+ };
23651
+
23652
+ // src/escrow-authority.ts
23653
+ var fail2 = /* @__PURE__ */ __name(() => {
23654
+ throw new EscrowEvidenceError();
23655
+ }, "fail");
23656
+ var requireEvidence = /* @__PURE__ */ __name((condition) => {
23657
+ if (!condition) fail2();
23658
+ }, "requireEvidence");
23659
+ var object = /* @__PURE__ */ __name((value) => {
23660
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail2();
23661
+ return value;
23662
+ }, "object");
23663
+ var keys = /* @__PURE__ */ __name((value, names) => {
23664
+ requireEvidence(
23665
+ Object.keys(value).length === names.length && names.every((name) => Object.prototype.hasOwnProperty.call(value, name))
23666
+ );
23667
+ }, "keys");
23668
+ var integer2 = /* @__PURE__ */ __name((value, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) => {
23669
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum || value > maximum)
23670
+ return fail2();
23671
+ return value;
23672
+ }, "integer");
23673
+ var text = /* @__PURE__ */ __name((value, maximum) => {
23674
+ if (typeof value !== "string" || !value.length || value.length > maximum) return fail2();
23675
+ return value;
23676
+ }, "text");
23677
+ var bytes2 = /* @__PURE__ */ __name((value, length) => {
23678
+ if (!Array.isArray(value) || value.length !== length || !value.every(
23679
+ (byte) => typeof byte === "number" && Number.isInteger(byte) && byte >= 0 && byte <= 255
23680
+ ))
23681
+ return fail2();
23682
+ return Uint8Array.from(value);
23683
+ }, "bytes");
23684
+ var base64 = /* @__PURE__ */ __name((value, maximum) => {
23685
+ const encoded = text(value, maximum);
23686
+ try {
23687
+ const decoded = new Uint8Array(base64ToBuffer(encoded));
23688
+ requireEvidence(bufferToBase64(decoded.buffer) === encoded);
23689
+ return decoded;
23690
+ } catch {
23691
+ return fail2();
23692
+ }
23693
+ }, "base64");
23694
+ var frame = /* @__PURE__ */ __name((value) => {
23695
+ const result = new Uint8Array(4 + value.length);
23696
+ new DataView(result.buffer).setUint32(0, value.length, false);
23697
+ result.set(value, 4);
23698
+ return result;
23699
+ }, "frame");
23700
+ var join2 = /* @__PURE__ */ __name((...values) => {
23701
+ const result = new Uint8Array(values.reduce((n, v) => n + v.length, 0));
23702
+ let offset = 0;
23703
+ for (const value of values) {
23704
+ result.set(value, offset);
23705
+ offset += value.length;
23706
+ }
23707
+ return result;
23708
+ }, "join");
23709
+ var hash = /* @__PURE__ */ __name(async (value) => bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", new Uint8Array(value)))), "hash");
23710
+ var utf82 = /* @__PURE__ */ __name((value) => new TextEncoder().encode(value), "utf8");
23711
+ var escrowAuthorityMeasurements = /* @__PURE__ */ __name(async (policy) => {
23712
+ if (policy.mode !== "nitro") return [];
23713
+ const hashes = [];
23714
+ for (const pin of policy.pinnedMeasurements) {
23715
+ const tuple = [pin.pcr0, pin.pcr1, pin.pcr2];
23716
+ if (!tuple.every((pcr) => typeof pcr === "string" && /^[0-9a-f]{96}$/i.test(pcr))) continue;
23717
+ if (pin.pcr0 === "00".repeat(48)) continue;
23718
+ const encoded = tuple.join("");
23719
+ const decoded = Uint8Array.from(
23720
+ { length: 144 },
23721
+ (_, i) => parseInt(encoded.slice(i * 2, i * 2 + 2), 16)
23722
+ );
23723
+ hashes.push(await hash(decoded));
23724
+ }
23725
+ return hashes;
23726
+ }, "escrowAuthorityMeasurements");
23727
+ var P256_ORDER = BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
23728
+ var verifyRecord = /* @__PURE__ */ __name(async (input, kind, identity, historical) => {
23729
+ requireEvidence(identity.mode === "nitro" && !!identity.authority);
23730
+ const raw = object(input);
23731
+ keys(raw, ["version", "kind", "keyId", "measurement", "payload", "signature"]);
23732
+ requireEvidence(raw.version === 1 && raw.kind === kind);
23733
+ const keyId = text(raw.keyId, 128);
23734
+ requireEvidence(
23735
+ historical ? [identity.keyId, ...identity.previousKeyIds].includes(keyId) : keyId === identity.keyId
23736
+ );
23737
+ const measurement = bytes2(raw.measurement, 32);
23738
+ requireEvidence(
23739
+ historical ? historical.allowedMeasurements.includes(bytesToHex(measurement)) : bytesToHex(measurement) === identity.authority?.measurement
23740
+ );
23741
+ const payloadB64 = text(raw.payload, kind === "snapshot" ? 49152 : 8192);
23742
+ const signatureB64 = text(raw.signature, 88);
23743
+ const payload = base64(payloadB64, kind === "snapshot" ? 49152 : 8192);
23744
+ const signature = base64(signatureB64, 88);
23745
+ const ledgerKey = base64(identity.authority?.ledgerPublicKey, 88);
23746
+ requireEvidence(ledgerKey.length === 65 && ledgerKey[0] === 4);
23747
+ requireEvidence(signature.length === 64);
23748
+ const s = BigInt(`0x${bytesToHex(signature.slice(32))}`);
23749
+ requireEvidence(s > 0n && s <= P256_ORDER / 2n);
23750
+ const message = join2(
23751
+ utf82("learncard-authority-signed-record-v1\0"),
23752
+ Uint8Array.of(kind === "snapshot" ? 2 : 1),
23753
+ frame(utf82(keyId)),
23754
+ measurement,
23755
+ frame(payload)
23756
+ );
23757
+ try {
23758
+ const key = await crypto.subtle.importKey(
23759
+ "raw",
23760
+ ledgerKey,
23761
+ { name: "ECDSA", namedCurve: "P-256" },
23762
+ false,
23763
+ ["verify"]
23764
+ );
23765
+ requireEvidence(
23766
+ await crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, signature, message)
23767
+ );
23768
+ const decoded = JSON.parse(
23769
+ new TextDecoder("utf-8", { fatal: true }).decode(payload)
23770
+ );
23771
+ const record = {
23772
+ version: 1,
23773
+ kind,
23774
+ keyId,
23775
+ measurement: Array.from(measurement),
23776
+ payload: payloadB64,
23777
+ signature: signatureB64
23778
+ };
23779
+ return { record, payload: decoded };
23780
+ } catch {
23781
+ return fail2();
23782
+ }
23783
+ }, "verifyRecord");
23784
+ var envelope = /* @__PURE__ */ __name((value) => {
23785
+ try {
23786
+ const e = parseEscrowEnvelope(value);
23787
+ return {
23788
+ version: e.version,
23789
+ algorithm: e.algorithm,
23790
+ keyId: e.keyId,
23791
+ ephemeralPublicKey: e.ephemeralPublicKey,
23792
+ salt: e.salt,
23793
+ iv: e.iv,
23794
+ ciphertext: e.ciphertext
23795
+ };
23796
+ } catch {
23797
+ return fail2();
23798
+ }
23799
+ }, "envelope");
23800
+ var state = /* @__PURE__ */ __name((value) => {
23801
+ const raw = object(value);
23802
+ keys(raw, [
23803
+ "tenant",
23804
+ "authorityGeneration",
23805
+ "did",
23806
+ "enrollmentVersion",
23807
+ "enrollmentEpoch",
23808
+ "status",
23809
+ "envelope",
23810
+ "shareVersion",
23811
+ "hasPin",
23812
+ "pinGeneration",
23813
+ "attemptsUsed"
23814
+ ]);
23815
+ if (raw.status !== "empty" && raw.status !== "active" && raw.status !== "disabled")
23816
+ return fail2();
23817
+ if (typeof raw.hasPin !== "boolean") return fail2();
23818
+ const result = {
23819
+ tenant: text(raw.tenant, 128),
23820
+ authorityGeneration: text(raw.authorityGeneration, 128),
23821
+ did: text(raw.did, 8192),
23822
+ enrollmentVersion: integer2(raw.enrollmentVersion),
23823
+ enrollmentEpoch: integer2(raw.enrollmentEpoch),
23824
+ status: raw.status,
23825
+ envelope: raw.envelope === null ? null : envelope(raw.envelope),
23826
+ shareVersion: raw.shareVersion === null ? null : integer2(raw.shareVersion, 1, 4294967295),
23827
+ hasPin: raw.hasPin,
23828
+ pinGeneration: integer2(raw.pinGeneration),
23829
+ attemptsUsed: integer2(raw.attemptsUsed, 0, 10)
23830
+ };
23831
+ requireEvidence(
23832
+ result.pinGeneration <= result.enrollmentVersion && result.enrollmentEpoch <= result.enrollmentVersion && (!result.hasPin || result.pinGeneration > 0) && (result.hasPin || result.attemptsUsed === 0)
23833
+ );
23834
+ if (result.status === "empty")
23835
+ requireEvidence(
23836
+ result.enrollmentVersion === 0 && result.enrollmentEpoch === 0 && !result.envelope && result.shareVersion === null && !result.hasPin
23837
+ );
23838
+ else requireEvidence(result.enrollmentVersion > 0 && result.enrollmentEpoch > 0);
23839
+ if (result.status === "active")
23840
+ requireEvidence(!!result.envelope && result.shareVersion !== null);
23841
+ else requireEvidence(result.envelope === null && result.shareVersion === null);
23842
+ return result;
23843
+ }, "state");
23844
+ var verifyEscrowAuthorityState = /* @__PURE__ */ __name(async (response, nonce, tenant, did, identity) => {
23845
+ requireEvidence(/^[0-9a-f]{64}$/.test(nonce) && nonce.length === 64);
23846
+ const raw = object(response);
23847
+ keys(raw, ["state", "proof"]);
23848
+ const { payload } = await verifyRecord(raw.proof, "snapshot", identity);
23849
+ if (!Array.isArray(payload) || payload.length !== 2 || payload[0] !== nonce) return fail2();
23850
+ const signed = state(payload[1]);
23851
+ requireEvidence(signed.tenant === tenant && signed.did === did);
23852
+ requireEvidence(JSON.stringify(signed) === JSON.stringify(state(raw.state)));
23853
+ if (signed.envelope) {
23854
+ requireEvidence(
23855
+ [identity.keyId, ...identity.previousKeyIds].includes(signed.envelope.keyId)
23856
+ );
23857
+ await getEscrowBlobIdentity(signed.envelope);
23858
+ }
23859
+ return signed;
23860
+ }, "verifyEscrowAuthorityState");
23861
+ var verifyEscrowEnrollmentCommit = /* @__PURE__ */ __name(async (response, intent, identity) => {
23862
+ const raw = object(response);
23863
+ const { record, payload } = await verifyRecord(raw.receipt, "commit", identity);
23864
+ const data = object(payload);
23865
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
23866
+ const commit = object(data.commit);
23867
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
23868
+ const binding = object(commit.binding);
23869
+ keys(binding, ["tenant", "generation", "didHash"]);
23870
+ const revisions = object(commit.revisions);
23871
+ keys(revisions, ["operation", "enrollment"]);
23872
+ requireEvidence(
23873
+ commit.schemaVersion === 1 && binding.tenant === intent.tenant && binding.generation === intent.authorityGeneration
23874
+ );
23875
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(intent.did)));
23876
+ requireEvidence(
23877
+ integer2(revisions.enrollment, 1) === intent.expectedEnrollmentVersion + 1 && integer2(revisions.operation, 1) >= integer2(revisions.enrollment, 1)
23878
+ );
23879
+ bytes2(commit.executionId, 16);
23880
+ bytes2(commit.transactionDigest, 32);
23881
+ bytes2(data.eventHash, 32);
23882
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === intent.enrollmentEpoch);
23883
+ requireEvidence(
23884
+ bytesToHex(bytes2(data.requestDigest, 32)) === await hash(encodeEscrowEnrollmentIntent(intent))
23885
+ );
23886
+ if (intent.action === "disable") {
23887
+ requireEvidence(
23888
+ (raw.envelope === null || raw.envelope === void 0) && data.resultBlobIdentity === null
23889
+ );
23890
+ return { envelope: null, receipt: record };
23891
+ }
23892
+ const output = envelope(raw.envelope);
23893
+ requireEvidence(
23894
+ output.keyId === identity.keyId && bytesToHex(bytes2(data.resultBlobIdentity, 32)) === await getEscrowBlobIdentity(output)
23895
+ );
23896
+ return { envelope: output, receipt: record };
23897
+ }, "verifyEscrowEnrollmentCommit");
23898
+ var holdDigest = /* @__PURE__ */ __name(async (tenant, record) => {
23899
+ const h2 = record.hold;
23900
+ const didHash = await hash(utf82(h2.did));
23901
+ return hash(
23902
+ utf82(
23903
+ JSON.stringify([
23904
+ "learncard-hold-v1",
23905
+ tenant,
23906
+ h2.holdId,
23907
+ didHash,
23908
+ h2.shareVersion,
23909
+ h2.blobHash,
23910
+ h2.enrollmentEpoch,
23911
+ h2.releasePolicy,
23912
+ h2.clientEphemeralPublicKey,
23913
+ h2.createdLo,
23914
+ h2.createdHi,
23915
+ record.holdDurationMs,
23916
+ h2.policyVersion,
23917
+ record.ledgerSeq
23918
+ ])
23919
+ )
23920
+ );
23921
+ }, "holdDigest");
23922
+ var verifyEscrowHoldRecord = /* @__PURE__ */ __name(async (record, expected, identity, historical) => {
23923
+ requireEvidence(
23924
+ record.hold.holdId === expected.holdId && record.hold.did === expected.did && record.hold.clientEphemeralPublicKey === expected.clientEphemeralPublicKey && record.hold.blobHash === expected.blobHash
23925
+ );
23926
+ let signed;
23927
+ try {
23928
+ signed = JSON.parse(
23929
+ new TextDecoder("utf-8", { fatal: true }).decode(base64(record.hold.signature, 8192))
23930
+ );
23931
+ } catch {
23932
+ return fail2();
23933
+ }
23934
+ const { record: receipt, payload } = await verifyRecord(signed, "commit", identity, historical);
23935
+ const data = object(payload);
23936
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
23937
+ const commit = object(data.commit);
23938
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
23939
+ const binding = object(commit.binding);
23940
+ keys(binding, ["tenant", "generation", "didHash"]);
23941
+ requireEvidence(commit.schemaVersion === 1 && binding.tenant === expected.tenant);
23942
+ const authorityGeneration = text(binding.generation, 128);
23943
+ if (historical) requireEvidence(authorityGeneration === historical.authorityGeneration);
23944
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
23945
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
23946
+ requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
23947
+ const digest = await holdDigest(expected.tenant, record);
23948
+ requireEvidence(bytesToHex(bytes2(data.requestDigest, 32)) === digest);
23949
+ return { receipt, authorityGeneration, holdDigest: digest };
23950
+ }, "verifyEscrowHoldRecord");
23951
+ var verifyEscrowHoldConfirmation = /* @__PURE__ */ __name(async (receipt, record, expected, identity) => {
23952
+ const raw = object(receipt);
23953
+ const kind = raw.kind;
23954
+ if (kind !== "commit" && kind !== "snapshot") return fail2();
23955
+ const { record: verified, payload } = await verifyRecord(raw, kind, identity);
23956
+ if (kind === "snapshot") {
23957
+ if (!Array.isArray(payload) || payload.length !== 7) return fail2();
23958
+ const [tag, holdId, digestBytes] = payload;
23959
+ requireEvidence(
23960
+ tag === "learncard-authority-hold-snapshot-v2" && holdId === record.hold.holdId && payload[6] === expected.authorityGeneration
23961
+ );
23962
+ requireEvidence(
23963
+ bytesToHex(bytes2(digestBytes, 32)) === await holdDigest(expected.tenant, record)
23964
+ );
23965
+ requireEvidence(payload[3] === "pending");
23966
+ integer2(payload[4], 1);
23967
+ return verified;
23968
+ }
23969
+ const data = object(payload);
23970
+ keys(data, ["commit", "eventHash", "requestDigest", "resultBlobIdentity", "enrollmentEpoch"]);
23971
+ const commit = object(data.commit);
23972
+ keys(commit, ["schemaVersion", "binding", "executionId", "revisions", "transactionDigest"]);
23973
+ const binding = object(commit.binding);
23974
+ keys(binding, ["tenant", "generation", "didHash"]);
23975
+ requireEvidence(
23976
+ commit.schemaVersion === 1 && binding.tenant === expected.tenant && binding.generation === expected.authorityGeneration
23977
+ );
23978
+ requireEvidence(bytesToHex(bytes2(binding.didHash, 32)) === await hash(utf82(expected.did)));
23979
+ requireEvidence(integer2(data.enrollmentEpoch, 1) === record.hold.enrollmentEpoch);
23980
+ requireEvidence(bytesToHex(bytes2(data.resultBlobIdentity, 32)) === record.hold.blobHash);
23981
+ bytes2(data.requestDigest, 32);
23982
+ return verified;
23983
+ }, "verifyEscrowHoldConfirmation");
23984
+ var resolveEscrowEnrollmentAction = /* @__PURE__ */ __name((current, input) => {
23985
+ const disabling = input === "disable";
23986
+ const pinAction = disabling ? "keep" : input === "set" ? current.hasPin ? "change" : "set" : input === "clear" ? current.hasPin ? "clear" : "keep" : "keep";
23987
+ const action = disabling ? "disable" : current.status !== "active" ? "enroll" : current.hasPin && pinAction === "keep" ? "carry" : "replace";
23988
+ return { action, pinAction, bindsRecoveryContact: action === "enroll" || action === "replace" };
23989
+ }, "resolveEscrowEnrollmentAction");
23990
+ var violatesCarryContactRule = /* @__PURE__ */ __name((action, target) => action === "carry" && !!target && (!!target.recoveryEmail || !!target.recoveryLanguage), "violatesCarryContactRule");
23991
+ var createEscrowEnrollmentIntent = /* @__PURE__ */ __name(async (input) => {
23992
+ const current = state(input.state);
23993
+ const target = input.target === null ? null : envelope(input.target);
23994
+ const disabling = input.pinAction === "disable";
23995
+ requireEvidence(
23996
+ current.enrollmentVersion < Number.MAX_SAFE_INTEGER && (disabling || current.enrollmentEpoch < Number.MAX_SAFE_INTEGER)
23997
+ );
23998
+ if (disabling && current.status !== "active") return fail2();
23999
+ if (current.status === "disabled" && current.hasPin && input.pinAction === "automatic")
24000
+ return fail2();
24001
+ const { action, pinAction, bindsRecoveryContact } = resolveEscrowEnrollmentAction(
24002
+ current,
24003
+ input.pinAction
24004
+ );
24005
+ requireEvidence(!disabling || input.target === null);
24006
+ requireEvidence(disabling || input.target !== null);
24007
+ if (action === "carry") requireEvidence(input.shareVersion > (current.shareVersion ?? 0));
24008
+ const intent = {
24009
+ version: 2,
24010
+ tenant: current.tenant,
24011
+ did: current.did,
24012
+ authorityGeneration: current.authorityGeneration,
24013
+ expectedEnrollmentVersion: current.enrollmentVersion,
24014
+ action,
24015
+ sourceBlobIdentity: current.envelope ? await getEscrowBlobIdentity(current.envelope) : null,
24016
+ targetBlobIdentity: target ? await getEscrowBlobIdentity(target) : null,
24017
+ pinAction,
24018
+ shareVersion: disabling ? current.shareVersion : input.shareVersion,
24019
+ enrollmentEpoch: current.enrollmentEpoch + (disabling ? 0 : 1),
24020
+ requestId: crypto.randomUUID(),
24021
+ allowRewrap: !disabling,
24022
+ recoveryEmail: bindsRecoveryContact ? input.recoveryEmail : null,
24023
+ recoveryLanguage: bindsRecoveryContact ? input.recoveryLanguage : null
24024
+ };
24025
+ return signEscrowEnrollmentIntent(intent, input.privateKey);
24026
+ }, "createEscrowEnrollmentIntent");
24027
+
22957
24028
  // src/types.ts
22958
24029
  var import_types = __toESM(require_dist());
22959
24030
  var EscrowPinUnavailableError = class extends Error {
@@ -23698,6 +24769,10 @@ function createSSSStrategy(config) {
23698
24769
  const localWrites = /* @__PURE__ */ new Set();
23699
24770
  const guardedStorage = /* @__PURE__ */ __name(() => {
23700
24771
  const generation = storageGeneration;
24772
+ const assertCurrent = /* @__PURE__ */ __name(() => {
24773
+ if (generation !== storageGeneration)
24774
+ throw new Error("This recovery request was cancelled.");
24775
+ }, "assertCurrent");
23701
24776
  const write = /* @__PURE__ */ __name((operation) => {
23702
24777
  if (generation !== storageGeneration) {
23703
24778
  return Promise.reject(new Error("This recovery request was cancelled."));
@@ -23708,6 +24783,7 @@ function createSSSStrategy(config) {
23708
24783
  }, "write");
23709
24784
  const guarded = {
23710
24785
  ...storage,
24786
+ assertCurrent,
23711
24787
  storeDeviceShare: /* @__PURE__ */ __name((share, id) => write(() => storage.storeDeviceShare(share, id)), "storeDeviceShare"),
23712
24788
  storeShareVersion: /* @__PURE__ */ __name((version, id) => write(() => storage.storeShareVersion(version, id)), "storeShareVersion"),
23713
24789
  clearAllShares: /* @__PURE__ */ __name((id) => write(() => storage.clearAllShares(id)), "clearAllShares"),
@@ -23725,6 +24801,7 @@ function createSSSStrategy(config) {
23725
24801
  let lastServerSnapshot = null;
23726
24802
  let escrowEnrollmentInFlight;
23727
24803
  let staleEscrowReenrollAttempted = false;
24804
+ let verifiedEscrowEnvelope;
23728
24805
  let unenrolledRotation;
23729
24806
  const escrowRequest = /* @__PURE__ */ __name(async (path, init, pinAttempt = false) => {
23730
24807
  const response = await fetch(`${serverUrl}/keys/escrow${path}`, {
@@ -23783,16 +24860,89 @@ function createSSSStrategy(config) {
23783
24860
  );
23784
24861
  return verifyEnclaveAttestation(attestation, config.escrow.attestation, nonce);
23785
24862
  }, "fetchVerifiedEnclaveKey");
23786
- const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false) => {
24863
+ const fetchEscrowHoldStatus = /* @__PURE__ */ __name(async (params) => {
24864
+ const query = new URLSearchParams(
24865
+ "holdId" in params ? { holdId: params.holdId } : { providerType: params.providerType }
24866
+ );
24867
+ const secret = "holdId" in params ? params.resumeToken : params.token;
24868
+ const result = await escrowRequest(`/status?${query}`, {
24869
+ method: "GET",
24870
+ headers: {
24871
+ ...buildHeaders("", void 0, tenantId),
24872
+ "X-Auth-Token": secret
24873
+ }
24874
+ });
24875
+ return result.hold;
24876
+ }, "fetchEscrowHoldStatus");
24877
+ const recoveryExpectations = /* @__PURE__ */ __name((holdId, expected) => {
24878
+ if (!expected || expected.holdId !== holdId || expected.tenant !== (tenantId ?? "learncard") || !expected.did || !expected.clientEphemeralPublicKey || !expected.blobHash || !expected.authorityGeneration || !expected.holdDigest || !expected.ledgerPublicKey || !expected.keyId)
24879
+ throw new EscrowEvidenceError();
24880
+ return { ...expected };
24881
+ }, "recoveryExpectations");
24882
+ const verifyPendingHold = /* @__PURE__ */ __name(async (status, expected, identity) => {
24883
+ 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)
24884
+ throw new EscrowEvidenceError();
24885
+ const record = status.holdRecord;
24886
+ const verified = await verifyEscrowHoldRecord(record, expected, identity, {
24887
+ historical: true,
24888
+ allowedMeasurements: await escrowAuthorityMeasurements(config.escrow.attestation),
24889
+ authorityGeneration: expected.authorityGeneration
24890
+ });
24891
+ if (verified.holdDigest !== expected.holdDigest || verified.receipt.keyId !== expected.keyId)
24892
+ throw new EscrowEvidenceError();
24893
+ return record;
24894
+ }, "verifyPendingHold");
24895
+ const fetchAuthorityState = /* @__PURE__ */ __name(async (token, providerType, privateKey, did, signer, identity, assertCurrent) => {
24896
+ assertCurrent();
24897
+ if (identity.mode !== "nitro" || !identity.authority)
24898
+ throw new Error("The enclave does not support verified enrollment.");
24899
+ const nonce = Array.from(
24900
+ crypto.getRandomValues(new Uint8Array(32)),
24901
+ (byte) => byte.toString(16).padStart(2, "0")
24902
+ ).join("");
24903
+ const vp = await requestFreshDidAuthVp(serverUrl, privateKey, did, signer, tenantId);
24904
+ assertCurrent();
24905
+ const response = await escrowRequest("/authority-state", {
24906
+ method: "POST",
24907
+ headers: buildHeaders(token, vp, tenantId),
24908
+ body: JSON.stringify({ authToken: token, providerType, nonce })
24909
+ });
24910
+ const result = await verifyEscrowAuthorityState(
24911
+ response,
24912
+ nonce,
24913
+ tenantId ?? "learncard",
24914
+ did,
24915
+ identity
24916
+ );
24917
+ assertCurrent();
24918
+ return result;
24919
+ }, "fetchAuthorityState");
24920
+ const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false, assertCurrent = guardedStorage().assertCurrent, recoveryEmail = "", recoveryLanguage = "") => {
23787
24921
  if (!config.escrow?.enabled) throw new Error("Escrow enrollment is disabled");
23788
24922
  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(
24923
+ const identity = verifiedKey ?? await fetchVerifiedEnclaveKey();
24924
+ assertCurrent();
24925
+ const { publicKey, keyId } = identity;
24926
+ const authority = config.escrow.attestation.mode === "nitro" ? await fetchAuthorityState(
24927
+ token,
24928
+ providerType,
24929
+ privateKey,
24930
+ primaryDid,
24931
+ signDidAuthVp,
24932
+ identity,
24933
+ assertCurrent
24934
+ ) : void 0;
24935
+ const bindsRecoveryContact = !authority || resolveEscrowEnrollmentAction(
24936
+ authority,
24937
+ pinMaterial ? "set" : clearPin ? "clear" : "automatic"
24938
+ ).bindsRecoveryContact;
24939
+ const envelope2 = await encryptEscrowBlob(
23791
24940
  {
23792
24941
  recoveryShare: shares.recoveryShare,
23793
24942
  did: primaryDid,
23794
24943
  shareVersion,
23795
- ...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {}
24944
+ ...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {},
24945
+ ...authority && recoveryEmail && bindsRecoveryContact ? { recoveryEmail, recoveryLanguage } : {}
23796
24946
  },
23797
24947
  publicKey,
23798
24948
  keyId
@@ -23804,36 +24954,60 @@ function createSSSStrategy(config) {
23804
24954
  signDidAuthVp,
23805
24955
  tenantId
23806
24956
  );
23807
- await escrowRequest("", {
24957
+ const signedIntent = authority ? await createEscrowEnrollmentIntent({
24958
+ state: authority,
24959
+ target: envelope2,
24960
+ shareVersion,
24961
+ privateKey,
24962
+ pinAction: pinMaterial ? "set" : clearPin ? "clear" : "automatic",
24963
+ recoveryEmail,
24964
+ recoveryLanguage
24965
+ }) : void 0;
24966
+ assertCurrent();
24967
+ verifiedEscrowEnvelope = void 0;
24968
+ const response = await escrowRequest("", {
23808
24969
  method: "POST",
23809
24970
  headers: buildHeaders(token, vp, tenantId),
23810
24971
  body: JSON.stringify({
23811
24972
  authToken: token,
23812
24973
  providerType,
23813
- envelope,
24974
+ envelope: envelope2,
23814
24975
  shareVersion,
23815
24976
  enclaveKeyId: keyId,
23816
24977
  ...pinMaterial ? { pinSalt: pinMaterial.pinSalt } : {},
23817
- ...clearPin ? { clearPin: true } : {}
24978
+ ...(signedIntent ? signedIntent.intent.pinAction === "clear" : clearPin) ? { clearPin: true } : {},
24979
+ ...signedIntent ? { signedIntent, sourceEnvelope: authority?.envelope ?? null } : {}
23818
24980
  })
23819
24981
  });
24982
+ if (signedIntent) {
24983
+ const committed = await verifyEscrowEnrollmentCommit(
24984
+ response,
24985
+ signedIntent.intent,
24986
+ identity
24987
+ );
24988
+ assertCurrent();
24989
+ verifiedEscrowEnvelope = committed.envelope ?? void 0;
24990
+ }
23820
24991
  }, "enrollEscrow");
23821
24992
  const tryEnrollEscrow = /* @__PURE__ */ __name(async (...args) => {
23822
24993
  if (!config.escrow?.enabled) return;
23823
24994
  try {
23824
24995
  await enrollEscrow(...args);
23825
- } catch (err) {
24996
+ } catch (err2) {
23826
24997
  try {
23827
- if (config.onEscrowError) config.onEscrowError(err);
24998
+ if (config.onEscrowError) config.onEscrowError(err2);
23828
24999
  else console.warn("SSS: escrow enrollment failed");
23829
25000
  } catch {
23830
25001
  console.warn("SSS: escrow error reporting failed");
23831
25002
  }
23832
25003
  }
23833
25004
  }, "tryEnrollEscrow");
23834
- const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false) => {
25005
+ const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false, allowDisabledEnrollment = false) => {
25006
+ let clearPinForEnrollment = forceRotate;
23835
25007
  if (!config.escrow?.enabled) return { enrolled: false, reason: "disabled" };
23836
25008
  const pin = params.options?.pin;
25009
+ const recoveryEmail = params.options?.recoveryEmail ?? "";
25010
+ const recoveryLanguage = params.options?.recoveryLanguage ?? "";
23837
25011
  if (pin !== void 0) {
23838
25012
  const validation = validatePin(pin);
23839
25013
  if (!validation.ok)
@@ -23842,12 +25016,35 @@ function createSSSStrategy(config) {
23842
25016
  );
23843
25017
  }
23844
25018
  const status = await self.fetchServerKeyStatus(params.token, params.providerType);
25019
+ storage2.assertCurrent();
23845
25020
  if (status.escrowOptedOut) return { enrolled: false, reason: "opted-out" };
23846
- const currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
25021
+ let currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
23847
25022
  (method) => method.type === "escrow" && method.shareVersion === status.shareVersion && (Boolean(method.confirmedAt) || "confirmationStatus" in method && method.confirmationStatus === "confirmed")
23848
25023
  );
23849
- const repairingStaleBlob = pin === void 0 && !forceRotate && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
23850
- if (!forceRotate && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
25024
+ let verifiedKey;
25025
+ if (config.escrow.attestation.mode === "nitro") {
25026
+ if (!status.primaryDid || !params.signDidAuthVp)
25027
+ throw new Error("Owner proof signing is required for escrow enrollment.");
25028
+ verifiedKey = await fetchVerifiedEnclaveKey();
25029
+ const current = await fetchAuthorityState(
25030
+ params.token,
25031
+ params.providerType,
25032
+ params.privateKey,
25033
+ status.primaryDid,
25034
+ params.signDidAuthVp,
25035
+ verifiedKey,
25036
+ storage2.assertCurrent
25037
+ );
25038
+ if (current.status === "disabled") {
25039
+ verifiedEscrowEnvelope = void 0;
25040
+ if (!allowDisabledEnrollment) return { enrolled: false, reason: "opted-out" };
25041
+ clearPinForEnrollment ||= current.hasPin && pin === void 0;
25042
+ }
25043
+ currentlyEnrolled = currentlyEnrolled && current.status === "active" && current.shareVersion === status.shareVersion && current.envelope?.keyId === verifiedKey.keyId;
25044
+ if (currentlyEnrolled) verifiedEscrowEnvelope = current.envelope ?? void 0;
25045
+ }
25046
+ const repairingStaleBlob = pin === void 0 && !clearPinForEnrollment && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
25047
+ if (!clearPinForEnrollment && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
23851
25048
  return { enrolled: true, changed: false };
23852
25049
  if (repairingStaleBlob) staleEscrowReenrollAttempted = true;
23853
25050
  if (!status.primaryDid) throw new Error("Cannot enroll escrow without a primary DID");
@@ -23855,7 +25052,7 @@ function createSSSStrategy(config) {
23855
25052
  throw new Error("DID proof signing is required for escrow enrollment");
23856
25053
  }
23857
25054
  try {
23858
- if (!forceRotate && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
25055
+ if (!clearPinForEnrollment && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
23859
25056
  const retry = unenrolledRotation;
23860
25057
  await enrollEscrow(
23861
25058
  params.token,
@@ -23867,12 +25064,16 @@ function createSSSStrategy(config) {
23867
25064
  params.signDidAuthVp,
23868
25065
  void 0,
23869
25066
  void 0,
23870
- retry.clearPin
25067
+ retry.clearPin,
25068
+ storage2.assertCurrent,
25069
+ recoveryEmail,
25070
+ recoveryLanguage
23871
25071
  );
23872
25072
  unenrolledRotation = void 0;
23873
25073
  return { enrolled: true, changed: true, shareVersion: retry.shareVersion };
23874
25074
  }
23875
- const verifiedKey = await fetchVerifiedEnclaveKey();
25075
+ verifiedKey ??= await fetchVerifiedEnclaveKey();
25076
+ storage2.assertCurrent();
23876
25077
  const pinSalt = pin !== void 0 ? generatePinSalt() : void 0;
23877
25078
  const pinMaterial = pin !== void 0 && pinSalt !== void 0 ? { pinSalt, pinVerifier: await derivePinProof(pin, pinSalt) } : void 0;
23878
25079
  const storageId = activeStorageId;
@@ -23901,7 +25102,12 @@ function createSSSStrategy(config) {
23901
25102
  authShare: shares.authShare,
23902
25103
  primaryDid: status.primaryDid
23903
25104
  };
23904
- unenrolledRotation = pinMaterial ? void 0 : { shares, shareVersion, primaryDid: status.primaryDid, clearPin: forceRotate };
25105
+ unenrolledRotation = pinMaterial ? void 0 : {
25106
+ shares,
25107
+ shareVersion,
25108
+ primaryDid: status.primaryDid,
25109
+ clearPin: clearPinForEnrollment
25110
+ };
23905
25111
  await enrollEscrow(
23906
25112
  params.token,
23907
25113
  params.providerType,
@@ -23912,14 +25118,17 @@ function createSSSStrategy(config) {
23912
25118
  params.signDidAuthVp,
23913
25119
  verifiedKey,
23914
25120
  pinMaterial,
23915
- forceRotate
25121
+ clearPinForEnrollment,
25122
+ storage2.assertCurrent,
25123
+ recoveryEmail,
25124
+ recoveryLanguage
23916
25125
  );
23917
25126
  unenrolledRotation = void 0;
23918
25127
  return { enrolled: true, changed: true, shareVersion };
23919
- } catch (err) {
23920
- if (!repairingStaleBlob) throw err;
25128
+ } catch (err2) {
25129
+ if (!repairingStaleBlob || config.escrow.attestation.mode === "nitro") throw err2;
23921
25130
  try {
23922
- if (config.onEscrowError) config.onEscrowError(err);
25131
+ if (config.onEscrowError) config.onEscrowError(err2);
23923
25132
  else console.warn("SSS: escrow enrollment failed");
23924
25133
  } catch {
23925
25134
  console.warn("SSS: escrow error reporting failed");
@@ -23958,6 +25167,7 @@ function createSSSStrategy(config) {
23958
25167
  },
23959
25168
  // --- User scoping ---
23960
25169
  setActiveUser(userId) {
25170
+ verifiedEscrowEnvelope = void 0;
23961
25171
  if (activeStorageId !== `sss-device-share:${userId}`) storageGeneration++;
23962
25172
  activeStorageId = `sss-device-share:${userId}`;
23963
25173
  lastServerSnapshot = null;
@@ -24002,6 +25212,7 @@ function createSSSStrategy(config) {
24002
25212
  );
24003
25213
  }
24004
25214
  storageGeneration++;
25215
+ verifiedEscrowEnvelope = void 0;
24005
25216
  await Promise.allSettled(localWrites);
24006
25217
  await clearPendingShareCandidates(storage, storageId);
24007
25218
  return storage.clearAllShares(storageId);
@@ -24300,8 +25511,58 @@ function createSSSStrategy(config) {
24300
25511
  return { state: enrolled ? "enrolled" : "not-enrolled", escrowPin: status.escrowPin };
24301
25512
  },
24302
25513
  async disableEscrowRecovery(params) {
25514
+ const assertCurrent = guardedStorage().assertCurrent;
24303
25515
  const status = await this.fetchServerKeyStatus(params.token, params.providerType);
24304
25516
  if (!status.primaryDid) throw new Error("Cannot disable escrow without a primary DID");
25517
+ if (config.escrow?.attestation.mode === "nitro") {
25518
+ const identity = await fetchVerifiedEnclaveKey();
25519
+ const current = await fetchAuthorityState(
25520
+ params.token,
25521
+ params.providerType,
25522
+ params.privateKey,
25523
+ status.primaryDid,
25524
+ params.signDidAuthVp,
25525
+ identity,
25526
+ assertCurrent
25527
+ );
25528
+ if (current.status === "disabled") {
25529
+ verifiedEscrowEnvelope = void 0;
25530
+ return;
25531
+ }
25532
+ const signedIntent = await createEscrowEnrollmentIntent({
25533
+ state: current,
25534
+ target: null,
25535
+ shareVersion: current.shareVersion ?? 0,
25536
+ privateKey: params.privateKey,
25537
+ pinAction: "disable",
25538
+ // Disable always nulls these server-side regardless of input.
25539
+ recoveryEmail: "",
25540
+ recoveryLanguage: ""
25541
+ });
25542
+ const vp2 = await requestFreshDidAuthVp(
25543
+ serverUrl,
25544
+ params.privateKey,
25545
+ status.primaryDid,
25546
+ params.signDidAuthVp,
25547
+ tenantId
25548
+ );
25549
+ assertCurrent();
25550
+ const response = await escrowRequest("/disable", {
25551
+ method: "POST",
25552
+ headers: buildHeaders(params.token, vp2, tenantId),
25553
+ body: JSON.stringify({
25554
+ authToken: params.token,
25555
+ providerType: params.providerType,
25556
+ optOut: true,
25557
+ signedIntent,
25558
+ sourceEnvelope: current.envelope
25559
+ })
25560
+ });
25561
+ await verifyEscrowEnrollmentCommit(response, signedIntent.intent, identity);
25562
+ assertCurrent();
25563
+ verifiedEscrowEnvelope = void 0;
25564
+ return;
25565
+ }
24305
25566
  const vp = await requestFreshDidAuthVp(
24306
25567
  serverUrl,
24307
25568
  params.privateKey,
@@ -24342,13 +25603,29 @@ function createSSSStrategy(config) {
24342
25603
  providerType: params.providerType
24343
25604
  })
24344
25605
  });
24345
- return ensureEscrowEnrollmentUnguarded(this, params, storage2);
25606
+ return ensureEscrowEnrollmentUnguarded(this, params, storage2, false, true);
24346
25607
  });
24347
25608
  },
24348
25609
  async setEscrowPin({ pin, ...params }) {
24349
25610
  const storage2 = guardedStorage();
24350
25611
  const result = await withRotationLock(
24351
- () => ensureEscrowEnrollmentUnguarded(this, { ...params, options: { pin } }, storage2)
25612
+ () => (
25613
+ // P9.1: preserve the caller's recoveryEmail/recoveryLanguage — do
25614
+ // not replace `params.options` wholesale, or nitro enroll/replace
25615
+ // loses its required recovery contact.
25616
+ ensureEscrowEnrollmentUnguarded(
25617
+ this,
25618
+ {
25619
+ ...params,
25620
+ options: {
25621
+ pin,
25622
+ recoveryEmail: params.options?.recoveryEmail,
25623
+ recoveryLanguage: params.options?.recoveryLanguage
25624
+ }
25625
+ },
25626
+ storage2
25627
+ )
25628
+ )
24352
25629
  );
24353
25630
  if (!result.enrolled || !result.changed) {
24354
25631
  throw new Error("Automatic recovery is not available for this account.");
@@ -24380,8 +25657,15 @@ function createSSSStrategy(config) {
24380
25657
  escrowEnrollmentInFlight = void 0;
24381
25658
  }
24382
25659
  },
25660
+ getVerifiedEscrowEnvelope() {
25661
+ return verifiedEscrowEnvelope ? { ...verifiedEscrowEnvelope } : null;
25662
+ },
24383
25663
  /** Start or explicitly restart a hold with fresh client-bound resume secrets. */
24384
25664
  async startEscrowRecovery(params) {
25665
+ const expectedDid = params.expectedDid;
25666
+ const nitro = config.escrow?.attestation.mode === "nitro";
25667
+ if (nitro && (!expectedDid || (params.tenantId ?? tenantId) !== tenantId))
25668
+ throw new EscrowEvidenceError();
24385
25669
  const sessionProof = params.recoverySessionToken !== void 0;
24386
25670
  if (sessionProof ? params.token !== void 0 || params.providerType !== void 0 : !params.token || !params.providerType) {
24387
25671
  throw new Error("Provide exactly one identity proof");
@@ -24401,25 +25685,101 @@ function createSSSStrategy(config) {
24401
25685
  },
24402
25686
  params.options?.releasePolicy === "pin"
24403
25687
  );
24404
- return { ...result, clientEphemeralPrivateKey: pair.privateKey };
25688
+ let expectations;
25689
+ if (nitro && result.resumeToken !== null) {
25690
+ const identity = await fetchVerifiedEnclaveKey();
25691
+ if (identity.mode !== "nitro" || !identity.authority || !result.holdRecord || !expectedDid)
25692
+ throw new EscrowEvidenceError();
25693
+ const verified = await verifyEscrowHoldRecord(
25694
+ result.holdRecord,
25695
+ {
25696
+ tenant: tenantId ?? "learncard",
25697
+ did: expectedDid,
25698
+ holdId: result.holdId,
25699
+ clientEphemeralPublicKey: pair.publicKey,
25700
+ blobHash: result.holdRecord.hold.blobHash
25701
+ },
25702
+ identity
25703
+ );
25704
+ expectations = {
25705
+ tenant: tenantId ?? "learncard",
25706
+ did: expectedDid,
25707
+ holdId: result.holdId,
25708
+ clientEphemeralPublicKey: pair.publicKey,
25709
+ blobHash: result.holdRecord.hold.blobHash,
25710
+ authorityGeneration: verified.authorityGeneration,
25711
+ holdDigest: verified.holdDigest,
25712
+ ledgerPublicKey: identity.authority.ledgerPublicKey,
25713
+ keyId: verified.receipt.keyId
25714
+ };
25715
+ }
25716
+ return { ...result, clientEphemeralPrivateKey: pair.privateKey, expectations };
24405
25717
  },
24406
25718
  /** Read hold status; secrets (auth or resume token) never travel in a URL. */
24407
25719
  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
- }
25720
+ const expected = config.escrow?.attestation.mode === "nitro" && "holdId" in params ? recoveryExpectations(params.holdId, params.expectations) : void 0;
25721
+ const status = await fetchEscrowHoldStatus(params);
25722
+ if (expected && status)
25723
+ await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
25724
+ return status;
25725
+ },
25726
+ /** Submit the confirmation code emailed by the enclave for an authority-mode hold. */
25727
+ async confirmEscrowRecovery(params) {
25728
+ let pending;
25729
+ if (config.escrow?.attestation.mode === "nitro") {
25730
+ const expected = recoveryExpectations(params.holdId, params.expectations);
25731
+ if ((params.tenantId ?? tenantId) !== tenantId) throw new EscrowEvidenceError();
25732
+ const identity = await fetchVerifiedEnclaveKey();
25733
+ const status = await fetchEscrowHoldStatus({
25734
+ holdId: params.holdId,
25735
+ resumeToken: params.resumeToken
25736
+ });
25737
+ if (!status?.holdRecord) {
25738
+ throw new EscrowEvidenceError();
24420
25739
  }
24421
- );
24422
- return result.hold;
25740
+ const holdRecord = await verifyPendingHold(status, expected, identity);
25741
+ pending = { identity, holdRecord, expected };
25742
+ }
25743
+ const confirm = /* @__PURE__ */ __name(() => escrowRequest("/confirm", {
25744
+ method: "POST",
25745
+ headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
25746
+ body: JSON.stringify({
25747
+ holdId: params.holdId,
25748
+ resumeToken: params.resumeToken,
25749
+ code: params.code
25750
+ })
25751
+ }), "confirm");
25752
+ const result = await confirm();
25753
+ if (pending) {
25754
+ if (!result.receipt) {
25755
+ throw new EscrowEvidenceError();
25756
+ }
25757
+ const receipt = await verifyEscrowHoldConfirmation(
25758
+ result.receipt,
25759
+ pending.holdRecord,
25760
+ pending.expected,
25761
+ pending.identity
25762
+ );
25763
+ if (receipt.kind === "commit") {
25764
+ const readback = await confirm();
25765
+ const snapshot = await verifyEscrowHoldConfirmation(
25766
+ readback.receipt,
25767
+ pending.holdRecord,
25768
+ pending.expected,
25769
+ pending.identity
25770
+ );
25771
+ if (snapshot.kind !== "snapshot") throw new EscrowEvidenceError();
25772
+ }
25773
+ }
25774
+ return { success: true };
25775
+ },
25776
+ /** Request a fresh confirmation code for a hold awaiting confirmation. */
25777
+ async resendEscrowRecoveryCode(params) {
25778
+ return escrowRequest("/resend", {
25779
+ method: "POST",
25780
+ headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
25781
+ body: JSON.stringify({ holdId: params.holdId, resumeToken: params.resumeToken })
25782
+ });
24423
25783
  },
24424
25784
  /** Cancel a pending hold with a fresh DID-owner proof. */
24425
25785
  async cancelEscrowRecovery(params) {
@@ -24451,8 +25811,19 @@ function createSSSStrategy(config) {
24451
25811
  const start = input.method === "escrow-pin" ? await this.startEscrowRecovery({
24452
25812
  token,
24453
25813
  providerType,
25814
+ expectedDid: input.expectedDid,
24454
25815
  options: { releasePolicy: "pin" }
24455
25816
  }) : input;
25817
+ const expected = config.escrow?.attestation.mode === "nitro" ? recoveryExpectations(start.holdId, start.expectations) : void 0;
25818
+ if (expected) {
25819
+ if (!start.resumeToken) throw new EscrowEvidenceError();
25820
+ const status = await fetchEscrowHoldStatus({
25821
+ holdId: start.holdId,
25822
+ resumeToken: start.resumeToken
25823
+ });
25824
+ if (!status) throw new EscrowEvidenceError();
25825
+ await verifyPendingHold(status, expected, await fetchVerifiedEnclaveKey());
25826
+ }
24456
25827
  let pinProof;
24457
25828
  if (input.method === "escrow-pin") {
24458
25829
  if (!("pinSalt" in start) || !start.pinSalt || !start.resumeToken)
@@ -24476,6 +25847,8 @@ function createSSSStrategy(config) {
24476
25847
  material.sealedShare,
24477
25848
  start.clientEphemeralPrivateKey
24478
25849
  );
25850
+ if (expected && (plaintext.did !== expected.did || plaintext.holdId !== expected.holdId))
25851
+ throw new EscrowEvidenceError();
24479
25852
  if (plaintext.holdId !== start.holdId || plaintext.did !== material.primaryDid || plaintext.shareVersion !== material.shareVersion) {
24480
25853
  throw new Error("Escrow recovery material does not match the request");
24481
25854
  }
@@ -24889,10 +26262,10 @@ function createSSSStrategy(config) {
24889
26262
  const pending = pendingPhraseConfirmation;
24890
26263
  if (!pending) throw new Error("Generate a new recovery phrase to continue");
24891
26264
  const phraseWords = pending.phrase.trim().toLowerCase().split(/\s+/);
24892
- const matches = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
26265
+ const matches2 = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
24893
26266
  (wordIndex, answerIndex) => input.challengeWords[answerIndex]?.trim().toLowerCase() === phraseWords[wordIndex]
24894
26267
  );
24895
- if (!matches) {
26268
+ if (!matches2) {
24896
26269
  throw new Error("Those words do not match. Check your phrase and try again.");
24897
26270
  }
24898
26271
  } else if (input.method === "backup") {
@@ -25278,6 +26651,7 @@ function createSSSStrategy(config) {
25278
26651
  },
25279
26652
  async cleanup() {
25280
26653
  storageGeneration++;
26654
+ verifiedEscrowEnvelope = void 0;
25281
26655
  await Promise.allSettled(localWrites);
25282
26656
  }
25283
26657
  };
@@ -25498,3 +26872,8 @@ var notifyDevicesForQrSession = /* @__PURE__ */ __name(async (config, sessionId,
25498
26872
  return { sent: false, deviceCount: 0 };
25499
26873
  }
25500
26874
  }, "notifyDevicesForQrSession");
26875
+ /*! Bundled license information:
26876
+
26877
+ @noble/ed25519/index.js:
26878
+ (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
26879
+ */