@interop/wallet-core 0.66.0 → 0.68.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 (257) hide show
  1. package/README.md +12 -8
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +6 -10
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +34 -56
  5. package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
  6. package/dist/clientAnnex/establish.d.ts +46 -29
  7. package/dist/clientAnnex/establish.d.ts.map +1 -1
  8. package/dist/clientAnnex/establish.js +111 -86
  9. package/dist/clientAnnex/establish.js.map +1 -1
  10. package/dist/clientAnnex/forget.d.ts +7 -16
  11. package/dist/clientAnnex/forget.d.ts.map +1 -1
  12. package/dist/clientAnnex/forget.js +13 -24
  13. package/dist/clientAnnex/forget.js.map +1 -1
  14. package/dist/clientAnnex/forgetLast.d.ts +33 -129
  15. package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
  16. package/dist/clientAnnex/forgetLast.js +43 -182
  17. package/dist/clientAnnex/forgetLast.js.map +1 -1
  18. package/dist/clientAnnex/gc.d.ts +26 -12
  19. package/dist/clientAnnex/gc.d.ts.map +1 -1
  20. package/dist/clientAnnex/gc.js +60 -57
  21. package/dist/clientAnnex/gc.js.map +1 -1
  22. package/dist/clientAnnex/heal.d.ts +75 -18
  23. package/dist/clientAnnex/heal.d.ts.map +1 -1
  24. package/dist/clientAnnex/heal.js +79 -147
  25. package/dist/clientAnnex/heal.js.map +1 -1
  26. package/dist/clientAnnex/index.d.ts +8 -8
  27. package/dist/clientAnnex/index.d.ts.map +1 -1
  28. package/dist/clientAnnex/index.js +5 -5
  29. package/dist/clientAnnex/index.js.map +1 -1
  30. package/dist/clientAnnex/ladder.d.ts +51 -4
  31. package/dist/clientAnnex/ladder.d.ts.map +1 -1
  32. package/dist/clientAnnex/ladder.js +283 -47
  33. package/dist/clientAnnex/ladder.js.map +1 -1
  34. package/dist/clientAnnex/ladderAnchored.d.ts +62 -73
  35. package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
  36. package/dist/clientAnnex/ladderAnchored.js +103 -117
  37. package/dist/clientAnnex/ladderAnchored.js.map +1 -1
  38. package/dist/clientAnnex/log.d.ts +123 -125
  39. package/dist/clientAnnex/log.d.ts.map +1 -1
  40. package/dist/clientAnnex/log.js +174 -233
  41. package/dist/clientAnnex/log.js.map +1 -1
  42. package/dist/clientAnnex/mend.d.ts +0 -4
  43. package/dist/clientAnnex/mend.d.ts.map +1 -1
  44. package/dist/clientAnnex/mend.js +50 -51
  45. package/dist/clientAnnex/mend.js.map +1 -1
  46. package/dist/clientAnnex/recoveryLadderAnchored.d.ts +25 -13
  47. package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
  48. package/dist/clientAnnex/recoveryLadderAnchored.js +80 -303
  49. package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
  50. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +13 -5
  51. package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
  52. package/dist/clientAnnex/rosterDeliveredEpochs.js +18 -9
  53. package/dist/clientAnnex/rosterDeliveredEpochs.js.map +1 -1
  54. package/dist/clientAnnex/selfEnroll.d.ts +6 -10
  55. package/dist/clientAnnex/selfEnroll.d.ts.map +1 -1
  56. package/dist/clientAnnex/selfEnroll.js +13 -18
  57. package/dist/clientAnnex/selfEnroll.js.map +1 -1
  58. package/dist/clientAnnex/zcap.d.ts +19 -0
  59. package/dist/clientAnnex/zcap.d.ts.map +1 -1
  60. package/dist/clientAnnex/zcap.js +80 -12
  61. package/dist/clientAnnex/zcap.js.map +1 -1
  62. package/dist/clients/index.d.ts +3 -2
  63. package/dist/clients/index.d.ts.map +1 -1
  64. package/dist/clients/index.js +3 -2
  65. package/dist/clients/index.js.map +1 -1
  66. package/dist/clients/listing.d.ts.map +1 -1
  67. package/dist/clients/listing.js +33 -15
  68. package/dist/clients/listing.js.map +1 -1
  69. package/dist/clients/policy.d.ts +18 -0
  70. package/dist/clients/policy.d.ts.map +1 -1
  71. package/dist/clients/policy.js +22 -8
  72. package/dist/clients/policy.js.map +1 -1
  73. package/dist/clients/revocation.d.ts +18 -30
  74. package/dist/clients/revocation.d.ts.map +1 -1
  75. package/dist/clients/revocation.js +12 -27
  76. package/dist/clients/revocation.js.map +1 -1
  77. package/dist/clients/rosterPolicy.d.ts +6 -1
  78. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  79. package/dist/clients/rosterPolicy.js +27 -30
  80. package/dist/clients/rosterPolicy.js.map +1 -1
  81. package/dist/descriptors/errors.d.ts +6 -5
  82. package/dist/descriptors/errors.d.ts.map +1 -1
  83. package/dist/descriptors/errors.js +6 -5
  84. package/dist/descriptors/errors.js.map +1 -1
  85. package/dist/descriptors/index.d.ts +7 -3
  86. package/dist/descriptors/index.d.ts.map +1 -1
  87. package/dist/descriptors/index.js +7 -3
  88. package/dist/descriptors/index.js.map +1 -1
  89. package/dist/descriptors/logSource.d.ts +28 -6
  90. package/dist/descriptors/logSource.d.ts.map +1 -1
  91. package/dist/descriptors/logSource.js +33 -7
  92. package/dist/descriptors/logSource.js.map +1 -1
  93. package/dist/enrollment/enrollment.d.ts.map +1 -1
  94. package/dist/enrollment/enrollment.js +3 -7
  95. package/dist/enrollment/enrollment.js.map +1 -1
  96. package/dist/genesis/accountGenesis.d.ts +11 -16
  97. package/dist/genesis/accountGenesis.d.ts.map +1 -1
  98. package/dist/genesis/accountGenesis.js +43 -47
  99. package/dist/genesis/accountGenesis.js.map +1 -1
  100. package/dist/genesis/kmsAuthentication.d.ts +50 -0
  101. package/dist/genesis/kmsAuthentication.d.ts.map +1 -0
  102. package/dist/genesis/kmsAuthentication.js +49 -0
  103. package/dist/genesis/kmsAuthentication.js.map +1 -0
  104. package/dist/keyring/kdf.d.ts +16 -20
  105. package/dist/keyring/kdf.d.ts.map +1 -1
  106. package/dist/keyring/kdf.js +2 -2
  107. package/dist/keyring/kdf.js.map +1 -1
  108. package/dist/keyring/unlockSpace.d.ts +8 -30
  109. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  110. package/dist/keyring/unlockSpace.js +8 -31
  111. package/dist/keyring/unlockSpace.js.map +1 -1
  112. package/dist/keys/clientKeyRecord.d.ts +2 -1
  113. package/dist/keys/clientKeyRecord.d.ts.map +1 -1
  114. package/dist/keys/clientKeyRecord.js +28 -11
  115. package/dist/keys/clientKeyRecord.js.map +1 -1
  116. package/dist/keys/index.d.ts +6 -2
  117. package/dist/keys/index.d.ts.map +1 -1
  118. package/dist/keys/index.js +5 -1
  119. package/dist/keys/index.js.map +1 -1
  120. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  121. package/dist/keys/rosterLogStore.js +14 -5
  122. package/dist/keys/rosterLogStore.js.map +1 -1
  123. package/dist/keys/spaceEpochs.d.ts +92 -3
  124. package/dist/keys/spaceEpochs.d.ts.map +1 -1
  125. package/dist/keys/spaceEpochs.js +110 -4
  126. package/dist/keys/spaceEpochs.js.map +1 -1
  127. package/dist/keys/userKeyRoster.d.ts +30 -3
  128. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  129. package/dist/keys/userKeyRoster.js +90 -15
  130. package/dist/keys/userKeyRoster.js.map +1 -1
  131. package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
  132. package/dist/keys/userKeyRosterCascade.js +5 -1
  133. package/dist/keys/userKeyRosterCascade.js.map +1 -1
  134. package/dist/recovery/continuation.d.ts +250 -0
  135. package/dist/recovery/continuation.d.ts.map +1 -0
  136. package/dist/recovery/continuation.js +467 -0
  137. package/dist/recovery/continuation.js.map +1 -0
  138. package/dist/recovery/index.d.ts +12 -8
  139. package/dist/recovery/index.d.ts.map +1 -1
  140. package/dist/recovery/index.js +11 -7
  141. package/dist/recovery/index.js.map +1 -1
  142. package/dist/recovery/recoveryDelegation.d.ts +23 -126
  143. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  144. package/dist/recovery/recoveryDelegation.js +1 -266
  145. package/dist/recovery/recoveryDelegation.js.map +1 -1
  146. package/dist/recovery/recoveryWebvh.d.ts +52 -107
  147. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  148. package/dist/recovery/recoveryWebvh.js +54 -403
  149. package/dist/recovery/recoveryWebvh.js.map +1 -1
  150. package/dist/request/classify.d.ts +3 -14
  151. package/dist/request/classify.d.ts.map +1 -1
  152. package/dist/request/classify.js +19 -40
  153. package/dist/request/classify.js.map +1 -1
  154. package/dist/request/index.d.ts +1 -0
  155. package/dist/request/index.d.ts.map +1 -1
  156. package/dist/request/index.js +1 -0
  157. package/dist/request/index.js.map +1 -1
  158. package/dist/request/onboarding.d.ts.map +1 -1
  159. package/dist/request/onboarding.js +19 -27
  160. package/dist/request/onboarding.js.map +1 -1
  161. package/dist/request/parse.d.ts +5 -3
  162. package/dist/request/parse.d.ts.map +1 -1
  163. package/dist/request/parse.js +7 -6
  164. package/dist/request/parse.js.map +1 -1
  165. package/dist/request/processRequest.d.ts.map +1 -1
  166. package/dist/request/processRequest.js +2 -1
  167. package/dist/request/processRequest.js.map +1 -1
  168. package/dist/request/queryPredicates.d.ts +98 -0
  169. package/dist/request/queryPredicates.d.ts.map +1 -0
  170. package/dist/request/queryPredicates.js +107 -0
  171. package/dist/request/queryPredicates.js.map +1 -0
  172. package/dist/resourceLog/document.d.ts +39 -0
  173. package/dist/resourceLog/document.d.ts.map +1 -1
  174. package/dist/resourceLog/document.js +41 -0
  175. package/dist/resourceLog/document.js.map +1 -1
  176. package/dist/resourceLog/index.d.ts +2 -2
  177. package/dist/resourceLog/index.js +2 -2
  178. package/dist/resourceLog/ladderRungs.d.ts.map +1 -1
  179. package/dist/resourceLog/ladderRungs.js +3 -2
  180. package/dist/resourceLog/ladderRungs.js.map +1 -1
  181. package/dist/sync/contactsConflict.d.ts.map +1 -1
  182. package/dist/sync/contactsConflict.js +8 -2
  183. package/dist/sync/contactsConflict.js.map +1 -1
  184. package/dist/sync/engine.d.ts +38 -23
  185. package/dist/sync/engine.d.ts.map +1 -1
  186. package/dist/sync/engine.js +36 -5
  187. package/dist/sync/engine.js.map +1 -1
  188. package/dist/sync/index.d.ts +9 -12
  189. package/dist/sync/index.d.ts.map +1 -1
  190. package/dist/sync/index.js +8 -11
  191. package/dist/sync/index.js.map +1 -1
  192. package/dist/sync/push.d.ts.map +1 -1
  193. package/dist/sync/push.js +1 -2
  194. package/dist/sync/push.js.map +1 -1
  195. package/dist/sync/remint.d.ts +0 -31
  196. package/dist/sync/remint.d.ts.map +1 -1
  197. package/dist/sync/remint.js +32 -1
  198. package/dist/sync/remint.js.map +1 -1
  199. package/dist/sync/types.d.ts +4 -41
  200. package/dist/sync/types.d.ts.map +1 -1
  201. package/dist/sync/types.js +4 -47
  202. package/dist/sync/types.js.map +1 -1
  203. package/dist/unlock/index.d.ts +1 -1
  204. package/dist/unlock/index.d.ts.map +1 -1
  205. package/dist/unlock/index.js +1 -1
  206. package/dist/unlock/index.js.map +1 -1
  207. package/dist/unlock/retire.d.ts +16 -64
  208. package/dist/unlock/retire.d.ts.map +1 -1
  209. package/dist/unlock/retire.js +7 -86
  210. package/dist/unlock/retire.js.map +1 -1
  211. package/dist/unlock/standingWebvh.d.ts +27 -61
  212. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  213. package/dist/unlock/standingWebvh.js +40 -92
  214. package/dist/unlock/standingWebvh.js.map +1 -1
  215. package/dist/unlock/unlockRecord.d.ts.map +1 -1
  216. package/dist/unlock/unlockRecord.js +69 -44
  217. package/dist/unlock/unlockRecord.js.map +1 -1
  218. package/dist/webvh/accountEntry.d.ts +68 -19
  219. package/dist/webvh/accountEntry.d.ts.map +1 -1
  220. package/dist/webvh/accountEntry.js +117 -37
  221. package/dist/webvh/accountEntry.js.map +1 -1
  222. package/dist/webvh/delegatedLogStore.d.ts +24 -13
  223. package/dist/webvh/delegatedLogStore.d.ts.map +1 -1
  224. package/dist/webvh/delegatedLogStore.js +40 -11
  225. package/dist/webvh/delegatedLogStore.js.map +1 -1
  226. package/dist/webvh/didWebvh.d.ts +91 -86
  227. package/dist/webvh/didWebvh.d.ts.map +1 -1
  228. package/dist/webvh/didWebvh.js +117 -142
  229. package/dist/webvh/didWebvh.js.map +1 -1
  230. package/dist/webvh/enrollClient.d.ts +2 -8
  231. package/dist/webvh/enrollClient.d.ts.map +1 -1
  232. package/dist/webvh/enrollClient.js +22 -31
  233. package/dist/webvh/enrollClient.js.map +1 -1
  234. package/dist/webvh/index.d.ts +12 -8
  235. package/dist/webvh/index.d.ts.map +1 -1
  236. package/dist/webvh/index.js +10 -7
  237. package/dist/webvh/index.js.map +1 -1
  238. package/dist/webvh/listClients.d.ts.map +1 -1
  239. package/dist/webvh/listClients.js +102 -65
  240. package/dist/webvh/listClients.js.map +1 -1
  241. package/dist/webvh/mergeMethods.d.ts +84 -0
  242. package/dist/webvh/mergeMethods.d.ts.map +1 -0
  243. package/dist/webvh/mergeMethods.js +46 -0
  244. package/dist/webvh/mergeMethods.js.map +1 -0
  245. package/dist/webvh/revokeClient.d.ts +15 -11
  246. package/dist/webvh/revokeClient.d.ts.map +1 -1
  247. package/dist/webvh/revokeClient.js +130 -57
  248. package/dist/webvh/revokeClient.js.map +1 -1
  249. package/dist/webvh/verifyLog.d.ts +45 -4
  250. package/dist/webvh/verifyLog.d.ts.map +1 -1
  251. package/dist/webvh/verifyLog.js +62 -21
  252. package/dist/webvh/verifyLog.js.map +1 -1
  253. package/dist/webvh/wasIdStore.d.ts +16 -3
  254. package/dist/webvh/wasIdStore.d.ts.map +1 -1
  255. package/dist/webvh/wasIdStore.js +18 -3
  256. package/dist/webvh/wasIdStore.js.map +1 -1
  257. package/package.json +11 -11
