@interop/wallet-core 0.41.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +17 -4
  2. package/dist/clients/rosterPolicy.d.ts +22 -15
  3. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  4. package/dist/clients/rosterPolicy.js +32 -15
  5. package/dist/clients/rosterPolicy.js.map +1 -1
  6. package/dist/descriptors/index.d.ts +1 -1
  7. package/dist/descriptors/index.d.ts.map +1 -1
  8. package/dist/descriptors/index.js +1 -1
  9. package/dist/descriptors/index.js.map +1 -1
  10. package/dist/descriptors/logSource.d.ts +58 -6
  11. package/dist/descriptors/logSource.d.ts.map +1 -1
  12. package/dist/descriptors/logSource.js +57 -15
  13. package/dist/descriptors/logSource.js.map +1 -1
  14. package/dist/enrollment/enrollment.d.ts.map +1 -1
  15. package/dist/enrollment/enrollment.js +14 -26
  16. package/dist/enrollment/enrollment.js.map +1 -1
  17. package/dist/keyring/fetch.d.ts +12 -0
  18. package/dist/keyring/fetch.d.ts.map +1 -1
  19. package/dist/keyring/fetch.js +0 -2
  20. package/dist/keyring/fetch.js.map +1 -1
  21. package/dist/keyring/index.d.ts +1 -1
  22. package/dist/keyring/index.d.ts.map +1 -1
  23. package/dist/keyring/index.js +1 -1
  24. package/dist/keyring/index.js.map +1 -1
  25. package/dist/keyring/kdf.d.ts +22 -6
  26. package/dist/keyring/kdf.d.ts.map +1 -1
  27. package/dist/keyring/kdf.js +9 -14
  28. package/dist/keyring/kdf.js.map +1 -1
  29. package/dist/keys/index.d.ts +1 -1
  30. package/dist/keys/index.d.ts.map +1 -1
  31. package/dist/keys/index.js +1 -1
  32. package/dist/keys/index.js.map +1 -1
  33. package/dist/keys/rosterLogStore.d.ts +4 -1
  34. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  35. package/dist/keys/rosterLogStore.js +13 -16
  36. package/dist/keys/rosterLogStore.js.map +1 -1
  37. package/dist/keys/rosterStore.d.ts +13 -1
  38. package/dist/keys/rosterStore.d.ts.map +1 -1
  39. package/dist/keys/rosterStore.js +18 -0
  40. package/dist/keys/rosterStore.js.map +1 -1
  41. package/dist/keys/userKeyRoster.d.ts +17 -5
  42. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  43. package/dist/keys/userKeyRoster.js +38 -13
  44. package/dist/keys/userKeyRoster.js.map +1 -1
  45. package/dist/recovery/index.d.ts +14 -12
  46. package/dist/recovery/index.d.ts.map +1 -1
  47. package/dist/recovery/index.js +13 -11
  48. package/dist/recovery/index.js.map +1 -1
  49. package/dist/recovery/recoveryCode.d.ts +5 -17
  50. package/dist/recovery/recoveryCode.d.ts.map +1 -1
  51. package/dist/recovery/recoveryCode.js +4 -14
  52. package/dist/recovery/recoveryCode.js.map +1 -1
  53. package/dist/recovery/recoveryDelegation.d.ts +50 -19
  54. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  55. package/dist/recovery/recoveryDelegation.js +86 -41
  56. package/dist/recovery/recoveryDelegation.js.map +1 -1
  57. package/dist/recovery/recoveryWebvh.d.ts +13 -22
  58. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  59. package/dist/recovery/recoveryWebvh.js +37 -129
  60. package/dist/recovery/recoveryWebvh.js.map +1 -1
  61. package/dist/resourceLog/append.d.ts +12 -3
  62. package/dist/resourceLog/append.d.ts.map +1 -1
  63. package/dist/resourceLog/append.js +17 -10
  64. package/dist/resourceLog/append.js.map +1 -1
  65. package/dist/resourceLog/index.d.ts +1 -1
  66. package/dist/resourceLog/index.d.ts.map +1 -1
  67. package/dist/resourceLog/index.js +1 -1
  68. package/dist/resourceLog/index.js.map +1 -1
  69. package/dist/resourceLog/pin.d.ts +46 -8
  70. package/dist/resourceLog/pin.d.ts.map +1 -1
  71. package/dist/resourceLog/pin.js +32 -7
  72. package/dist/resourceLog/pin.js.map +1 -1
  73. package/dist/resourceLog/seal.d.ts +4 -1
  74. package/dist/resourceLog/seal.d.ts.map +1 -1
  75. package/dist/resourceLog/seal.js +6 -2
  76. package/dist/resourceLog/seal.js.map +1 -1
  77. package/dist/unlock/index.d.ts +40 -0
  78. package/dist/unlock/index.d.ts.map +1 -0
  79. package/dist/unlock/index.js +36 -0
  80. package/dist/unlock/index.js.map +1 -0
  81. package/dist/unlock/ladder.d.ts +100 -0
  82. package/dist/unlock/ladder.d.ts.map +1 -0
  83. package/dist/unlock/ladder.js +144 -0
  84. package/dist/unlock/ladder.js.map +1 -0
  85. package/dist/unlock/selfEnroll.d.ts +83 -0
  86. package/dist/unlock/selfEnroll.d.ts.map +1 -0
  87. package/dist/unlock/selfEnroll.js +126 -0
  88. package/dist/unlock/selfEnroll.js.map +1 -0
  89. package/dist/unlock/standingClient.d.ts +68 -0
  90. package/dist/unlock/standingClient.d.ts.map +1 -0
  91. package/dist/unlock/standingClient.js +81 -0
  92. package/dist/unlock/standingClient.js.map +1 -0
  93. package/dist/unlock/standingWebvh.d.ts +153 -0
  94. package/dist/unlock/standingWebvh.d.ts.map +1 -0
  95. package/dist/unlock/standingWebvh.js +370 -0
  96. package/dist/unlock/standingWebvh.js.map +1 -0
  97. package/dist/unlock/unlockRecord.d.ts +207 -0
  98. package/dist/unlock/unlockRecord.d.ts.map +1 -0
  99. package/dist/unlock/unlockRecord.js +435 -0
  100. package/dist/unlock/unlockRecord.js.map +1 -0
  101. package/dist/webvh/didWebvh.d.ts +94 -6
  102. package/dist/webvh/didWebvh.d.ts.map +1 -1
  103. package/dist/webvh/didWebvh.js +175 -19
  104. package/dist/webvh/didWebvh.js.map +1 -1
  105. package/dist/webvh/index.d.ts +7 -2
  106. package/dist/webvh/index.d.ts.map +1 -1
  107. package/dist/webvh/index.js +7 -2
  108. package/dist/webvh/index.js.map +1 -1
  109. package/dist/webvh/keyAgreement.d.ts +22 -6
  110. package/dist/webvh/keyAgreement.d.ts.map +1 -1
  111. package/dist/webvh/keyAgreement.js +1 -1
  112. package/dist/webvh/keyAgreement.js.map +1 -1
  113. package/dist/webvh/verifyLog.d.ts +15 -2
  114. package/dist/webvh/verifyLog.d.ts.map +1 -1
  115. package/dist/webvh/verifyLog.js +22 -3
  116. package/dist/webvh/verifyLog.js.map +1 -1
  117. package/package.json +11 -5
  118. package/dist/recovery/recoveryRecord.d.ts +0 -172
  119. package/dist/recovery/recoveryRecord.d.ts.map +0 -1
  120. package/dist/recovery/recoveryRecord.js +0 -288
  121. package/dist/recovery/recoveryRecord.js.map +0 -1
@@ -11,21 +11,46 @@
11
11
  * adopted. Storage is the app's concern (freewallet: beside its other pins in
12
12
  * localStorage; DCW: a table row), so only the seam lives here, plus an
13
13
  * in-memory implementation for tests and single-session use.
14
+ *
15
+ * The seam is keyed: every read and write names the log it concerns with a
16
+ * `logId`, so one store instance serves every log a wallet holds. Wallet-core
17
+ * supplies the key at every call, built by {@link resourceLogPinId} (or one of
18
+ * the named builders over it), so an app implements one keyed store and never
19
+ * chooses keys itself.
20
+ */
21
+ /**
22
+ * The pin-slot key for one log: an opaque per-log identity key for pin
23
+ * storage, not a fetchable path or URL.
24
+ *
25
+ * It is deliberately host-free. The `spaceId` is the account's stable random
26
+ * id, so a log served from a claimed new host lands in the SAME pin slot and
27
+ * is checked against the pin already held, rather than opening a fresh
28
+ * trust-on-first-use slate (the mirror-fork concern).
29
+ *
30
+ * @param options {object}
31
+ * @param options.spaceId {string} the Space the log lives in
32
+ * @param options.collectionId {string} the collection holding the log
33
+ * @param options.resourceId {string} the log resource's id
34
+ * @returns {string}
14
35
  */
36
+ export function resourceLogPinId({ spaceId, collectionId, resourceId }) {
37
+ return `space/${spaceId}/${collectionId}/${resourceId}`;
38
+ }
15
39
  /**
16
- * An in-memory pin store: continuity within one session only. Tests use it
17
- * as the seam's reference implementation; apps persist for real.
40
+ * An in-memory pin store: continuity within one session only, keyed by
41
+ * `logId` like any other implementation, so one instance serves several logs.
42
+ * Tests use it as the seam's reference implementation; apps persist for real.
18
43
  *
19
44
  * @returns {ResourceLogPinStore}
20
45
  */