@@ -51,12 +51,10 @@
51
51
  import { createDID, deriveNextKeyHash, updateDID } from '@interop/did-method-webvh';
52
52
  import { rootCapabilityId, spaceItems, spacePath, toUrl } from '@interop/was-client/paths';
53
53
  import { base64urlnopad } from '@scure/base';
54
- import { DID_LOG_RESOURCE } from '../space/collections.js';
55
54
  import { plaintextCollection } from '../space/plaintextCollection.js';
56
- import { resourceLogPinId } from '@interop/vh-resource-log';
57
- import { clientAnnexRung } from './ladder.js';
58
- import { assertCarryOverCommitments, assertPublishedLogDid, concludeWithPublishedLog, currentLogParameters, didWebvhControllerTemplate, MULTIKEY_VM_TYPE, pinOfLog, putLogResource, readPublishedLogOrThrow, updateKeySigner, WebvhLogConflictError, withLogConflictRetry } from '../webvh/didWebvh.js';
59
- import { signAccountEntry } from '../webvh/accountEntry.js';
55
+ import { clientAnnexRung, ladderRung } from './ladder.js';
56
+ import { assertCarryOverCommitments, assertPublishedLogDid, concludeWithPublishedLog, currentLogParameters, didWebvhControllerTemplate, MULTIKEY_VM_TYPE, putLogResource, readPublishedLog, readPublishedLogOrThrow, updateKeySigner, withLogConflictRetry, withThreadedHeadOnce } from '../webvh/didWebvh.js';
57
+ import { accountEntryHead, signAccountEntry } from '../webvh/accountEntry.js';
60
58
  import { relationIds } from '../resourceLog/document.js';
61
59
  import { STANDING_ZCAP_TTL_MS, standingZcapStale } from '../webvh/standingZcap.js';
62
60
  import { wasWebvhLogStore } from '../webvh/wasIdStore.js';
@@ -121,27 +119,6 @@ export function assertGenerationId(generationId) {
121
119
  'base64url characters).');
122
120
  }
123
121
  }
124
- /**
125
- * The pin-slot key for one annex generation's log -- host-free like every
126
- * pin-slot key, keyed by the auxiliary Space id and the generation id.
127
- * A transient session keeps this slot in an in-memory pin store (a
128
- * client-local pin is the wrong lifetime for a disposable log, and a
129
- * transient session must not create client-local state on a read); an
130
- * enrolled client's store clears annex slots when the generation is
131
- * collected.
132
- *
133
- * @param options {object}
134
- * @param options.spaceId {string} the auxiliary annex Space's id
135
- * @param options.generationId {string} the generation collection's name
136
- * @returns {string}
137
- */
138
- export function clientAnnexLogPinId({ spaceId, generationId }) {
139
- return resourceLogPinId({
140
- spaceId,
141
- collectionId: generationId,
142
- resourceId: DID_LOG_RESOURCE
143
- });
144
- }
145
122
  /**
146
123
  * The WAS-backed store an annex generation's ceremonies read and publish
147
124
  * through with controller-tier signing (an enrolled client). A transient
@@ -153,17 +130,20 @@ export function clientAnnexLogPinId({ spaceId, generationId }) {
153
130
  * @param options.was {WasClient}
154
131
  * @param options.spaceId {string} the auxiliary annex Space's id
155
132
  * @param options.generationId {string} the generation collection's name
133
+ * @param options.pinStore {ResourceLogPinStore} this client's chain-head
134
+ * pins; the store derives each log's slot
156
135
  * @param [options.capability] {IZcap} an invocation capability every request
157
136
  * rides (the sibling delegation, where the caller is not an enrolled
158
137
  * invoker); absent, requests invoke the root capability
159
138
  * @returns {WebvhLogResourceStore}
160
139
  */