21
46
  export function memoryResourceLogPinStore() {
22
- let pin = null;
47
+ const pins = new Map();
23
48
  return {
24
- async read() {
25
- return pin;
49
+ async read({ logId }) {
50
+ return pins.get(logId) ?? null;
26
51
  },
27
- async write(next) {
28
- pin = next;
52
+ async write({ logId, pin }) {
53
+ pins.set(logId, pin);
29
54
  }
30
55
  };
31
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pin.js","sourceRoot":"","sources":["../../src/resourceLog/pin.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;GAUG;AA0BH;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,IAAI,GAAG,GAA8B,IAAI,CAAA;IACzC,OAAO;QACL,KAAK,CAAC,IAAI;YACR,OAAO,GAAG,CAAA;QACZ,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,IAAwB;YAClC,GAAG,GAAG,IAAI,CAAA;QACZ,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"pin.js","sourceRoot":"","sources":["../../src/resourceLog/pin.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;GAgBG;AAgCH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAC/B,OAAO,EACP,YAAY,EACZ,UAAU,EAKX;IACC,OAAO,SAAS,OAAO,IAAI,YAAY,IAAI,UAAU,EAAE,CAAA;AACzD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,IAAI,GAAG,IAAI,GAAG,EAA8B,CAAA;IAClD,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE;YAClB,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAA;QAChC,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACtB,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -67,6 +67,8 @@ export declare function latestAssertionRemovalIndex({ controller }: {
67
67
  * @param options.expectedMethod {string} the format identifier expected
68
68
  * @param options.pinStore {ResourceLogPinStore} this client's chain-head
69
69
  * pin for this log
70
+ * @param options.logId {string} the pin-slot key for this log, from
71
+ * `resourceLogPinId`
70
72
  * @param options.signer {ResourceLogSigner} this client's enrolled signing
71
73
  * key
72
74
  * @param [options.versionTime] {string} RFC3339 UTC; defaults to now
@@ -79,11 +81,12 @@ export declare function latestAssertionRemovalIndex({ controller }: {
79
81
  * anything is written
80
82
  * @returns {Promise<{ sealed: boolean, verified: VerifiedResourceLog | null }>}
81
83
  */
82
- export declare function sealResourceLog({ store, controller, expectedMethod, pinStore, signer, versionTime, verified: knownVerified }: {
84
+ export declare function sealResourceLog({ store, controller, expectedMethod, pinStore, logId, signer, versionTime, verified: knownVerified }: {
83
85
  store: ResourceLogStore;
84
86
  controller: ResourceLogController;
85
87
  expectedMethod: string;
86
88
  pinStore: ResourceLogPinStore;
89
+ logId: string;
87
90
  signer: ResourceLogSigner;
88
91
  versionTime?: string;
89
92
  verified?: VerifiedResourceLog;
@@ -1 +1 @@
1
- {"version":3,"file":"seal.d.ts","sourceRoot":"","sources":["../../src/resourceLog/seal.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,UAAU,EACX,EAAE;IACD,UAAU,EAAE,qBAAqB,CAAA;CAClC,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,eAAe,CAAC,EACpC,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,MAAM,EACN,WAAW,EACX,QAAQ,EAAE,aAAa,EACxB,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,MAAM,EAAE,iBAAiB,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAC/B,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,CAAC,CA2CrE"}
1
+ {"version":3,"file":"seal.d.ts","sourceRoot":"","sources":["../../src/resourceLog/seal.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,2BAA2B,CAAC,EAChD,UAAU,EACX,EAAE;IACD,UAAU,EAAE,qBAAqB,CAAA;CAClC,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,eAAe,CAAC,EACpC,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,KAAK,EACL,MAAM,EACN,WAAW,EACX,QAAQ,EAAE,aAAa,EACxB,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,iBAAiB,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAC/B,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAAE,CAAC,CA6CrE"}
@@ -53,6 +53,8 @@ export async function latestAssertionRemovalIndex({ controller }) {
53
53
  * @param options.expectedMethod {string} the format identifier expected
54
54
  * @param options.pinStore {ResourceLogPinStore} this client's chain-head
55
55
  * pin for this log
56
+ * @param options.logId {string} the pin-slot key for this log, from
57
+ * `resourceLogPinId`
56
58
  * @param options.signer {ResourceLogSigner} this client's enrolled signing
57
59
  * key
58
60
  * @param [options.versionTime] {string} RFC3339 UTC; defaults to now
@@ -65,7 +67,7 @@ export async function latestAssertionRemovalIndex({ controller }) {
65
67
  * anything is written
66
68
  * @returns {Promise<{ sealed: boolean, verified: VerifiedResourceLog | null }>}
67
69
  */
68
- export async function sealResourceLog({ store, controller, expectedMethod, pinStore, signer, versionTime, verified: knownVerified }) {
70
+ export async function sealResourceLog({ store, controller, expectedMethod, pinStore, logId, signer, versionTime, verified: knownVerified }) {
69
71
  if (controller.versionIds.length === 0) {
70
72
  return { sealed: false, verified: null };
71
73
  }
@@ -79,7 +81,8 @@ export async function sealResourceLog({ store, controller, expectedMethod, pinSt
79
81
  store,
80
82
  controller,
81
83
  expectedMethod,
82
- pinStore
84
+ pinStore,
85
+ logId
83
86
  });
84
87
  if (current === null) {
85
88
  return { sealed: false, verified: null };
@@ -95,6 +98,7 @@ export async function sealResourceLog({ store, controller, expectedMethod, pinSt
95
98
  controller,
96
99
  expectedMethod,
97
100
  pinStore,
101
+ logId,
98
102
  signer,
99
103
  // The rebase hook doubles as the convergence check: a concurrent writer
100
104
  // whose entry already anchors past the removal sealed the log for us.
@@ -1 +1 @@
1
- {"version":3,"file":"seal.js","sourceRoot":"","sources":["../../src/resourceLog/seal.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAMhE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,EAChD,UAAU,EAGX;IACC,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,QAAQ,GAAuB,IAAI,CAAA;IACvC,KAAK,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;QACxD,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnB,YAAY,GAAG,KAAK,CAAA;oBACpB,MAAK;gBACP,CAAC;YACH,CAAC;QACH,CAAC;QACD,QAAQ,GAAG,IAAI,CAAA;IACjB,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,MAAM,EACN,WAAW,EACX,QAAQ,EAAE,aAAa,EASxB;IACC,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC1C,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,2BAA2B,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IACtE,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,IAAI,IAAI,EAAE,CAAA;IAC3D,CAAC;IACD,IAAI,QAAQ,GAAG,aAAa,IAAI,IAAI,CAAA;IACpC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC;YACpC,KAAK;YACL,UAAU;YACV,cAAc;YACd,QAAQ;SACT,CAAC,CAAA;QACF,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;QAC1C,CAAC;QACD,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IAC7B,CAAC;IACD,IACE,QAAQ,CAAC,eAAe,KAAK,IAAI;QACjC,QAAQ,CAAC,eAAe,IAAI,YAAY,EACxC,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;IACpC,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC;QACxC,KAAK;QACL,UAAU;QACV,cAAc;QACd,QAAQ;QACR,MAAM;QACN,wEAAwE;QACxE,sEAAsE;QACtE,UAAU,EAAE,OAAO,CAAC,EAAE,CACpB,OAAO,CAAC,eAAe,KAAK,IAAI;YAChC,OAAO,CAAC,eAAe,IAAI,YAAY;YACrC,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK;QACxB,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;KACtD,CAAC,CAAA;IACF,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;AAC9C,CAAC"}
1
+ {"version":3,"file":"seal.js","sourceRoot":"","sources":["../../src/resourceLog/seal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/unlock` subpath: standing unlock credentials --
6
+ * every unlock method (passphrase, passkey PRF, recovery code) as a standing
7
+ * credential in the recovery-code posture, with self-enrolling login. The
8
+ * recovery subpath's spend-on-use flows sit on top of the machinery here.
9
+ *
10
+ * - `standingClientFromUnlockSeed` / `unlockClientIdentityFromSeed` -- the
11
+ * deterministic client identity a credential derives (roster wrap target,
12
+ * binding MAC key), shared with the recovery-code derivation.
13
+ * - `generateLadderSeed` / `ladderRung` / `attributeLadderRung` -- the
14
+ * update-key ladder: latent-and-consumed did:webvh update authority from a
15
+ * random seed carried in the unlock record, current rung recovered from the
16
+ * log itself, ambiguity failing closed.
17
+ * - `wrapUnlockRecord` / `unwrapUnlockRecord` / `remintUnlockRecordBridge` --
18
+ * the unlock record codec: the credential-authenticated shell-and-core
19
+ * layout (controller, email, pointer under the binding MAC; the bridge
20
+ * delegation re-mintable; the ladder seed sealed and carried verbatim).
21
+ * - `publishUnlockKey` / `removeUnlockKey` -- the merged document posture
22
+ * edit, parameterized by credential class: a verbatim `keyAgreement` entry,
23
+ * or a `MultikeyCommitment` entry for a low-entropy-derived key.
24
+ * - `selfEnrollWebvhClient` / `selfEnrollClientCore` -- the self-enrolling
25
+ * continuation (reveal a rung, add an ordinary client, retire the rung) and
26
+ * the composed completion a fresh browser runs end to end.
27
+ *
28
+ * Kept out of the root export: this subpath pulls the webkms-client / ezcap /
29
+ * was-client dependency graph (the same isolation pattern as `./keyring`).
30
+ */
31
+ export { standingClientFromUnlockSeed, STANDING_CLIENT_SALT, unlockClientIdentityFromSeed } from './standingClient.js';
32
+ export type { StandingUnlockClient, UnlockClientIdentity } from './standingClient.js';
33
+ export { attributeLadderRung, generateLadderSeed, LADDER_MAX_SCAN, LADDER_SEED_BYTES, LadderAttributionError, ladderRung, ladderRungSeed } from './ladder.js';
34
+ export type { LadderRung, LadderRungState } from './ladder.js';
35
+ export { computeUnlockBinding, remintUnlockRecordBridge, UnlockBindingError, unlockRecordBinding, unwrapUnlockRecord, wrapUnlockRecord } from './unlockRecord.js';
36
+ export type { SealedRecordMember, SignedUnlockRecord, UnlockRecordContents, UnlockRecordProofState } from './unlockRecord.js';
37
+ export { publishUnlockKey, removeUnlockKey, selfEnrollWebvhClient, unlockKeyVerificationMethod, unlockKeyVmId } from './standingWebvh.js';
38
+ export type { StandingUnlockKeys, UnlockKeyAgreementPublication, UnlockLogStore } from './standingWebvh.js';
39
+ export { selfEnrollClientCore } from './selfEnroll.js';
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/unlock/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,cAAc,EACf,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE9D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,aAAa,EACd,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,cAAc,EACf,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,36 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/unlock` subpath: standing unlock credentials --
6
+ * every unlock method (passphrase, passkey PRF, recovery code) as a standing
7
+ * credential in the recovery-code posture, with self-enrolling login. The
8
+ * recovery subpath's spend-on-use flows sit on top of the machinery here.
9
+ *
10
+ * - `standingClientFromUnlockSeed` / `unlockClientIdentityFromSeed` -- the
11
+ * deterministic client identity a credential derives (roster wrap target,
12
+ * binding MAC key), shared with the recovery-code derivation.
13
+ * - `generateLadderSeed` / `ladderRung` / `attributeLadderRung` -- the
14
+ * update-key ladder: latent-and-consumed did:webvh update authority from a
15
+ * random seed carried in the unlock record, current rung recovered from the
16
+ * log itself, ambiguity failing closed.
17
+ * - `wrapUnlockRecord` / `unwrapUnlockRecord` / `remintUnlockRecordBridge` --
18
+ * the unlock record codec: the credential-authenticated shell-and-core
19
+ * layout (controller, email, pointer under the binding MAC; the bridge
20
+ * delegation re-mintable; the ladder seed sealed and carried verbatim).
21
+ * - `publishUnlockKey` / `removeUnlockKey` -- the merged document posture
22
+ * edit, parameterized by credential class: a verbatim `keyAgreement` entry,
23
+ * or a `MultikeyCommitment` entry for a low-entropy-derived key.
24
+ * - `selfEnrollWebvhClient` / `selfEnrollClientCore` -- the self-enrolling
25
+ * continuation (reveal a rung, add an ordinary client, retire the rung) and
26
+ * the composed completion a fresh browser runs end to end.
27
+ *
28
+ * Kept out of the root export: this subpath pulls the webkms-client / ezcap /
29
+ * was-client dependency graph (the same isolation pattern as `./keyring`).
30
+ */
31
+ export { standingClientFromUnlockSeed, STANDING_CLIENT_SALT, unlockClientIdentityFromSeed } from './standingClient.js';
32
+ export { attributeLadderRung, generateLadderSeed, LADDER_MAX_SCAN, LADDER_SEED_BYTES, LadderAttributionError, ladderRung, ladderRungSeed } from './ladder.js';
33
+ export { computeUnlockBinding, remintUnlockRecordBridge, UnlockBindingError, unlockRecordBinding, unwrapUnlockRecord, wrapUnlockRecord } from './unlockRecord.js';
34
+ export { publishUnlockKey, removeUnlockKey, selfEnrollWebvhClient, unlockKeyVerificationMethod, unlockKeyVmId } from './standingWebvh.js';
35
+ export { selfEnrollClientCore } from './selfEnroll.js';
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/unlock/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,qBAAqB,CAAA;AAM5B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,cAAc,EACf,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAQ1B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,aAAa,EACd,MAAM,oBAAoB,CAAA;AAO3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The byte length of a ladder seed: 32 random bytes, minted at bind time and
3
+ * carried only inside the unlock record's sealed ladder member.
4
+ */
5
+ export declare const LADDER_SEED_BYTES = 32;
6
+ /**
7
+ * How many rungs {@link attributeLadderRung} derives before concluding the
8
+ * log commits none of them. Generous: one rung is consumed per
9
+ * self-enrollment, so a real ladder's standing commitment sits at the number
10
+ * of self-enrollments the credential has ever performed.
11
+ */
12
+ export declare const LADDER_MAX_SCAN = 128;
13
+ /**
14
+ * Thrown when the published log's standing parameters match no derivable rung
15
+ * -- the credential's posture was revoked (or never published), the ladder
16
+ * seed does not belong to this account, or the scan bound was exceeded -- or
17
+ * when they match more than one rung in the same role, which no legitimate
18
+ * history produces. Self-enrollment refuses loudly rather than guessing.
19
+ */
20
+ export declare class LadderAttributionError extends Error {
21
+ constructor(message: string);
22
+ }
23
+ /**
24
+ * Generates a fresh random ladder seed.
25
+ *
26
+ * @returns {Uint8Array}
27
+ */
28
+ export declare function generateLadderSeed(): Uint8Array;
29
+ /**
30
+ * One rung of the ladder: its index, the 32-byte Ed25519 seed behind it, and
31
+ * the update key's public multibase as the log carries it.
32
+ */
33
+ export interface LadderRung {
34
+ index: number;
35
+ seed: Uint8Array;
36
+ keyMultibase: string;
37
+ }
38
+ /**
39
+ * Derives the 32-byte update-key seed of rung `index`.
40
+ *
41
+ * @param options {object}
42
+ * @param options.ladderSeed {Uint8Array}
43
+ * @param options.index {number} the rung index, from 0
44
+ * @returns {Uint8Array}
45
+ */
46
+ export declare function ladderRungSeed({ ladderSeed, index }: {
47
+ ladderSeed: Uint8Array;
48
+ index: number;
49
+ }): Uint8Array;
50
+ /**
51
+ * Derives rung `index` in full: seed and public multibase.
52
+ *
53
+ * @param options {object}
54
+ * @param options.ladderSeed {Uint8Array}
55
+ * @param options.index {number} the rung index, from 0
56
+ * @returns {Promise<LadderRung>}
57
+ */
58
+ export declare function ladderRung({ ladderSeed, index }: {
59
+ ladderSeed: Uint8Array;
60
+ index: number;
61
+ }): Promise<LadderRung>;
62
+ /**
63
+ * Where an attributed rung stands in the published log: `'committed'` (the
64
+ * steady state -- only its hash stands in `nextKeyHashes`) or `'revealed'` (a
65
+ * torn self-enrollment published the reveal entry but not the add entry, so
66
+ * the rung sits in `updateKeys` awaiting the resumed add).
67
+ */
68
+ export type LadderRungState = 'committed' | 'revealed';
69
+ /**
70
+ * Recovers the ladder's current rung from the published log's standing
71
+ * parameters -- the counter recovery that replaces any stored counter. Scans
72
+ * rungs `0..maxScan - 1`; a rung whose key stands in `updateKeys` is a torn
73
+ * self-enrollment to resume (`'revealed'`), else a rung whose hash stands in
74
+ * `nextKeyHashes` is the standing commitment (`'committed'`). Exactly one
75
+ * revealed rung, or exactly one committed rung beside it, is legitimate --
76
+ * the reveal entry keeps the spent rung's hash committed so a resumed run can
77
+ * re-state it, which is why a revealed rung wins over a committed one.
78
+ * Anything else fails closed with {@link LadderAttributionError}.
79
+ *
80
+ * @param options {object}
81
+ * @param options.ladderSeed {Uint8Array}
82
+ * @param options.published {object} the resolved log's standing parameters
83
+ * @param options.published.updateKeys {string[]}
84
+ * @param options.published.nextKeyHashes {string[]}
85
+ * @param [options.maxScan] {number} how many rungs to derive before giving
86
+ * up; defaults to {@link LADDER_MAX_SCAN}
87
+ * @returns {Promise<{ rung: LadderRung, state: LadderRungState }>}
88
+ */
89
+ export declare function attributeLadderRung({ ladderSeed, published, maxScan }: {
90
+ ladderSeed: Uint8Array;
91
+ published: {
92
+ updateKeys: string[];
93
+ nextKeyHashes: string[];
94
+ };
95
+ maxScan?: number;
96
+ }): Promise<{
97
+ rung: LadderRung;
98
+ state: LadderRungState;
99
+ }>;
100
+ //# sourceMappingURL=ladder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ladder.d.ts","sourceRoot":"","sources":["../../src/unlock/ladder.ts"],"names":[],"mappings":"AAiCA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAUnC;;;;;GAKG;AACH,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CAE/C;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,UAAU,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,KAAK,EACN,EAAE;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,UAAU,CAWb;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,EAC/B,UAAU,EACV,KAAK,EACN,EAAE;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,UAAU,CAAC,CAGtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,UAAU,EACV,SAAS,EACT,OAAyB,EAC1B,EAAE;IACD,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAC,CA+BxD"}
@@ -0,0 +1,144 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The update-key ladder: a standing unlock credential's latent-and-consumed
6
+ * did:webvh update authority. Rungs derive deterministically from a random
7
+ * 32-byte ladder seed carried inside the credential's unlock record -- never
8
+ * from the unlock secret itself, because a revealed rung lives verbatim in
9
+ * the world-readable `updateKeys` forever, where no hash commitment can
10
+ * protect it, so a secret-derived rung would be a standing offline grind
11
+ * oracle against the credential.
12
+ *
13
+ * Between uses only `hash(rung i)` stands in the document's `nextKeyHashes`;
14
+ * each self-enrollment is one loud reveal-and-commit entry signing with rung
15
+ * `i` and committing `hash(rung i + 1)`, after which the add entry retires
16
+ * the spent rung. The credential never holds a standing `updateKeys` member.
17
+ *
18
+ * There is no stored counter: which rung is current is recovered by
19
+ * re-deriving and scanning the published log's standing parameters
20
+ * ({@link attributeLadderRung}), and ambiguity fails closed rather than
21
+ * guessing -- the clients-listing attribution precedent. A lost
22
+ * compare-and-swap race resolves by determinism: the winner's entry commits
23
+ * `hash(rung i + 1)`, which IS the loser's retry key, so a re-run
24
+ * re-attributes and climbs one rung.
25
+ *
26
+ * The rung derivation is wire-level (both wallet apps must climb the same
27
+ * ladder from the same seed), so the salt and info labels are permanent.
28
+ */
29
+ import { deriveNextKeyHash } from '@interop/did-method-webvh';
30
+ import { hkdf } from '@noble/hashes/hkdf.js';
31
+ import { sha256 } from '@noble/hashes/sha2.js';
32
+ import { updateKeyMultibase } from '../webvh/didWebvh.js';
33
+ /**
34
+ * The byte length of a ladder seed: 32 random bytes, minted at bind time and
35
+ * carried only inside the unlock record's sealed ladder member.
36
+ */
37
+ export const LADDER_SEED_BYTES = 32;
38
+ /**
39
+ * The HKDF salt for rung derivation and the per-rung info prefix (the rung
40
+ * index in decimal follows it). Both permanent -- changing either orphans
41
+ * every bound credential's ladder.
42
+ */
43
+ const LADDER_SALT = 'freewallet/unlock/update-ladder/v1';
44
+ const LADDER_RUNG_INFO_PREFIX = 'rung/';
45
+ /**
46
+ * How many rungs {@link attributeLadderRung} derives before concluding the
47
+ * log commits none of them. Generous: one rung is consumed per
48
+ * self-enrollment, so a real ladder's standing commitment sits at the number
49
+ * of self-enrollments the credential has ever performed.
50
+ */
51
+ export const LADDER_MAX_SCAN = 128;
52
+ /**
53
+ * Thrown when the published log's standing parameters match no derivable rung
54
+ * -- the credential's posture was revoked (or never published), the ladder
55
+ * seed does not belong to this account, or the scan bound was exceeded -- or
56
+ * when they match more than one rung in the same role, which no legitimate
57
+ * history produces. Self-enrollment refuses loudly rather than guessing.
58
+ */
59
+ export class LadderAttributionError extends Error {
60
+ constructor(message) {
61
+ super(message);
62
+ this.name = 'LadderAttributionError';
63
+ }
64
+ }
65
+ /**
66
+ * Generates a fresh random ladder seed.
67
+ *
68
+ * @returns {Uint8Array}
69
+ */
70
+ export function generateLadderSeed() {
71
+ return crypto.getRandomValues(new Uint8Array(LADDER_SEED_BYTES));
72
+ }
73
+ /**
74
+ * Derives the 32-byte update-key seed of rung `index`.
75
+ *
76
+ * @param options {object}
77
+ * @param options.ladderSeed {Uint8Array}
78
+ * @param options.index {number} the rung index, from 0
79
+ * @returns {Uint8Array}
80
+ */
81
+ export function ladderRungSeed({ ladderSeed, index }) {
82
+ if (!Number.isInteger(index) || index < 0) {
83
+ throw new Error(`Invalid ladder rung index "${String(index)}".`);
84
+ }
85
+ return hkdf(sha256, ladderSeed, new TextEncoder().encode(LADDER_SALT), new TextEncoder().encode(`${LADDER_RUNG_INFO_PREFIX}${index}`), 32);
86
+ }
87
+ /**
88
+ * Derives rung `index` in full: seed and public multibase.
89
+ *
90
+ * @param options {object}
91
+ * @param options.ladderSeed {Uint8Array}
92
+ * @param options.index {number} the rung index, from 0
93
+ * @returns {Promise<LadderRung>}
94
+ */
95
+ export async function ladderRung({ ladderSeed, index }) {
96
+ const seed = ladderRungSeed({ ladderSeed, index });
97
+ return { index, seed, keyMultibase: await updateKeyMultibase({ seed }) };
98
+ }
99
+ /**
100
+ * Recovers the ladder's current rung from the published log's standing
101
+ * parameters -- the counter recovery that replaces any stored counter. Scans
102
+ * rungs `0..maxScan - 1`; a rung whose key stands in `updateKeys` is a torn
103
+ * self-enrollment to resume (`'revealed'`), else a rung whose hash stands in
104
+ * `nextKeyHashes` is the standing commitment (`'committed'`). Exactly one
105
+ * revealed rung, or exactly one committed rung beside it, is legitimate --
106
+ * the reveal entry keeps the spent rung's hash committed so a resumed run can
107
+ * re-state it, which is why a revealed rung wins over a committed one.
108
+ * Anything else fails closed with {@link LadderAttributionError}.
109
+ *
110
+ * @param options {object}
111
+ * @param options.ladderSeed {Uint8Array}
112
+ * @param options.published {object} the resolved log's standing parameters
113
+ * @param options.published.updateKeys {string[]}
114
+ * @param options.published.nextKeyHashes {string[]}
115
+ * @param [options.maxScan] {number} how many rungs to derive before giving
116
+ * up; defaults to {@link LADDER_MAX_SCAN}
117
+ * @returns {Promise<{ rung: LadderRung, state: LadderRungState }>}
118
+ */
119
+ export async function attributeLadderRung({ ladderSeed, published, maxScan = LADDER_MAX_SCAN }) {
120
+ const revealed = [];
121
+ const committed = [];
122
+ for (let index = 0; index < maxScan; index++) {
123
+ const rung = await ladderRung({ ladderSeed, index });
124
+ if (published.updateKeys.includes(rung.keyMultibase)) {
125
+ revealed.push(rung);
126
+ }
127
+ else if (published.nextKeyHashes.includes(await deriveNextKeyHash(rung.keyMultibase))) {
128
+ committed.push(rung);
129
+ }
130
+ }
131
+ if (revealed.length > 1 || committed.length > 1) {
132
+ throw new LadderAttributionError('The published log commits more than one rung of this ladder in the ' +
133
+ 'same role; refusing to self-enroll on an ambiguous attribution.');
134
+ }
135
+ if (revealed.length === 1) {
136
+ return { rung: revealed[0], state: 'revealed' };
137
+ }
138
+ if (committed.length === 1) {
139
+ return { rung: committed[0], state: 'committed' };
140
+ }
141
+ throw new LadderAttributionError('The published log commits no rung of this ladder; the credential has ' +
142
+ 'been revoked, was never published, or does not belong to this account.');
143
+ }
144
+ //# sourceMappingURL=ladder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ladder.js","sourceRoot":"","sources":["../../src/unlock/ladder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The self-enrollment completion core: what a fresh browser runs once its
6
+ * typed credential has located the account, proven the unlock record genuine,
7
+ * and handed over the bridge delegation and the ladder seed. One call turns
8
+ * the credential's latent authority into an ordinary enrolled client, with no
9
+ * second party involved:
10
+ *
11
+ * 1. Mint the new client's whole key set locally (client seed, did:webvh
12
+ * update-key seeds). Nothing is durable before the ceremony succeeds.
13
+ * 2. Write the self-enrolling continuation through the delegated `did.jsonl`
14
+ * bridge ({@link selfEnrollWebvhClient}): the reveal-and-commit entry
15
+ * signed by the attributed ladder rung, then the add entry that publishes
16
+ * the new client and retires the rung. Loud by construction -- the
17
+ * world-readable, hash-chained log extends before a single byte can be
18
+ * read.
19
+ * 3. Verify the account log locally and perform the first roster read,
20
+ * signed with the just-published `<did:webvh>#<multibase>` key and
21
+ * unwrapping the user key from the CREDENTIAL's standing wrap (escrowed
22
+ * into every epoch at bind time, kept alive by rotation fan-out).
23
+ * 4. Escrow the new client into the roster as its own recipient
24
+ * (`addUserKeyRosterRecipient`, epochs unwrapped with the credential's
25
+ * key-agreement key), so later logins on this browser read the roster the
26
+ * ordinary enrolled way.
27
+ *
28
+ * Persisting the key set under the app's own unlock layer is the caller's
29
+ * job, exactly as with the enrollment ceremony's completion: this module
30
+ * hands back the key set, the user key, and the roster epoch to pin, and
31
+ * stops there. Every stage is idempotent, so a torn run converges by
32
+ * re-running with the same credential (step 2 resumes from the standing
33
+ * commitments; a re-run after completion mints a fresh client, which is the
34
+ * ordinary next self-enrollment).
35
+ */
36
+ import type { IKeyAgreementKey } from '@interop/data-integrity-core';
37
+ import type { UserKey } from '../keys/userKey.js';
38
+ import type { AccountPointer } from '../keyring/record.js';
39
+ import { type ResourceLogPinStore } from '../resourceLog/index.js';
40
+ import type { ClientWebvhUpdateKeys } from '../webvh/didWebvh.js';
41
+ import type { UnlockLogStore } from './standingWebvh.js';
42
+ /**
43
+ * Runs the whole self-enrollment described in the module doc. The caller has
44
+ * already unwrapped the credential's unlock record (so it holds the
45
+ * credential-authenticated pointer, the bridge delegation behind `logStore`,
46
+ * and the ladder seed) and derived the credential's client identity (so it
47
+ * holds the key-agreement key with its secret half).
48
+ *
49
+ * @param options {object}
50
+ * @param options.pointer {AccountPointer} the credential-authenticated
51
+ * account pointer; must name a did:webvh
52
+ * @param options.ladderSeed {Uint8Array} the credential's update-key ladder
53
+ * seed, from its unlock record
54
+ * @param options.credentialKeyAgreementKey {IKeyAgreementKey} the
55
+ * credential's own key-agreement key (secret half included) -- its roster
56
+ * entry, which the user key is unwrapped from and every epoch re-wrapped
57
+ * with
58
+ * @param options.logStore {UnlockLogStore} the public log read plus the
59
+ * delegated `did.jsonl` PUT, built by the app around the record's bridge
60
+ * delegation
61
+ * @param [options.accountLogPinStore] {ResourceLogPinStore} this client's
62
+ * chain-head pin for the account log. A fresh browser normally has none
63
+ * (this is its first contact), which is exactly the pin's
64
+ * trust-on-first-use establishment
65
+ * @returns {Promise<object>} the new client's key set (for the caller to
66
+ * persist under its unlock layer), its did:key, the account DID, the user
67
+ * key, and the roster epoch to pin
68
+ */
69
+ export declare function selfEnrollClientCore({ pointer, ladderSeed, credentialKeyAgreementKey, logStore, accountLogPinStore }: {
70
+ pointer: AccountPointer;
71
+ ladderSeed: Uint8Array;
72
+ credentialKeyAgreementKey: IKeyAgreementKey;
73
+ logStore: UnlockLogStore;
74
+ accountLogPinStore?: ResourceLogPinStore;
75
+ }): Promise<{
76
+ clientSeed: Uint8Array;
77
+ webvhUpdateKeys: ClientWebvhUpdateKeys;
78
+ clientDid: string;
79
+ did: string;
80
+ userKey: UserKey;
81
+ latestEpochId: string;
82
+ }>;
83
+ //# sourceMappingURL=selfEnroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selfEnroll.d.ts","sourceRoot":"","sources":["../../src/unlock/selfEnroll.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AASpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAA;AAKhC,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,sBAAsB,CAAA;AAQ7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,OAAO,EACP,UAAU,EACV,yBAAyB,EACzB,QAAQ,EACR,kBAAkB,EACnB,EAAE;IACD,OAAO,EAAE,cAAc,CAAA;IACvB,UAAU,EAAE,UAAU,CAAA;IACtB,yBAAyB,EAAE,gBAAgB,CAAA;IAC3C,QAAQ,EAAE,cAAc,CAAA;IACxB,kBAAkB,CAAC,EAAE,mBAAmB,CAAA;CACzC,GAAG,OAAO,CAAC;IACV,UAAU,EAAE,UAAU,CAAA;IACtB,eAAe,EAAE,qBAAqB,CAAA;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAC,CAqGD"}