161
- export function clientAnnexLogStore({ was, spaceId, generationId, capability }) {
140
+ export function clientAnnexLogStore({ was, spaceId, generationId, pinStore, capability }) {
162
141
  assertGenerationId(generationId);
163
142
  return wasWebvhLogStore({
164
143
  was,
165
144
  spaceId,
166
145
  collectionId: generationId,
146
+ pinStore,
167
147
  ...(capability !== undefined ? { capability } : {})
168
148
  });
169
149
  }
@@ -315,6 +295,8 @@ export async function ensureClientAnnexSpace({ was, spaceId, controller }) {
315
295
  * @param options.nextKeyHashes {string[]} every standing credential's
316
296
  * rung-0 hash, the minting credential's included
317
297
  * @param options.signer {Signer} the minting credential's rung-0 signer
298
+ * @param options.pinStore {ResourceLogPinStore} this client's chain-head
299
+ * pins; the store derives each log's slot
318
300
  * @returns {Promise<PublishedWebvhLog & { generationId: string;
319
301
  * spaceDescription?: SpaceDescription }>} the published head of the
320
302
  * genesis log, which a stage building the generation's next entry can
@@ -324,7 +306,7 @@ export async function ensureClientAnnexSpace({ was, spaceId, controller }) {
324
306
  * controller afterwards need not re-read it. Always present here, since
325
307
  * this minter always runs the ensure.
326
308
  */
327
- export async function mintClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, updateKeyPublicKeyMultibase, nextKeyHashes, signer }) {
309
+ export async function mintClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, updateKeyPublicKeyMultibase, nextKeyHashes, signer, pinStore }) {
328
310
  const spaceDescription = await ensureClientAnnexSpace({
329
311
  was,
330
312
  spaceId,
@@ -338,7 +320,8 @@ export async function mintClientAnnexGeneration({ was, wasServerUrl, spaceId, co
338
320
  generationId,
339
321
  updateKeyPublicKeyMultibase,
340
322
  nextKeyHashes,
341
- signer
323
+ signer,
324
+ pinStore
342
325
  });
343
326
  return { ...published, spaceDescription };
344
327
  }
@@ -355,6 +338,8 @@ export async function mintClientAnnexGeneration({ was, wasServerUrl, spaceId, co
355
338
  * @param options.updateKeyPublicKeyMultibase {string}
356
339
  * @param options.nextKeyHashes {string[]}
357
340
  * @param options.signer {Signer}
341
+ * @param options.pinStore {ResourceLogPinStore} this client's chain-head
342
+ * pins; the store derives each log's slot
358
343
  * @param [options.capability] {IZcap} an invocation capability the
359
344
  * collection create and the genesis publish ride (a delegated minter)
360
345
  * @returns {Promise<PublishedWebvhLog & { generationId: string }>} the
@@ -367,7 +352,7 @@ export async function mintClientAnnexGeneration({ was, wasServerUrl, spaceId, co
367
352
  * for itself rather than degrade its compare-and-swap to an unconditional
368
353
  * write.
369
354
  */
370
- async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generationId, updateKeyPublicKeyMultibase, nextKeyHashes, signer, capability }) {
355
+ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generationId, updateKeyPublicKeyMultibase, nextKeyHashes, signer, pinStore, capability }) {
371
356
  // The generation collection must exist before its first resource PUT; a
372
357
  // fresh random generation id means this is always a create, so the truthful
373
358
  // `current: null` skips was-client's pre-merge describe of a Collection
@@ -393,6 +378,7 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
393
378
  was,
394
379
  spaceId,
395
380
  generationId,
381
+ pinStore,
396
382
  ...(capability !== undefined ? { capability } : {})
397
383
  }),
398
384
  log: created.log,
@@ -427,6 +413,8 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
427
413
  * only when the Space does not exist yet
428
414
  * @param options.ladderSeed {Uint8Array} the minting credential's ladder
429
415
  * seed, from its unlock record
416
+ * @param options.pinStore {ResourceLogPinStore} this client's chain-head
417
+ * pins; the store derives each log's slot
430
418
  * @param [options.extraNextKeyHashes] {string[]} the OTHER standing
431
419
  * credentials' rung-0 hashes for this generation id, when the account has
432
420
  * more
@@ -446,7 +434,7 @@ async function publishClientAnnexGenesis({ was, wasServerUrl, spaceId, generatio
446
434
  * controller afterwards need not re-read it. Present exactly when the
447
435
  * ensure ran, so absent under a supplied `capability`.
448
436
  */
449
- export async function mintCredentialClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, extraNextKeyHashes = [], capability }) {
437
+ export async function mintCredentialClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, pinStore, extraNextKeyHashes = [], capability }) {
450
438
  const spaceDescription = capability === undefined
451
439
  ? await ensureClientAnnexSpace({ was, spaceId, controller })
452
440
  : undefined;
@@ -463,6 +451,7 @@ export async function mintCredentialClientAnnexGeneration({ was, wasServerUrl, s
463
451
  ...extraNextKeyHashes
464
452
  ],
465
453
  signer: await updateKeySigner({ seed: rung.seed }),
454
+ pinStore,
466
455
  ...(capability !== undefined ? { capability } : {})
467
456
  });
468
457
  return {
@@ -624,8 +613,8 @@ export const DELEGATED_CLIENTS_DELEGATION_ACTIONS = ['GET', 'PUT'];
624
613
  /**
625
614
  * The sibling delegation's lifetime: the house standing-zcap value (one
626
615
  * year; see `standingZcap.ts`). It rots on exactly the account bridge's axis
627
- * -- same signer, same current-key-set rule, same renewal window -- so the
628
- * re-mint pass that refreshes the bridge refreshes it too.
616
+ * -- same signer, same current-key-set rule, same renewal window -- so
617
+ * whatever refreshes the bridge refreshes it too.
629
618
  */
630
619
  export const DELEGATED_CLIENTS_DELEGATION_TTL_MS = STANDING_ZCAP_TTL_MS;
631
620
  /**
@@ -676,15 +665,14 @@ export async function mintDelegatedClientsDelegation({ zcapClient, wasServerUrl,
676
665
  }));
677
666
  }
678
667
  /**
679
- * Builds the annex-side sibling-delegation minter the enrolled-client record
680
- * re-mint orchestrator (`recovery/remintRecoveryDelegations`) takes as an
681
- * injected closure -- the boundary keeping that base orchestrator free of
682
- * annex imports. The returned closure reads the auxiliary annex Space id off
683
- * the verified document's delegated-clients service entry (the annex DID
684
- * string embeds it) and mints a fresh {@link mintDelegatedClientsDelegation}
685
- * to the named controller; it resolves `undefined` while the document points
686
- * at no generation, which the orchestrator reads as "carry the old sealed
687
- * member verbatim".
668
+ * Builds the annex-side sibling-delegation minter a record re-bind takes as
669
+ * an injected closure -- the boundary keeping a caller outside this subpath
670
+ * free of annex imports. The returned closure reads the auxiliary annex Space
671
+ * id off the verified document's delegated-clients service entry (the annex
672
+ * DID string embeds it) and mints a fresh
673
+ * {@link mintDelegatedClientsDelegation} to the named controller; it resolves
674
+ * `undefined` while the document points at no generation, which a caller
675
+ * reads as "carry the old sealed member verbatim".
688
676
  * @param options {object}
689
677
  * @param options.doc {object} the locally verified account document
690
678
  * @param options.zcapClient {ZcapClient} the acting client's promoted
@@ -963,7 +951,7 @@ export async function revokeTreatingAlreadyRevokedAsSuccess({ revoke, delegation
963
951
  await revoke(delegation);
964
952
  }
965
953
  catch (err) {
966
- if (err.name === 'ValidationError') {
954
+ if (err?.name === 'ValidationError') {
967
955
  return;
968
956
  }
969
957
  throw err;
@@ -1086,25 +1074,51 @@ async function admitActingRung({ ladderSeed, generationId, updateKeys, nextKeyHa
1086
1074
  /**
1087
1075
  * Reads and resolves the published annex log through the narrow seam, or
1088
1076
  * throws when the generation's `did.jsonl` is missing (an unpointed or
1089
- * deleted generation -- nothing to enroll into).
1077
+ * deleted generation -- nothing to enroll into). The read runs under the
1078
+ * store's own chain-head pin.
1090
1079
  *
1091
1080
  * @param options {object}
1092
1081
  * @param options.store {ClientAnnexWriteStore}
1093
1082
  * @param [options.expectedDid] {string}
1094
- * @param [options.pinStore] {ResourceLogPinStore}
1095
- * @param [options.logId] {string}
1096
1083
  * @returns {Promise<PublishedWebvhLog>}
1097
1084
  */
1098
- async function readClientAnnexLogOrThrow({ store, expectedDid, pinStore, logId }) {
1085
+ async function readClientAnnexLogOrThrow({ store, expectedDid }) {
1099
1086
  return readPublishedLogOrThrow({
1100
1087
  idStore: store,
1101
1088
  ...(expectedDid !== undefined ? { expectedDid } : {}),
1102
- ...(pinStore !== undefined ? { pinStore } : {}),
1103
- ...(logId !== undefined ? { logId } : {}),
1104
1089
  missingMessage: 'client annex: did.jsonl is missing; the generation was never minted ' +
1105
1090
  'or has been collected.'
1106
1091
  });
1107
1092
  }
1093
+ /**
1094
+ * Reads and resolves a generation's published annex log, or resolves
1095
+ * `undefined` when its `did.jsonl` does not exist -- even under a held pin.
1096
+ *
1097
+ * The pinned read refuses an absent log under a held pin as a `rollback`,
1098
+ * which is right for the account log: a full truncation is never "not yet
1099
+ * provisioned". A generation is different. It is deleted by design (the GC
1100
+ * collect, an abandoned annex Space), and every arm that tells a dead or
1101
+ * absent generation from a live one -- the readiness ensure's re-point, the
1102
+ * last-client transition's `log-unreadable` escape, the GC's orphan collect
1103
+ * -- is gated on that absence. A client that read the generation earlier and
1104
+ * still holds its pin would otherwise be refused exactly where it must mend,
1105
+ * with nothing that ever drops the slot. So the read runs in the pinned
1106
+ * read's absence-tolerant mode: a genuinely absent log is absence (the pin
1107
+ * left standing), and a log that is served and falls behind the pin stays
1108
+ * refused, so a served prefix is never mistaken for a missing log.
1109
+ *
1110
+ * @param options {object}
1111
+ * @param options.store {ClientAnnexWriteStore}
1112
+ * @param [options.expectedDid] {string}
1113
+ * @returns {Promise<PublishedWebvhLog | undefined>}
1114
+ */
1115
+ export async function readClientAnnexLogOrAbsent({ store, expectedDid }) {
1116
+ return readPublishedLog({
1117
+ idStore: store,
1118
+ absentUnderPin: 'absent',
1119
+ ...(expectedDid !== undefined ? { expectedDid } : {})
1120
+ });
1121
+ }
1108
1122
  /**
1109
1123
  * TRANSIENT ENROLLMENT: publishes one per-visit verification method into a
1110
1124
  * annex generation's log -- one atomic entry, signed by the writing
@@ -1162,11 +1176,8 @@ async function readClientAnnexLogOrThrow({ store, expectedDid, pinStore, logId }
1162
1176
  * by genesis (a genesis-embedded signed zcap can never verify -- its
1163
1177
  * `controller` embeds the SCID the genesis hash derives from)
1164
1178
  * @param [options.expectedDid] {string} the annex DID the log must
1165
- * resolve to, from the account document's pointer
1166
- * @param [options.pinStore] {ResourceLogPinStore} chain-head pins (a
1167
- * transient session passes an in-memory store)
1168
- * @param [options.logId] {string} the generation's pin-slot key, from
1169
- * {@link clientAnnexLogPinId}; required whenever a `pinStore` is supplied
1179
+ * resolve to, from the account document's pointer. The read and the publish
1180
+ * run under the store's own chain-head pin
1170
1181
  * @param [options.published] {PublishedWebvhLog} a head the caller already
1171
1182
  * read and verified under this same pin slot, so the enrollment builds its
1172
1183
  * entry on it instead of spending a second round trip on the same log (the
@@ -1178,23 +1189,10 @@ async function readClientAnnexLogOrThrow({ store, expectedDid, pinStore, logId }
1178
1189
  * @returns {Promise<{ did: string, doc: DIDDoc, log: DIDLog }>}
1179
1190
  */
1180
1191
  export async function enrollClientAnnexTransientClient({ published: threadedHead, ...rest }) {
1181
- if (threadedHead !== undefined) {
1182
- try {
1183
- return await enrollClientAnnexTransientClientOnce({
1184
- ...rest,
1185
- published: threadedHead
1186
- });
1187
- }
1188
- catch (err) {
1189
- // A lost compare-and-swap on the threaded head says only that the head
1190
- // is stale; the retry below re-reads under the pin with its whole
1191
- // budget. Every other failure is the caller's.
1192
- if (!(err instanceof WebvhLogConflictError)) {
1193
- throw err;
1194
- }
1195
- }
1196
- }
1197
- return withLogConflictRetry(() => enrollClientAnnexTransientClientOnce(rest));
1192
+ return withThreadedHeadOnce({
1193
+ published: threadedHead,
1194
+ attempt: published => enrollClientAnnexTransientClientOnce({ ...rest, published })
1195
+ });
1198
1196
  }
1199
1197
  /**
1200
1198
  * One attempt of {@link enrollClientAnnexTransientClient}, re-invoked by the
@@ -1204,7 +1202,7 @@ export async function enrollClientAnnexTransientClient({ published: threadedHead
1204
1202
  * @param options {object} see {@link enrollClientAnnexTransientClient}
1205
1203
  * @returns {Promise<{ did: string, doc: DIDDoc, log: DIDLog }>}
1206
1204
  */
1207
- async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generationId, transientKeyMultibase, services, mintGenerationDelegation: mintDelegation, expectedDid, pinStore, logId, published: alreadyRead }) {
1205
+ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generationId, transientKeyMultibase, services, mintGenerationDelegation: mintDelegation, expectedDid, published: alreadyRead }) {
1208
1206
  assertGenerationId(generationId);
1209
1207
  const published = alreadyRead !== undefined
1210
1208
  ? assertPublishedLogDid({
@@ -1213,9 +1211,7 @@ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generat
1213
1211
  })
1214
1212
  : await readClientAnnexLogOrThrow({
1215
1213
  store,
1216
- ...(expectedDid !== undefined ? { expectedDid } : {}),
1217
- ...(pinStore !== undefined ? { pinStore } : {}),
1218
- ...(logId !== undefined ? { logId } : {})
1214
+ ...(expectedDid !== undefined ? { expectedDid } : {})
1219
1215
  });
1220
1216
  const { did, doc } = published;
1221
1217
  const vmId = `${did}#${transientKeyMultibase}`;
@@ -1288,24 +1284,28 @@ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generat
1288
1284
  ...(services !== undefined ? { services } : {})
1289
1285
  });
1290
1286
  // The log only -- an annex has no did:web projection -- conditional on
1291
- // the read this entry was built on.
1287
+ // the read this entry was built on. The publish advances the store's
1288
+ // chain-head pin to what it just wrote, so a host serving the pre-entry log
1289
+ // straight afterwards is refused as a rollback on the next read.
1292
1290
  await putLogResource({ store, log: updated.log, ifMatch: published.etag });
1293
- // Advance the pin to what this entry just published, so a host serving the
1294
- // pre-entry log straight afterwards is refused as a rollback on the next
1295
- // read (equal-to-pin would otherwise be accepted, and a later stage built on
1296
- // the stale head would miss this entry).
1297
- if (pinStore && logId !== undefined) {
1298
- await pinStore.write({ logId, pin: pinOfLog(updated.log) });
1299
- }
1300
1291
  return { did: updated.did, doc: updated.doc, log: updated.log };
1301
1292
  }
1302
1293
  /**
1303
1294
  * Points the account document's delegated-clients service entry at a
1304
1295
  * annex DID -- the first install after a generation's genesis, and the GC
1305
- * swap's re-point alike. One ordinary document-update entry, signed by an
1306
- * enrolled client's active update key; the annex log always
1307
- * publishes FIRST (see {@link mintClientAnnexGeneration}), so a tear leaves an
1308
- * unpointed, authorization-inert generation, never a dangling pointer.
1296
+ * swap's re-point alike. One ordinary document-update entry on either signer
1297
+ * arm; the annex log always publishes FIRST (see
1298
+ * {@link mintClientAnnexGeneration}), so a tear leaves an unpointed,
1299
+ * authorization-inert generation, never a dangling pointer.
1300
+ *
1301
+ * On the ladder arm the entry is the pointer move a credential-only caller
1302
+ * makes (the transient readiness pass, the establishment's stage 3): the
1303
+ * seam attributes the ladder's current rung per attempt, the rung reveals
1304
+ * itself in the entry it signs, and when it stood only committed the entry
1305
+ * also commits the next rung's hash, so one entry does what a reveal entry
1306
+ * followed by a client-signed pointer entry used to. A lost race re-runs the
1307
+ * attribution from the winner's head, which is what climbs to the winner's
1308
+ * committed rung (retry-up-the-ladder).
1309
1309
  *
1310
1310
  * An existing delegated-clients entry is re-pointed in place, its fragment id
1311
1311
  * preserved verbatim (the id is non-semantic and stable); absent one, a fresh
@@ -1313,34 +1313,34 @@ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generat
1313
1313
  * service entry, the verification methods, and the relationship arrays are
1314
1314
  * preserved untouched. Idempotent: a document already pointing at the DID is
1315
1315
  * a no-op on the log (and, unless `logOnly`, it republishes `did.json` from
1316
- * the resolved log, which the enrolled-client caller has the authority to
1316
+ * the resolved log, which a controller-invoking caller has the authority to
1317
1317
  * do).
1318
1318
  *
1319
1319
  * @param options {object}
1320
1320
  * @param options.idStore {WebvhIdStore} the ACCOUNT log's store; with
1321
1321
  * `logOnly`, only its log read and `did.jsonl` PUT are used, so the narrow
1322
1322
  * delegated seam satisfies it
1323
- * @param options.signer {AccountLogSigner} who signs the pointer entry:
1324
- * this enrolled client's update-key seeds -- or the ladder-rung idiom on a
1325
- * ladder-anchored account (`{ updateSeed: rung0.seed, stagedSeed:
1326
- * rung1.seed }`), as the credential-anchored genesis and the
1327
- * transient-recovery continuation pass
1323
+ * @param options.signer {AccountLogSigner} who signs the pointer entry: an
1324
+ * enrolled client's own update-key seeds (`{ kind: 'client', updateKeys }`,
1325
+ * the GC swap's re-point and an enrolled client's stage-3 fold), or a
1326
+ * standing credential's ladder seed (`{ kind: 'ladder', ladderSeed }`),
1327
+ * under which the acting rung is attributed from the head each attempt
1328
+ * builds on
1328
1329
  * @param options.clientAnnexDid {string} the generation to point at
1329
1330
  * @param [options.expectedDid] {string} the account DID the log must
1330
- * resolve to, from the account pointer
1331
- * @param [options.pinStore] {ResourceLogPinStore} this client's chain-head
1332
- * pins for the account log
1333
- * @param [options.logId] {string} the account log's pin-slot key, from
1334
- * `accountLogPinId({ spaceId })`; required whenever a `pinStore` is
1335
- * supplied
1331
+ * resolve to, from the account pointer. The read and the publish run under
1332
+ * the store's own chain-head pin
1336
1333
  * @param [options.logOnly] {boolean} publish `did.jsonl` only, never the
1337
- * `did.json` projection -- the transient-recovery continuation writing
1338
- * through the record's bridge delegation, whose narrow scope covers nothing
1339
- * but the log. The projection then lags until some caller holding an
1340
- * `id`-collection writer runs `ensureDidWebProjection` over the resolved
1341
- * log; on a client-less account that is a transient visit under its
1342
- * generation delegation. The log stays the source of truth meanwhile, and
1343
- * the server reads it rather than the projection, so the lag is a `did:web`
1334
+ * `did.json` projection. Defaults per arm, as {@link signAccountEntry}
1335
+ * does: `true` on the ladder arm, since a transient visit writes through
1336
+ * the record's bridge delegation, whose narrow scope covers nothing but the
1337
+ * log, and `false` on the client arm. The establishment's stage 3, a ladder
1338
+ * signer over a root-invoking store, passes `false` explicitly. A lagging
1339
+ * projection is republished when some caller holding an `id`-collection
1340
+ * writer runs `ensureDidWebProjection` over the resolved log; on a
1341
+ * client-less account that is a transient visit under its generation
1342
+ * delegation. The log stays the source of truth meanwhile, and the server
1343
+ * reads it rather than the projection, so the lag is a `did:web`
1344
1344
  * verifier's concern alone
1345
1345
  * @param [options.published] {PublishedWebvhLog} a head the caller already
1346
1346
  * read and verified under this same pin slot, so the pointer entry builds
@@ -1351,55 +1351,36 @@ async function enrollClientAnnexTransientClientOnce({ store, ladderSeed, generat
1351
1351
  * threaded attempt is EXTRA rather than one of the retry's three: a caller
1352
1352
  * who saved a read is left with the same conflict budget as one who did not
1353
1353
  * @returns {Promise<{ did: string, doc: DIDDoc,
1354
- * published: PublishedWebvhLog }>} `published` is the head this call
1355
- * leaves standing: the post-entry one, paired with its publish's own ETag,
1356
- * when the entry was appended; the head it stood on verbatim when the
1357
- * document already pointed at the DID
1354
+ * published: PublishedWebvhLog, rung?: LadderRung }>} `published` is the
1355
+ * head this call leaves standing: the post-entry one, paired with its
1356
+ * publish's own ETag, when the entry was appended; the head it stood on
1357
+ * verbatim when the document already pointed at the DID. `rung` stands on
1358
+ * the ladder arm alone: the rung the entry was signed with, or, when the
1359
+ * document already pointed, the ladder's currently attributed rung
1358
1360
  */
1359
1361
  export async function setDelegatedClientsPointer({ published: threadedHead, ...rest }) {
1360
- if (threadedHead !== undefined) {
1361
- try {
1362
- return await setDelegatedClientsPointerOnce({
1363
- ...rest,
1364
- published: threadedHead
1365
- });
1366
- }
1367
- catch (err) {
1368
- // A lost compare-and-swap on the threaded head says only that the head
1369
- // is stale; the retry below re-reads under the pin with its whole
1370
- // budget. Every other failure is the caller's.
1371
- if (!(err instanceof WebvhLogConflictError)) {
1372
- throw err;
1373
- }
1374
- }
1375
- }
1376
- return withLogConflictRetry(() => setDelegatedClientsPointerOnce(rest));
1362
+ return withThreadedHeadOnce({
1363
+ published: threadedHead,
1364
+ attempt: published => setDelegatedClientsPointerOnce({ ...rest, published })
1365
+ });
1377
1366
  }
1378
1367
  /**
1379
1368
  * ONE attempt of {@link setDelegatedClientsPointer}, re-invoked by that
1380
- * function's conflict retry and exported for a caller that runs its own.
1381
- * A caller whose retry loop also attributes the signing rung must use this
1382
- * form: the wrapper's inner retry would re-invoke the attempt with the SAME
1383
- * signer, and a rung a racing ceremony consumed meanwhile can never
1384
- * become authorized by re-reading, so the attempt would fail on the plain
1385
- * not-authorized refusal instead of surfacing the conflict the caller's loop
1386
- * knows how to re-attribute from.
1387
- *
1388
- * A caller that already read the head its signer was attributed
1389
- * against passes it as `published`, and the entry is built on exactly that
1390
- * head. A racing entry landing in between then loses the CAS on the PUT and
1391
- * surfaces as a {@link WebvhLogConflictError}, which is what a re-attributing
1392
- * loop retries -- rather than as the not-authorized refusal a fresh read of
1393
- * the winner's head would produce.
1369
+ * function's conflict retry and exported for a caller that runs its own
1370
+ * retry around it.
1371
+ *
1372
+ * A caller that already read the head passes it as `published`, and the
1373
+ * entry is built on exactly that head. A racing entry landing in between
1374
+ * then loses the CAS on the PUT and surfaces as a
1375
+ * {@link WebvhLogConflictError} for the retry to re-run.
1394
1376
  *
1395
1377
  * @param options {object} see {@link setDelegatedClientsPointer}, plus:
1396
1378
  * @param [options.published] {PublishedWebvhLog} the verified head to build
1397
1379
  * this entry on, when the caller has already read it under the same pin;
1398
1380
  * absent, the attempt reads the head itself
1399
- * @returns {Promise<{ did: string, doc: DIDDoc,
1400
- * published: PublishedWebvhLog }>}
1381
+ * @returns {Promise<PointerEntryOutcome>}
1401
1382
  */
1402
- export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAnnexDid, expectedDid, pinStore, logId, logOnly = false, published: alreadyRead }) {
1383
+ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAnnexDid, expectedDid, logOnly = signer.kind === 'ladder', published: alreadyRead }) {
1403
1384
  // Refuses a malformed target before anything is read or written.
1404
1385
  clientAnnexDidParts({ did: clientAnnexDid });
1405
1386
  let settled;
@@ -1408,15 +1389,13 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1408
1389
  signer,
1409
1390
  ...(alreadyRead !== undefined ? { published: alreadyRead } : {}),
1410
1391
  ...(expectedDid !== undefined ? { expectedDid } : {}),
1411
- ...(pinStore ? { pinStore } : {}),
1412
- ...(logId !== undefined ? { logId } : {}),
1413
1392
  missingMessage: 'did:webvh: did.jsonl is missing; nothing to point at a client annex.',
1414
1393
  verb: 're-pointing the delegated-clients entry',
1415
1394
  logOnly,
1416
- build: async ({ published }) => {
1395
+ build: async ({ published, rung, state }) => {
1417
1396
  const { did, doc } = published;
1418
1397
  if (delegatedClientsPointer({ doc }) === clientAnnexDid) {
1419
- if (!logOnly && signer.kind === 'client') {
1398
+ if (!logOnly) {
1420
1399
  await concludeWithPublishedLog({ idStore, published });
1421
1400
  }
1422
1401
  // The head verbatim: the projection PUT touches no log, so this
@@ -1424,7 +1403,20 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1424
1403
  settled = { did, doc, published };
1425
1404
  return undefined;
1426
1405
  }
1406
+ // A ladder rung standing only as a committed hash reveals itself
1407
+ // through the seam's reveal union; this entry commits the next rung
1408
+ // beside it, so the ladder stays prerotated past the move. An already
1409
+ // revealed rung re-states the parameters verbatim.
1410
+ const commitHashes = signer.kind === 'ladder' && state === 'committed'
1411
+ ? [
1412
+ await deriveNextKeyHash((await ladderRung({
1413
+ ladderSeed: signer.ladderSeed,
1414
+ index: rung.index + 1
1415
+ })).keyMultibase)
1416
+ ]
1417
+ : undefined;
1427
1418
  return {
1419
+ ...(commitHashes !== undefined ? { commitHashes } : {}),
1428
1420
  services: servicesPointedAtClientAnnex({
1429
1421
  doc,
1430
1422
  accountDid: did,
@@ -1433,8 +1425,9 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1433
1425
  };
1434
1426
  }
1435
1427
  });
1428
+ const ladderRungPart = outcome.rung !== undefined ? { rung: outcome.rung } : {};
1436
1429
  if (settled) {
1437
- return settled;
1430
+ return { ...settled, ...ladderRungPart };
1438
1431
  }
1439
1432
  const updated = outcome.updated;
1440
1433
  return {
@@ -1443,16 +1436,8 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1443
1436
  // The post-entry head, from what `updateDID` already resolved plus this
1444
1437
  // publish's own validator: the update-key parameters are the ones the
1445
1438
  // entry re-stated unchanged above, so nothing is re-resolved or re-read.
1446
- published: {
1447
- log: updated.log,
1448
- did: updated.did,
1449
- // Detached from the entry's own `state`, as every other producer of
1450
- // this type is, so a consumer editing the document cannot edit the log.
1451
- doc: structuredClone(updated.doc),
1452
- updateKeys: updated.meta.updateKeys,
1453
- nextKeyHashes: updated.meta.nextKeyHashes,
1454
- ...(outcome.etag !== undefined ? { etag: outcome.etag } : {})
1455
- }
1439
+ published: accountEntryHead({ outcome }),
1440
+ ...ladderRungPart
1456
1441
  };
1457
1442
  }
1458
1443
  /**
@@ -1484,9 +1469,6 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1484
1469
  * {@link enrollClientAnnexTransientClient}). The closure receives whichever
1485
1470
  * annex DID the round enrolls into, so a GC-race re-enroll mints for
1486
1471
  * the fresh generation
1487
- * @param [options.pinStore] {ResourceLogPinStore} chain-head pins for the
1488
- * generation logs (a transient session passes an in-memory store); slot
1489
- * keys are derived per generation with {@link clientAnnexLogPinId}
1490
1472
  * @param [options.maxRounds] {number} how many pointer moves to chase
1491
1473
  * before giving up (a GC pass is quarterly, so more than one mid-ceremony
1492
1474
  * move means something else is wrong)
@@ -1498,7 +1480,7 @@ export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAn
1498
1480
  * every later round does
1499
1481
  * @returns {Promise<{ clientAnnexDid: string, doc: DIDDoc, log: DIDLog }>}
1500
1482
  */
1501
- export async function enrollTransientClient({ readAccountDocument, storeForGenerationId, ladderSeed, transientKeyMultibase, mintGenerationDelegation: mintDelegation, pinStore, maxRounds = 3, published: threadedHead }) {
1483
+ export async function enrollTransientClient({ readAccountDocument, storeForGenerationId, ladderSeed, transientKeyMultibase, mintGenerationDelegation: mintDelegation, maxRounds = 3, published: threadedHead }) {
1502
1484
  let accountDoc = await readAccountDocument();
1503
1485
  for (let round = 0; round < maxRounds; round++) {
1504
1486
  const clientAnnexDid = delegatedClientsPointer({ doc: accountDoc });
@@ -1506,9 +1488,7 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
1506
1488
  throw new Error('client annex: the account document carries no delegated-clients ' +
1507
1489
  'service entry; no generation exists to enroll into.');
1508
1490
  }
1509
- const { spaceId, generationId } = clientAnnexDidParts({
1510
- did: clientAnnexDid
1511
- });
1491
+ const { generationId } = clientAnnexDidParts({ did: clientAnnexDid });
1512
1492
  // Round 0's threaded head, and only for the generation the pointer names:
1513
1493
  // a head read before a GC swap belongs to the abandoned generation and
1514
1494
  // says nothing about the one this round enrolls into.
@@ -1524,9 +1504,6 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
1524
1504
  ...(head !== undefined ? { published: head } : {}),
1525
1505
  ...(mintDelegation !== undefined
1526
1506
  ? { mintGenerationDelegation: mintDelegation }
1527
- : {}),
1528
- ...(pinStore !== undefined
1529
- ? { pinStore, logId: clientAnnexLogPinId({ spaceId, generationId }) }
1530
1507
  : {})
1531
1508
  });
1532
1509
  // The GC-race re-read: an unchanged pointer means the enrollment stands
@@ -1544,9 +1521,10 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
1544
1521
  * The fresh-generation block every separate-pointer-entry caller runs: mint
1545
1522
  * a generation in the annex Space, install its generation delegation, then
1546
1523
  * append the account document's pointer entry naming it. The pointer write is
1547
- * the injected step (`point`): the establishment signs it as a client under
1548
- * a rung the caller attributed, the transient visit moves it as the ladder
1549
- * with its reveal-and-retry form. A caller with a step that must land
1524
+ * the injected step (`point`): an enrolled client signs it under its own
1525
+ * update keys, and a credential-only caller (the establishment, the
1526
+ * transient visit) moves it as the ladder, one rung-signed entry per attempt. A
1527
+ * caller with a step that must land
1550
1528
  * between the install and the pointer entry (the establishment's bootstrap
1551
1529
  * arm, whose Space still answers to its creation controller until it flips
1552
1530
  * it to the account DID) supplies `beforePointerEntry`.
@@ -1572,25 +1550,26 @@ export async function enrollTransientClient({ readAccountDocument, storeForGener
1572
1550
  * `({ clientAnnexDid }) => Promise<IZcap>`
1573
1551
  * @param options.point {Function} `(clientAnnexDid) => Promise<T>` -- the
1574
1552
  * pointer entry, whose result rides the return verbatim
1553
+ * @param options.pinStore {ResourceLogPinStore} this client's chain-head
1554
+ * pins; the store derives each log's slot
1575
1555
  * @param [options.capability] {IZcap} the sibling delegation the annex
1576
1556
  * writes ride, for a caller holding a standing invocation authority
1577
1557
  * @param [options.beforePointerEntry] {Function}
1578
1558
  * `({ minted }) => Promise<void>` -- runs after the install and before the
1579
1559
  * pointer entry, with the mint's published head (its `spaceDescription`
1580
1560
  * included)
1581
- * @param [options.pinStore] {ResourceLogPinStore} chain-head pins; the
1582
- * generation's slot is derived here
1583
1561
  * @param [options.now] {number} epoch milliseconds, for tests
1584
1562
  * @returns {Promise<{ clientAnnexDid: string, generationDelegation: IZcap,
1585
1563
  * pointed: T }>}
1586
1564
  */
1587
- export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, mintGenerationDelegation, point, capability, beforePointerEntry, pinStore, now }) {
1565
+ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spaceId, controller, ladderSeed, mintGenerationDelegation, point, pinStore, capability, beforePointerEntry, now }) {
1588
1566
  const minted = await mintCredentialClientAnnexGeneration({
1589
1567
  was,
1590
1568
  wasServerUrl,
1591
1569
  spaceId,
1592
1570
  controller,
1593
1571
  ladderSeed,
1572
+ pinStore,
1594
1573
  ...(capability !== undefined ? { capability } : {})
1595
1574
  });
1596
1575
  const ensured = await ensureGenerationDelegationCurrent({
@@ -1598,6 +1577,7 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
1598
1577
  was,
1599
1578
  spaceId,
1600
1579
  generationId: minted.generationId,
1580
+ pinStore,
1601
1581
  ...(capability !== undefined ? { capability } : {})
1602
1582
  }),
1603
1583
  ladderSeed,
@@ -1605,15 +1585,6 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
1605
1585
  mintGenerationDelegation,
1606
1586
  expectedDid: minted.did,
1607
1587
  ...(minted.etag !== undefined ? { published: minted } : {}),
1608
- ...(pinStore !== undefined
1609
- ? {
1610
- pinStore,
1611
- logId: clientAnnexLogPinId({
1612
- spaceId,
1613
- generationId: minted.generationId
1614
- })
1615
- }
1616
- : {}),
1617
1588
  ...(now !== undefined ? { now } : {})
1618
1589
  });
1619
1590
  if (beforePointerEntry !== undefined) {
@@ -1672,11 +1643,8 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
1672
1643
  * `({ clientAnnexDid }) => Promise<IZcap>` -- mints the replacement
1673
1644
  * delegation (ladder-signed in a transient session)
1674
1645
  * @param [options.expectedDid] {string} the annex DID the log must
1675
- * resolve to, from the account document's pointer
1676
- * @param [options.pinStore] {ResourceLogPinStore} chain-head pins (a
1677
- * transient session passes an in-memory store)
1678
- * @param [options.logId] {string} the generation's pin-slot key, from
1679
- * {@link clientAnnexLogPinId}; required whenever a `pinStore` is supplied
1646
+ * resolve to, from the account document's pointer. The read and the publish
1647
+ * run under the store's own chain-head pin
1680
1648
  * @param [options.accountDoc] {PublishedKeyDocument} the locally VERIFIED
1681
1649
  * account document; supplied, a standing delegation whose proof key it no
1682
1650
  * longer lists is replaced (the signer-death axis above)
@@ -1707,23 +1675,10 @@ export async function mintPointedClientAnnexGeneration({ was, wasServerUrl, spac
1707
1675
  * wanting one reads for itself
1708
1676
  */
1709
1677
  export async function ensureGenerationDelegationCurrent({ published: threadedHead, ...rest }) {
1710
- if (threadedHead !== undefined) {
1711
- try {
1712
- return await ensureGenerationDelegationCurrentOnce({
1713
- ...rest,
1714
- published: threadedHead
1715
- });
1716
- }
1717
- catch (err) {
1718
- // A lost compare-and-swap on the threaded head says only that the head
1719
- // is stale; the retry below re-reads under the pin with its whole
1720
- // budget. Every other failure is the caller's.
1721
- if (!(err instanceof WebvhLogConflictError)) {
1722
- throw err;
1723
- }
1724
- }
1725
- }
1726
- return withLogConflictRetry(() => ensureGenerationDelegationCurrentOnce(rest));
1678
+ return withThreadedHeadOnce({
1679
+ published: threadedHead,
1680
+ attempt: published => ensureGenerationDelegationCurrentOnce({ ...rest, published })
1681
+ });
1727
1682
  }
1728
1683
  /**
1729
1684
  * One attempt of {@link ensureGenerationDelegationCurrent}, re-invoked by the
@@ -1734,7 +1689,7 @@ export async function ensureGenerationDelegationCurrent({ published: threadedHea
1734
1689
  * @returns {Promise<{ delegation: IZcap, renewed: boolean,
1735
1690
  * published?: PublishedWebvhLog }>}
1736
1691
  */
1737
- async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, generationId, mintGenerationDelegation: mintDelegation, expectedDid, pinStore, logId, accountDoc, retiringKeyMultibases = [], now, published: alreadyRead }) {
1692
+ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, generationId, mintGenerationDelegation: mintDelegation, expectedDid, accountDoc, retiringKeyMultibases = [], now, published: alreadyRead }) {
1738
1693
  assertGenerationId(generationId);
1739
1694
  const published = alreadyRead !== undefined
1740
1695
  ? assertPublishedLogDid({
@@ -1743,9 +1698,7 @@ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, genera
1743
1698
  })
1744
1699
  : await readClientAnnexLogOrThrow({
1745
1700
  store,
1746
- ...(expectedDid !== undefined ? { expectedDid } : {}),
1747
- ...(pinStore !== undefined ? { pinStore } : {}),
1748
- ...(logId !== undefined ? { logId } : {})
1701
+ ...(expectedDid !== undefined ? { expectedDid } : {})
1749
1702
  });
1750
1703
  const { did, doc } = published;
1751
1704
  const standing = embeddedGenerationDelegation({ doc });
@@ -1788,14 +1741,10 @@ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, genera
1788
1741
  delegation: fresh
1789
1742
  })
1790
1743
  });
1744
+ // The publish advances the store's chain-head pin to what it just wrote, so
1745
+ // a host serving the pre-entry log straight afterwards is refused as a
1746
+ // rollback on the next read.
1791
1747
  await putLogResource({ store, log: updated.log, ifMatch: published.etag });
1792
- // Advance the pin to what this entry just published, so a host serving the
1793
- // pre-entry log straight afterwards is refused as a rollback on the next
1794
- // read (equal-to-pin would otherwise be accepted, and a later stage built on
1795
- // the stale head would miss this entry).
1796
- if (pinStore && logId !== undefined) {
1797
- await pinStore.write({ logId, pin: pinOfLog(updated.log) });
1798
- }
1799
1748
  return { delegation: fresh, renewed: true };
1800
1749
  }
1801
1750
  /**
@@ -1826,10 +1775,8 @@ async function ensureGenerationDelegationCurrentOnce({ store, ladderSeed, genera
1826
1775
  * ladder seed, whose committed rung 0 signs the strike entry
1827
1776
  * @param options.generationId {string} the generation collection's name
1828
1777
  * @param [options.expectedDid] {string} the annex DID the log must
1829
- * resolve to, from the account document's pointer
1830
- * @param [options.pinStore] {ResourceLogPinStore}
1831
- * @param [options.logId] {string} the generation's pin-slot key, from
1832
- * {@link clientAnnexLogPinId}; required whenever a `pinStore` is supplied
1778
+ * resolve to, from the account document's pointer. The read and the publish
1779
+ * run under the store's own chain-head pin
1833
1780
  * @returns {Promise<{ struck: boolean }>}
1834
1781
  */
1835
1782
  export async function retireClientAnnexRung(options) {
@@ -1843,13 +1790,11 @@ export async function retireClientAnnexRung(options) {
1843
1790
  * @param options {object} see {@link retireClientAnnexRung}
1844
1791
  * @returns {Promise<{ struck: boolean }>}
1845
1792
  */
1846
- async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadderSeed, generationId, expectedDid, pinStore, logId }) {
1793
+ async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadderSeed, generationId, expectedDid }) {
1847
1794
  assertGenerationId(generationId);
1848
1795
  const published = await readClientAnnexLogOrThrow({
1849
1796
  store,
1850
- ...(expectedDid !== undefined ? { expectedDid } : {}),
1851
- ...(pinStore !== undefined ? { pinStore } : {}),
1852
- ...(logId !== undefined ? { logId } : {})
1797
+ ...(expectedDid !== undefined ? { expectedDid } : {})
1853
1798
  });
1854
1799
  const retired = await clientAnnexRung({
1855
1800
  ladderSeed: retiredLadderSeed,
@@ -1918,10 +1863,8 @@ async function retireClientAnnexRungOnce({ store, retiredLadderSeed, actingLadde
1918
1863
  * login credential's ladder seed, whose committed rung 0 signs the entry
1919
1864
  * @param options.generationId {string} the generation collection's name
1920
1865
  * @param [options.expectedDid] {string} the annex DID the log must
1921
- * resolve to, from the account document's pointer
1922
- * @param [options.pinStore] {ResourceLogPinStore}
1923
- * @param [options.logId] {string} the generation's pin-slot key, from
1924
- * {@link clientAnnexLogPinId}; required whenever a `pinStore` is supplied
1866
+ * resolve to, from the account document's pointer. The read and the publish
1867
+ * run under the store's own chain-head pin
1925
1868
  * @returns {Promise<{ committed: boolean }>}
1926
1869
  */
1927
1870
  export async function commitClientAnnexRung(options) {
@@ -1935,13 +1878,11 @@ export async function commitClientAnnexRung(options) {
1935
1878
  * @param options {object} see {@link commitClientAnnexRung}
1936
1879
  * @returns {Promise<{ committed: boolean }>}
1937
1880
  */
1938
- async function commitClientAnnexRungOnce({ store, boundLadderSeed, actingLadderSeed, generationId, expectedDid, pinStore, logId }) {
1881
+ async function commitClientAnnexRungOnce({ store, boundLadderSeed, actingLadderSeed, generationId, expectedDid }) {
1939
1882
  assertGenerationId(generationId);
1940
1883
  const published = await readClientAnnexLogOrThrow({
1941
1884
  store,
1942
- ...(expectedDid !== undefined ? { expectedDid } : {}),
1943
- ...(pinStore !== undefined ? { pinStore } : {}),
1944
- ...(logId !== undefined ? { logId } : {})
1885
+ ...(expectedDid !== undefined ? { expectedDid } : {})
1945
1886
  });
1946
1887
  const bound = await clientAnnexRung({
1947
1888
  ladderSeed: boundLadderSeed,