@interop/wallet-core 0.62.0 → 0.66.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 (321) hide show
  1. package/README.md +41 -16
  2. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +46 -26
  3. package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
  4. package/dist/clientAnnex/credentialAnchoredGenesis.js +91 -39
  5. package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
  6. package/dist/clientAnnex/establish.d.ts +119 -35
  7. package/dist/clientAnnex/establish.d.ts.map +1 -1
  8. package/dist/clientAnnex/establish.js +227 -160
  9. package/dist/clientAnnex/establish.js.map +1 -1
  10. package/dist/clientAnnex/forget.d.ts +18 -8
  11. package/dist/clientAnnex/forget.d.ts.map +1 -1
  12. package/dist/clientAnnex/forget.js +37 -64
  13. package/dist/clientAnnex/forget.js.map +1 -1
  14. package/dist/clientAnnex/forgetLast.d.ts +85 -38
  15. package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
  16. package/dist/clientAnnex/forgetLast.js +155 -98
  17. package/dist/clientAnnex/forgetLast.js.map +1 -1
  18. package/dist/clientAnnex/gc.d.ts +3 -2
  19. package/dist/clientAnnex/gc.d.ts.map +1 -1
  20. package/dist/clientAnnex/gc.js +16 -7
  21. package/dist/clientAnnex/gc.js.map +1 -1
  22. package/dist/clientAnnex/heal.d.ts +65 -14
  23. package/dist/clientAnnex/heal.d.ts.map +1 -1
  24. package/dist/clientAnnex/heal.js +397 -298
  25. package/dist/clientAnnex/heal.js.map +1 -1
  26. package/dist/clientAnnex/index.d.ts +23 -7
  27. package/dist/clientAnnex/index.d.ts.map +1 -1
  28. package/dist/clientAnnex/index.js +26 -7
  29. package/dist/clientAnnex/index.js.map +1 -1
  30. package/dist/clientAnnex/ladder.d.ts +58 -0
  31. package/dist/clientAnnex/ladder.d.ts.map +1 -1
  32. package/dist/clientAnnex/ladder.js +249 -41
  33. package/dist/clientAnnex/ladder.js.map +1 -1
  34. package/dist/clientAnnex/ladderAnchored.d.ts +148 -22
  35. package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
  36. package/dist/clientAnnex/ladderAnchored.js +391 -346
  37. package/dist/clientAnnex/ladderAnchored.js.map +1 -1
  38. package/dist/clientAnnex/log.d.ts +237 -53
  39. package/dist/clientAnnex/log.d.ts.map +1 -1
  40. package/dist/clientAnnex/log.js +533 -198
  41. package/dist/clientAnnex/log.js.map +1 -1
  42. package/dist/clientAnnex/mend.d.ts +12 -6
  43. package/dist/clientAnnex/mend.d.ts.map +1 -1
  44. package/dist/clientAnnex/mend.js +44 -72
  45. package/dist/clientAnnex/mend.js.map +1 -1
  46. package/dist/clientAnnex/recoveryLadderAnchored.d.ts +6 -4
  47. package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
  48. package/dist/clientAnnex/recoveryLadderAnchored.js +56 -35
  49. package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
  50. package/dist/clientAnnex/spaceCapability.d.ts +123 -0
  51. package/dist/clientAnnex/spaceCapability.d.ts.map +1 -0
  52. package/dist/clientAnnex/spaceCapability.js +152 -0
  53. package/dist/clientAnnex/spaceCapability.js.map +1 -0
  54. package/dist/clientAnnex/stages.d.ts +63 -0
  55. package/dist/clientAnnex/stages.d.ts.map +1 -0
  56. package/dist/clientAnnex/stages.js +64 -0
  57. package/dist/clientAnnex/stages.js.map +1 -0
  58. package/dist/clientAnnex/zcap.d.ts +1 -1
  59. package/dist/clientAnnex/zcap.d.ts.map +1 -1
  60. package/dist/clientAnnex/zcap.js +42 -35
  61. package/dist/clientAnnex/zcap.js.map +1 -1
  62. package/dist/clients/policy.d.ts +15 -1
  63. package/dist/clients/policy.d.ts.map +1 -1
  64. package/dist/clients/policy.js +12 -6
  65. package/dist/clients/policy.js.map +1 -1
  66. package/dist/clients/revocation.d.ts +18 -10
  67. package/dist/clients/revocation.d.ts.map +1 -1
  68. package/dist/clients/revocation.js +13 -5
  69. package/dist/clients/revocation.js.map +1 -1
  70. package/dist/clients/rosterPolicy.d.ts +10 -2
  71. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  72. package/dist/clients/rosterPolicy.js +41 -24
  73. package/dist/clients/rosterPolicy.js.map +1 -1
  74. package/dist/descriptors/acquire.d.ts.map +1 -1
  75. package/dist/descriptors/acquire.js +6 -23
  76. package/dist/descriptors/acquire.js.map +1 -1
  77. package/dist/descriptors/cipher.d.ts.map +1 -1
  78. package/dist/descriptors/cipher.js +5 -0
  79. package/dist/descriptors/cipher.js.map +1 -1
  80. package/dist/descriptors/errors.d.ts +43 -0
  81. package/dist/descriptors/errors.d.ts.map +1 -0
  82. package/dist/descriptors/errors.js +45 -0
  83. package/dist/descriptors/errors.js.map +1 -0
  84. package/dist/descriptors/index.d.ts +5 -0
  85. package/dist/descriptors/index.d.ts.map +1 -1
  86. package/dist/descriptors/index.js +5 -0
  87. package/dist/descriptors/index.js.map +1 -1
  88. package/dist/enrollment/enrollment.d.ts +37 -10
  89. package/dist/enrollment/enrollment.d.ts.map +1 -1
  90. package/dist/enrollment/enrollment.js +52 -15
  91. package/dist/enrollment/enrollment.js.map +1 -1
  92. package/dist/genesis/accountGenesis.d.ts +42 -11
  93. package/dist/genesis/accountGenesis.d.ts.map +1 -1
  94. package/dist/genesis/accountGenesis.js +80 -22
  95. package/dist/genesis/accountGenesis.js.map +1 -1
  96. package/dist/genesis/index.d.ts +3 -1
  97. package/dist/genesis/index.d.ts.map +1 -1
  98. package/dist/genesis/index.js +3 -1
  99. package/dist/genesis/index.js.map +1 -1
  100. package/dist/identity/agents.d.ts +17 -1
  101. package/dist/identity/agents.d.ts.map +1 -1
  102. package/dist/identity/agents.js +23 -7
  103. package/dist/identity/agents.js.map +1 -1
  104. package/dist/identity/index.d.ts +3 -1
  105. package/dist/identity/index.d.ts.map +1 -1
  106. package/dist/identity/index.js +3 -1
  107. package/dist/identity/index.js.map +1 -1
  108. package/dist/index.d.ts +6 -3
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +6 -3
  111. package/dist/index.js.map +1 -1
  112. package/dist/keyring/index.d.ts +2 -1
  113. package/dist/keyring/index.d.ts.map +1 -1
  114. package/dist/keyring/index.js +2 -1
  115. package/dist/keyring/index.js.map +1 -1
  116. package/dist/keyring/record.d.ts.map +1 -1
  117. package/dist/keyring/record.js +3 -6
  118. package/dist/keyring/record.js.map +1 -1
  119. package/dist/keyring/unlockSpace.d.ts +14 -5
  120. package/dist/keyring/unlockSpace.d.ts.map +1 -1
  121. package/dist/keyring/unlockSpace.js +31 -36
  122. package/dist/keyring/unlockSpace.js.map +1 -1
  123. package/dist/keys/index.d.ts +22 -8
  124. package/dist/keys/index.d.ts.map +1 -1
  125. package/dist/keys/index.js +20 -6
  126. package/dist/keys/index.js.map +1 -1
  127. package/dist/keys/rosterLogStore.d.ts +15 -12
  128. package/dist/keys/rosterLogStore.d.ts.map +1 -1
  129. package/dist/keys/rosterLogStore.js +21 -16
  130. package/dist/keys/rosterLogStore.js.map +1 -1
  131. package/dist/keys/rosterStore.d.ts +3 -6
  132. package/dist/keys/rosterStore.d.ts.map +1 -1
  133. package/dist/keys/rosterStore.js +10 -9
  134. package/dist/keys/rosterStore.js.map +1 -1
  135. package/dist/keys/spaceEpochs.d.ts.map +1 -1
  136. package/dist/keys/spaceEpochs.js +2 -3
  137. package/dist/keys/spaceEpochs.js.map +1 -1
  138. package/dist/keys/userKeyCascade.d.ts +8 -5
  139. package/dist/keys/userKeyCascade.d.ts.map +1 -1
  140. package/dist/keys/userKeyCascade.js +7 -6
  141. package/dist/keys/userKeyCascade.js.map +1 -1
  142. package/dist/keys/userKeyRoster.d.ts +95 -8
  143. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  144. package/dist/keys/userKeyRoster.js +278 -35
  145. package/dist/keys/userKeyRoster.js.map +1 -1
  146. package/dist/keys/userKeyRosterCascade.d.ts +117 -16
  147. package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
  148. package/dist/keys/userKeyRosterCascade.js +184 -43
  149. package/dist/keys/userKeyRosterCascade.js.map +1 -1
  150. package/dist/keys/wasLabelsStore.d.ts +9 -2
  151. package/dist/keys/wasLabelsStore.d.ts.map +1 -1
  152. package/dist/keys/wasLabelsStore.js +14 -6
  153. package/dist/keys/wasLabelsStore.js.map +1 -1
  154. package/dist/log.d.ts +7 -2
  155. package/dist/log.d.ts.map +1 -1
  156. package/dist/log.js +6 -1
  157. package/dist/log.js.map +1 -1
  158. package/dist/recovery/index.d.ts +13 -9
  159. package/dist/recovery/index.d.ts.map +1 -1
  160. package/dist/recovery/index.js +12 -8
  161. package/dist/recovery/index.js.map +1 -1
  162. package/dist/recovery/recoveryCode.d.ts +27 -7
  163. package/dist/recovery/recoveryCode.d.ts.map +1 -1
  164. package/dist/recovery/recoveryCode.js +18 -6
  165. package/dist/recovery/recoveryCode.js.map +1 -1
  166. package/dist/recovery/recoveryDelegation.d.ts +23 -0
  167. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  168. package/dist/recovery/recoveryDelegation.js +66 -46
  169. package/dist/recovery/recoveryDelegation.js.map +1 -1
  170. package/dist/recovery/recoveryWebvh.d.ts +75 -63
  171. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  172. package/dist/recovery/recoveryWebvh.js +127 -116
  173. package/dist/recovery/recoveryWebvh.js.map +1 -1
  174. package/dist/request/appKey.d.ts +35 -1
  175. package/dist/request/appKey.d.ts.map +1 -1
  176. package/dist/request/appKey.js +29 -10
  177. package/dist/request/appKey.js.map +1 -1
  178. package/dist/request/classify.d.ts +32 -8
  179. package/dist/request/classify.d.ts.map +1 -1
  180. package/dist/request/classify.js +39 -14
  181. package/dist/request/classify.js.map +1 -1
  182. package/dist/request/ephemeralExchange.d.ts +1 -6
  183. package/dist/request/ephemeralExchange.d.ts.map +1 -1
  184. package/dist/request/ephemeralExchange.js.map +1 -1
  185. package/dist/request/onboarding.d.ts.map +1 -1
  186. package/dist/request/onboarding.js +2 -2
  187. package/dist/request/onboarding.js.map +1 -1
  188. package/dist/request/parse.d.ts.map +1 -1
  189. package/dist/request/parse.js +2 -3
  190. package/dist/request/parse.js.map +1 -1
  191. package/dist/resourceLog/controller.d.ts +34 -12
  192. package/dist/resourceLog/controller.d.ts.map +1 -1
  193. package/dist/resourceLog/controller.js +79 -86
  194. package/dist/resourceLog/controller.js.map +1 -1
  195. package/dist/resourceLog/document.d.ts +182 -0
  196. package/dist/resourceLog/document.d.ts.map +1 -0
  197. package/dist/resourceLog/document.js +159 -0
  198. package/dist/resourceLog/document.js.map +1 -0
  199. package/dist/resourceLog/errors.d.ts +47 -8
  200. package/dist/resourceLog/errors.d.ts.map +1 -1
  201. package/dist/resourceLog/errors.js +54 -8
  202. package/dist/resourceLog/errors.js.map +1 -1
  203. package/dist/resourceLog/index.d.ts +7 -3
  204. package/dist/resourceLog/index.d.ts.map +1 -1
  205. package/dist/resourceLog/index.js +7 -3
  206. package/dist/resourceLog/index.js.map +1 -1
  207. package/dist/resourceLog/ladderRungs.d.ts +35 -0
  208. package/dist/resourceLog/ladderRungs.d.ts.map +1 -0
  209. package/dist/resourceLog/ladderRungs.js +352 -0
  210. package/dist/resourceLog/ladderRungs.js.map +1 -0
  211. package/dist/resourceLog/license.d.ts +42 -17
  212. package/dist/resourceLog/license.d.ts.map +1 -1
  213. package/dist/resourceLog/license.js +38 -24
  214. package/dist/resourceLog/license.js.map +1 -1
  215. package/dist/space/activity.d.ts +15 -15
  216. package/dist/space/activity.d.ts.map +1 -1
  217. package/dist/space/activity.js +15 -15
  218. package/dist/space/activity.js.map +1 -1
  219. package/dist/space/collections.d.ts +11 -0
  220. package/dist/space/collections.d.ts.map +1 -1
  221. package/dist/space/collections.js +13 -0
  222. package/dist/space/collections.js.map +1 -1
  223. package/dist/space/deleteSpace.d.ts +28 -0
  224. package/dist/space/deleteSpace.d.ts.map +1 -0
  225. package/dist/space/deleteSpace.js +44 -0
  226. package/dist/space/deleteSpace.js.map +1 -0
  227. package/dist/space/errors.d.ts.map +1 -1
  228. package/dist/space/errors.js +0 -1
  229. package/dist/space/errors.js.map +1 -1
  230. package/dist/space/index.d.ts +6 -0
  231. package/dist/space/index.d.ts.map +1 -1
  232. package/dist/space/index.js +6 -0
  233. package/dist/space/index.js.map +1 -1
  234. package/dist/space/plaintextCollection.d.ts +43 -0
  235. package/dist/space/plaintextCollection.d.ts.map +1 -0
  236. package/dist/space/plaintextCollection.js +17 -0
  237. package/dist/space/plaintextCollection.js.map +1 -0
  238. package/dist/stages.d.ts +23 -0
  239. package/dist/stages.d.ts.map +1 -0
  240. package/dist/stages.js +23 -0
  241. package/dist/stages.js.map +1 -0
  242. package/dist/sync/index.d.ts +7 -0
  243. package/dist/sync/index.d.ts.map +1 -1
  244. package/dist/sync/index.js +7 -0
  245. package/dist/sync/index.js.map +1 -1
  246. package/dist/sync/push.js +4 -4
  247. package/dist/sync/push.js.map +1 -1
  248. package/dist/sync/remint.js +2 -2
  249. package/dist/sync/remint.js.map +1 -1
  250. package/dist/sync/types.d.ts +41 -1
  251. package/dist/sync/types.d.ts.map +1 -1
  252. package/dist/sync/types.js +47 -1
  253. package/dist/sync/types.js.map +1 -1
  254. package/dist/unlock/index.d.ts +5 -1
  255. package/dist/unlock/index.d.ts.map +1 -1
  256. package/dist/unlock/index.js +5 -1
  257. package/dist/unlock/index.js.map +1 -1
  258. package/dist/unlock/retire.d.ts +35 -7
  259. package/dist/unlock/retire.d.ts.map +1 -1
  260. package/dist/unlock/retire.js +52 -14
  261. package/dist/unlock/retire.js.map +1 -1
  262. package/dist/unlock/standingClient.d.ts.map +1 -1
  263. package/dist/unlock/standingClient.js +5 -1
  264. package/dist/unlock/standingClient.js.map +1 -1
  265. package/dist/unlock/standingWebvh.d.ts +217 -35
  266. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  267. package/dist/unlock/standingWebvh.js +469 -210
  268. package/dist/unlock/standingWebvh.js.map +1 -1
  269. package/dist/webvh/accountEntry.d.ts +146 -0
  270. package/dist/webvh/accountEntry.d.ts.map +1 -0
  271. package/dist/webvh/accountEntry.js +239 -0
  272. package/dist/webvh/accountEntry.js.map +1 -0
  273. package/dist/webvh/didWeb.d.ts +12 -7
  274. package/dist/webvh/didWeb.d.ts.map +1 -1
  275. package/dist/webvh/didWeb.js +2 -2
  276. package/dist/webvh/didWeb.js.map +1 -1
  277. package/dist/webvh/didWebProjection.d.ts +164 -0
  278. package/dist/webvh/didWebProjection.d.ts.map +1 -0
  279. package/dist/webvh/didWebProjection.js +230 -0
  280. package/dist/webvh/didWebProjection.js.map +1 -0
  281. package/dist/webvh/didWebvh.d.ts +275 -136
  282. package/dist/webvh/didWebvh.d.ts.map +1 -1
  283. package/dist/webvh/didWebvh.js +307 -340
  284. package/dist/webvh/didWebvh.js.map +1 -1
  285. package/dist/webvh/enrollClient.d.ts +65 -0
  286. package/dist/webvh/enrollClient.d.ts.map +1 -0
  287. package/dist/webvh/enrollClient.js +172 -0
  288. package/dist/webvh/enrollClient.js.map +1 -0
  289. package/dist/webvh/index.d.ts +37 -12
  290. package/dist/webvh/index.d.ts.map +1 -1
  291. package/dist/webvh/index.js +33 -10
  292. package/dist/webvh/index.js.map +1 -1
  293. package/dist/webvh/listClients.d.ts +1 -35
  294. package/dist/webvh/listClients.d.ts.map +1 -1
  295. package/dist/webvh/listClients.js +2 -30
  296. package/dist/webvh/listClients.js.map +1 -1
  297. package/dist/webvh/revokeClient.d.ts +41 -11
  298. package/dist/webvh/revokeClient.d.ts.map +1 -1
  299. package/dist/webvh/revokeClient.js +99 -48
  300. package/dist/webvh/revokeClient.js.map +1 -1
  301. package/dist/webvh/standingZcap.d.ts +61 -14
  302. package/dist/webvh/standingZcap.d.ts.map +1 -1
  303. package/dist/webvh/standingZcap.js +91 -0
  304. package/dist/webvh/standingZcap.js.map +1 -1
  305. package/dist/webvh/verifyLog.d.ts +59 -5
  306. package/dist/webvh/verifyLog.d.ts.map +1 -1
  307. package/dist/webvh/verifyLog.js +76 -11
  308. package/dist/webvh/verifyLog.js.map +1 -1
  309. package/dist/webvh/wasIdStore.d.ts +8 -8
  310. package/dist/webvh/wasIdStore.d.ts.map +1 -1
  311. package/dist/webvh/wasIdStore.js +39 -14
  312. package/dist/webvh/wasIdStore.js.map +1 -1
  313. package/dist/webvh/zcap.d.ts +14 -1
  314. package/dist/webvh/zcap.d.ts.map +1 -1
  315. package/dist/webvh/zcap.js +3 -27
  316. package/dist/webvh/zcap.js.map +1 -1
  317. package/package.json +2 -2
  318. package/dist/webvh/keyAgreement.d.ts +0 -97
  319. package/dist/webvh/keyAgreement.d.ts.map +0 -1
  320. package/dist/webvh/keyAgreement.js +0 -71
  321. package/dist/webvh/keyAgreement.js.map +0 -1
@@ -1,14 +1,30 @@
1
1
  import { WasClient } from '@interop/was-client';
2
- import { effectiveParameters, readPublishedLog, WebvhLogConflictError, withLogConflictRetry } from '../webvh/didWebvh.js';
3
- import { delegationKeyInDocument, ladderVmIds } from '../webvh/listClients.js';
4
- import { delegationProofKeyId, zcapExpiring } from '../webvh/standingZcap.js';
2
+ import { spacePath } from '@interop/was-client/paths';
3
+ import { currentLogParameters, readPublishedLog, readPublishedLogOrThrow, WebvhLogConflictError, withLogConflictRetry } from '../webvh/didWebvh.js';
4
+ import { ladderVmIds } from '../resourceLog/document.js';
5
+ import { standingZcapStale } from '../webvh/standingZcap.js';
5
6
  import { delegateLogWrite } from '../recovery/recoveryDelegation.js';
6
7
  import { accountLogPinId } from '../webvh/verifyLog.js';
7
8
  import { mintSpaceId } from '../genesis/accountGenesis.js';
8
9
  import { attributeLadderRung, ladderRung, ladderVmKeyMultibase } from './ladder.js';
9
10
  import { revealLadderRungWebvh } from './ladderAnchored.js';
10
11
  import { ladderVmAgent, ladderVmZcapClient } from './zcap.js';
11
- import { clientAnnexDidParts, clientAnnexLogPinId, clientAnnexLogStore, delegatedClientsDelegationSpaceId, delegatedClientsPointer, ensureGenerationDelegationCurrent, mintCredentialClientAnnexGeneration, mintDelegatedClientsDelegation, mintGenerationDelegation, setDelegatedClientsPointerOnce } from './log.js';
12
+ import { mintSpaceRootVerbCapability } from './spaceCapability.js';
13
+ import { clientAnnexDidParts, clientAnnexLogPinId, clientAnnexLogStore, delegatedClientsDelegationSpaceId, delegatedClientsPointer, ensureClientAnnexSpace, ensureGenerationDelegationCurrent, mintDelegatedClientsDelegation, mintGenerationDelegation, mintPointedClientAnnexGeneration, setDelegatedClientsPointerOnce } from './log.js';
14
+ /**
15
+ * The HTTP status a raw signed request's rejection carries, when it carries
16
+ * one. `WasClient.request` applies no error mapping, so the status is all a
17
+ * caller has to dispatch on, and different transports hang it in different
18
+ * places (`status`, or `response.status`).
19
+ *
20
+ * @param err {unknown}
21
+ * @returns {number | undefined}
22
+ */
23
+ function rawRequestStatus(err) {
24
+ const raw = err;
25
+ const status = raw?.status ?? raw?.response?.status;
26
+ return typeof status === 'number' ? status : undefined;
27
+ }
12
28
  /**
13
29
  * The typed refusal of {@link ensureCredentialClientAnnexGeneration}: the
14
30
  * account is not in a shape this visit can mend, and nothing was written.
@@ -212,259 +228,364 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
212
228
  }
213
229
  return {};
214
230
  }
215
- if (annexSpaceId === undefined) {
216
- // THE FRESH-SPACE ARM: neither the pointer nor a sibling names a Space.
217
- // The pre-flight attribution runs before any generation or Space is
218
- // minted (a bridge delegation mint writes nothing durable); the stage
219
- // order mirrors the credential-anchored genesis exactly. A rung that is
220
- // only committed passes here and is revealed at the pointer entry.
221
- await assertPointerEntryAttributable({ ladderSeed, log: account.log });
231
+ /**
232
+ * The fresh-Space stage, controller-first past the create. The create
233
+ * itself must name the ladder VM's bare did:key: a storage server
234
+ * authorizes a Space create against the controller the request body names,
235
+ * and a root invocation must be signed by that very DID, so a create
236
+ * naming the account did:webvh is refused. The controller is flipped to
237
+ * the account DID in the very next request, before anything publishes into
238
+ * the Space.
239
+ *
240
+ * So the stranding window is one request wide. Inside it the stranded
241
+ * Space is did:key-controlled, which no server orphan sweep can reap,
242
+ * since a did:key resolves from its own bytes forever. Past the flip it is
243
+ * account-controlled and reapable. Narrowing the window to that one
244
+ * request is what this ordering buys; it does not close it.
245
+ *
246
+ * The flip preceding the generation mint is load-bearing rather than
247
+ * cosmetic. The mint and the delegation embed ride the ladder-signed
248
+ * sibling delegation, and the server admits that chain only once the
249
+ * Space's controller is the account DID whose document lists the ladder
250
+ * VM. Minting first and flipping afterwards would need the bootstrap key's
251
+ * own root invocations, which is the ordering this stage replaced.
252
+ *
253
+ * The flip swallows nothing. The establishment's bootstrap arm tolerates
254
+ * an authorization-class refusal there because its Space may be a
255
+ * sibling-named one a concurrent run already flipped; this Space's id was
256
+ * minted a moment ago and no other run can hold it, so every failure is
257
+ * the transport or logic failure it looks like and propagates.
258
+ *
259
+ * @returns {Promise<string>} the fresh auxiliary Space's id
260
+ */
261
+ async function mintFreshAnnexSpace() {
222
262
  const freshSpaceId = mintSpaceId();
223
263
  const keyAgent = await ladderVmAgent({ ladderSeed });
224
264
  const bootstrapWas = bootstrapWasFor({ keyAgent });
225
- const minted = await mintCredentialClientAnnexGeneration({
265
+ const created = await ensureClientAnnexSpace({
226
266
  was: bootstrapWas,
227
- wasServerUrl,
228
267
  spaceId: freshSpaceId,
229
- controller: keyAgent.id,
230
- ladderSeed
231
- });
232
- // The delegation embeds while the Space still answers to the bootstrap
233
- // did:key; the controller flip follows, then the pointer entry.
234
- const ensured = await ensureGenerationDelegationCurrent({
235
- store: clientAnnexLogStore({
236
- was: bootstrapWas,
237
- spaceId: freshSpaceId,
238
- generationId: minted.generationId
239
- }),
240
- ladderSeed,
241
- generationId: minted.generationId,
242
- mintGenerationDelegation: mintDelegation,
243
- expectedDid: minted.did,
244
- ...(pinStore !== undefined
245
- ? {
246
- pinStore,
247
- logId: clientAnnexLogPinId({
248
- spaceId: freshSpaceId,
249
- generationId: minted.generationId
250
- })
251
- }
252
- : {}),
253
- ...(now !== undefined ? { now } : {})
268
+ controller: keyAgent.id
254
269
  });
270
+ // The create's own answer is the current Description, so the flip carries
271
+ // it as `current` rather than re-reading what this call just wrote.
255
272
  await bootstrapWas
256
273
  .space(freshSpaceId)
257
- .configure({ controller: account.did, force: true });
258
- await movePointerAsLadder({
259
- idStore,
260
- ladderSeed,
261
- clientAnnexDid: minted.did,
262
- accountDid: account.did,
263
- ...(pinStore !== undefined
264
- ? { pinStore, logId: accountLogPinId({ spaceId }) }
265
- : {})
266
- });
267
- const sibling = await mintDelegatedClientsDelegation({
274
+ .configure({ current: created, controller: account.did, force: true });
275
+ return freshSpaceId;
276
+ }
277
+ /**
278
+ * One Space Description read, judged by its HTTP STATUS alone. A 404 is
279
+ * `'not-found'`; a 2xx is `'present'`, whatever its body says, since a
280
+ * Space served with an unreadable body is a present Space and reading it
281
+ * as absence is exactly what would re-point a live account. Every other
282
+ * answer -- a transport failure, a 5xx, a 4xx that is not 404 -- throws,
283
+ * so nothing but a real 404 can ever reach the absence decision.
284
+ *
285
+ * The read goes through the raw signed request rather than the
286
+ * `describe()` handle, whose null-on-404 translation also swallows 401 and
287
+ * 403 and an unparseable body.
288
+ *
289
+ * @param options {object}
290
+ * @param options.was {WasClient} the client whose signer invokes
291
+ * @param options.annexSpaceId {string}
292
+ * @param [options.capability] {IZcap} the attached capability; absent
293
+ * means a root invocation
294
+ * @returns {Promise<'present' | 'not-found'>}
295
+ */
296
+ async function readSpaceDescription({ was, annexSpaceId, capability }) {
297
+ let status;
298
+ try {
299
+ const response = await was.request({
300
+ path: spacePath(annexSpaceId),
301
+ method: 'GET',
302
+ ...(capability !== undefined ? { capability } : {})
303
+ });
304
+ status = response.status;
305
+ }
306
+ catch (err) {
307
+ if (rawRequestStatus(err) === 404) {
308
+ return 'not-found';
309
+ }
310
+ throw err;
311
+ }
312
+ if (status >= 200 && status < 300) {
313
+ return 'present';
314
+ }
315
+ if (status === 404) {
316
+ return 'not-found';
317
+ }
318
+ throw new Error(`client annex: the Space Description read for "${annexSpaceId}" ` +
319
+ `answered ${status}; the visit cannot tell whether the Space is gone.`);
320
+ }
321
+ /**
322
+ * Whether the auxiliary Space itself is gone from the server, asked only
323
+ * when the pointed generation's log did not read back. A storage server
324
+ * masks an unauthorized read as the same 404 an absent Space answers, so
325
+ * ONE 404 is not absence: it is "absent, or this reader has no authority
326
+ * here". Absence is therefore corroborated by two independent readers, and
327
+ * the Space is gone only when both answer a real 404.
328
+ *
329
+ * The first reader is a ladder-signed GET-only child of the Space's own
330
+ * root, which the account DID's document backs. The sibling delegation
331
+ * cannot carry the question: it targets the items subtree beneath the
332
+ * Space and says nothing about the Space Description.
333
+ *
334
+ * The second is a root invocation as the ladder VM's BARE did:key, the
335
+ * controller a torn establishment leaves behind when its flip never
336
+ * landed. That reader answers 2xx on exactly the Space the first reader
337
+ * has no authority over, so the pair covers both controllers a live annex
338
+ * Space of this credential's can have.
339
+ *
340
+ * The residual bound, stated because no read can close it: a server that
341
+ * does not admit the ladder delegation clause's single-verb predicate
342
+ * refuses the first probe with the same masked 404, and on an
343
+ * account-controlled Space the second probe is refused too. Both readers
344
+ * then say `'not-found'` about a live Space. That is a server older than
345
+ * the one this arm was built against, and the arm's cost there is a
346
+ * re-point of a live generation.
347
+ *
348
+ * @param options {object}
349
+ * @param options.annexSpaceId {string}
350
+ * @param options.was {WasClient} the standing client's storage client
351
+ * @returns {Promise<boolean>}
352
+ */
353
+ async function annexSpaceAbsent({ annexSpaceId, was }) {
354
+ const probe = await mintSpaceRootVerbCapability({
268
355
  zcapClient: ladderClient,
269
- wasServerUrl,
270
- clientAnnexSpaceId: freshSpaceId,
356
+ storageServerUrl: wasServerUrl,
357
+ spaceId: annexSpaceId,
358
+ verb: 'GET',
271
359
  controller: standingClient.did,
272
360
  ...(now !== undefined ? { now } : {})
273
361
  });
362
+ const delegated = await readSpaceDescription({
363
+ was,
364
+ annexSpaceId,
365
+ capability: probe
366
+ });
367
+ if (delegated === 'present') {
368
+ return false;
369
+ }
370
+ const bootstrapWas = bootstrapWasFor({
371
+ keyAgent: await ladderVmAgent({ ladderSeed })
372
+ });
373
+ const asBootstrap = await readSpaceDescription({
374
+ was: bootstrapWas,
375
+ annexSpaceId
376
+ });
377
+ return asBootstrap === 'not-found';
378
+ }
379
+ let spaceMinted = false;
380
+ let pointedSpaceMissing = false;
381
+ /**
382
+ * The arms that run inside one auxiliary Space: the sibling delegation,
383
+ * the pointed generation's renewal, and the fresh-generation mint with its
384
+ * pointer move. Called once on the resolved Space, and once more on a
385
+ * fresh Space when the pointed one turns out to be gone -- the replacement
386
+ * is decided before any write, so nothing is stranded by the re-run.
387
+ *
388
+ * @param options {object}
389
+ * @param options.annexSpaceId {string} the Space this run works in
390
+ * @param options.allowSpaceReplacement {boolean} whether an absent
391
+ * pointed generation may be checked against the Space itself, and a
392
+ * fresh Space minted when the Space is gone. False on the run that
393
+ * already works in a Space this visit created
394
+ * @param [options.pointer] {string} the pointed annex DID, when the
395
+ * document names one and this run works in its Space
396
+ * @returns {Promise<ClientAnnexGenerationEnsureOutcome>}
397
+ */
398
+ async function runInAnnexSpace({ annexSpaceId, allowSpaceReplacement, pointer }) {
399
+ // A usable sibling first: absent, targeting a different Space than this
400
+ // run works in, or stale on either of the standing-zcap axes -- expiry
401
+ // (past, or inside the renewal window) and signer death (its proof key
402
+ // no longer under `capabilityDelegation` in the verified account
403
+ // document, the current-key-set rule) -- a fresh sibling is minted
404
+ // (local ladder-VM signing, which verifies because the gate above proved
405
+ // the VM a document verification method) so every annex request below
406
+ // can ride it.
407
+ let sibling = delegatedClients;
408
+ let siblingReminted = false;
409
+ const siblingStale = sibling !== undefined &&
410
+ standingZcapStale({
411
+ zcap: sibling,
412
+ doc: account.doc,
413
+ ...(now !== undefined ? { now } : {})
414
+ });
415
+ if (sibling === undefined ||
416
+ siblingSpaceId !== annexSpaceId ||
417
+ siblingStale) {
418
+ sibling = await mintDelegatedClientsDelegation({
419
+ zcapClient: ladderClient,
420
+ wasServerUrl,
421
+ clientAnnexSpaceId: annexSpaceId,
422
+ controller: standingClient.did,
423
+ ...(now !== undefined ? { now } : {})
424
+ });
425
+ siblingReminted = true;
426
+ }
427
+ const usableSibling = sibling;
428
+ const standingWas = new WasClient({
429
+ serverUrl: wasServerUrl,
430
+ zcapClient: standingClient.zcapClient
431
+ });
432
+ const storeFor = (generationId) => clientAnnexLogStore({
433
+ was: standingWas,
434
+ spaceId: annexSpaceId,
435
+ generationId,
436
+ capability: usableSibling
437
+ });
438
+ const annexPin = (generationId) => pinStore !== undefined
439
+ ? {
440
+ pinStore,
441
+ logId: clientAnnexLogPinId({ spaceId: annexSpaceId, generationId })
442
+ }
443
+ : {};
444
+ // RENEW PRECEDES MINT: a live, verifiable pointed generation is renewed
445
+ // in place; only a rung this generation never committed falls through to
446
+ // the fresh mint (the GC swap's no-committed-survivor escape).
447
+ if (pointer !== undefined) {
448
+ const parts = clientAnnexDidParts({ did: pointer });
449
+ const pointedLog = await readPublishedLog({
450
+ idStore: storeFor(parts.generationId),
451
+ expectedDid: pointer,
452
+ ...annexPin(parts.generationId)
453
+ });
454
+ if (pointedLog !== undefined) {
455
+ try {
456
+ const ensured = await ensureGenerationDelegationCurrent({
457
+ store: storeFor(parts.generationId),
458
+ ladderSeed,
459
+ generationId: parts.generationId,
460
+ mintGenerationDelegation: mintDelegation,
461
+ expectedDid: pointer,
462
+ accountDoc: account.doc,
463
+ // The head just read: on a healthy account this stage spends no
464
+ // second round trip on the same log, and hands its head back for
465
+ // the enrollment to build on.
466
+ published: pointedLog,
467
+ ...annexPin(parts.generationId),
468
+ ...(now !== undefined ? { now } : {})
469
+ });
470
+ const resealed = await resealRecord({
471
+ delegatedClients: usableSibling,
472
+ siblingReminted
473
+ });
474
+ return {
475
+ clientAnnexDid: pointer,
476
+ generationDelegation: ensured.delegation,
477
+ delegation: usableBridge,
478
+ delegatedClients: usableSibling,
479
+ generationMinted: false,
480
+ spaceMinted,
481
+ pointedSpaceMissing,
482
+ delegationRenewed: ensured.renewed,
483
+ siblingReminted,
484
+ bridgeReminted,
485
+ ...(ensured.published !== undefined
486
+ ? { generationLog: ensured.published }
487
+ : {}),
488
+ ...resealed
489
+ };
490
+ }
491
+ catch (err) {
492
+ if (err.name !==
493
+ 'ClientAnnexRungUncommittedError') {
494
+ throw err;
495
+ }
496
+ // This credential's rung was never committed into the pointed
497
+ // generation (bound mid-generation): fall through to the fresh
498
+ // mint, which commits it with the fresh genesis.
499
+ }
500
+ }
501
+ else if (allowSpaceReplacement &&
502
+ (await annexSpaceAbsent({ annexSpaceId, was: standingWas }))) {
503
+ // THE POINTED SPACE IS GONE. A missing generation log inside a live
504
+ // Space is the fresh-generation arm's case; a missing SPACE is not,
505
+ // since every write below would land in a Space that does not exist
506
+ // and the visit would fail on something other than the typed
507
+ // refusal. The Space is re-minted and the run starts over in it,
508
+ // before anything has been written.
509
+ await attributePointerEntryRung({ ladderSeed, log: account.log });
510
+ const freshSpaceId = await mintFreshAnnexSpace();
511
+ spaceMinted = true;
512
+ pointedSpaceMissing = true;
513
+ return runInAnnexSpace({
514
+ annexSpaceId: freshSpaceId,
515
+ allowSpaceReplacement: false
516
+ });
517
+ }
518
+ }
519
+ // THE FRESH-GENERATION ARM: pre-flight attribution first (never mint a
520
+ // generation the pointer entry cannot then name), then the GC swap's
521
+ // stage order minus its revoke -- mint, install the delegation,
522
+ // re-point. The fresh genesis commits only the acting credential's annex
523
+ // rung; other standing credentials' per-generation rungs are re-committed
524
+ // only by their own later ceremonies (a property of every generation
525
+ // swap).
526
+ await attributePointerEntryRung({ ladderSeed, log: account.log });
527
+ const generation = await mintPointedClientAnnexGeneration({
528
+ was: standingWas,
529
+ wasServerUrl,
530
+ spaceId: annexSpaceId,
531
+ controller: account.did,
532
+ ladderSeed,
533
+ capability: usableSibling,
534
+ mintGenerationDelegation: mintDelegation,
535
+ // No revocation of the superseded generation's delegation is
536
+ // attempted: a transient visit has no reach that could invoke it (the
537
+ // standing client is neither the Space controller nor in that
538
+ // delegation's chain). The pointer move itself retires it on a
539
+ // conforming server -- the inspector clause compares the delegation's
540
+ // controller against the document's pointer -- and it otherwise rots
541
+ // on its TTL.
542
+ point: clientAnnexDid => movePointerAsLadder({
543
+ idStore,
544
+ ladderSeed,
545
+ clientAnnexDid,
546
+ accountDid: account.did,
547
+ ...(pinStore !== undefined
548
+ ? { pinStore, logId: accountLogPinId({ spaceId }) }
549
+ : {})
550
+ }),
551
+ ...(pinStore !== undefined ? { pinStore } : {}),
552
+ ...(now !== undefined ? { now } : {})
553
+ });
274
554
  const resealed = await resealRecord({
275
- delegatedClients: sibling,
276
- siblingReminted: true
555
+ delegatedClients: usableSibling,
556
+ siblingReminted
277
557
  });
278
558
  return {
279
- clientAnnexDid: minted.did,
280
- generationDelegation: ensured.delegation,
559
+ clientAnnexDid: generation.clientAnnexDid,
560
+ generationDelegation: generation.generationDelegation,
281
561
  delegation: usableBridge,
282
- delegatedClients: sibling,
562
+ delegatedClients: usableSibling,
283
563
  generationMinted: true,
284
- spaceMinted: true,
564
+ spaceMinted,
565
+ pointedSpaceMissing,
285
566
  delegationRenewed: false,
286
- siblingReminted: true,
567
+ siblingReminted,
287
568
  bridgeReminted,
288
569
  ...resealed
289
570
  };
290
571
  }
291
- // THE EXISTING-SPACE ARMS. A usable sibling first: absent, targeting a
292
- // different Space than the resolved one, or stale on either of the
293
- // standing-zcap axes -- expiry (past, or inside the renewal window) and
294
- // signer death (its proof key no longer under `capabilityDelegation` in
295
- // the verified account document, the current-key-set rule) -- a fresh
296
- // sibling is minted (local ladder-VM signing, which verifies because the
297
- // gate above proved the VM a document verification method) so every annex
298
- // request below can ride it.
299
- let sibling = delegatedClients;
300
- let siblingReminted = false;
301
- const siblingStale = sibling !== undefined &&
302
- standingZcapStale({
303
- zcap: sibling,
304
- doc: account.doc,
305
- ...(now !== undefined ? { now } : {})
306
- });
307
- if (sibling === undefined ||
308
- siblingSpaceId !== annexSpaceId ||
309
- siblingStale) {
310
- sibling = await mintDelegatedClientsDelegation({
311
- zcapClient: ladderClient,
312
- wasServerUrl,
313
- clientAnnexSpaceId: annexSpaceId,
314
- controller: standingClient.did,
315
- ...(now !== undefined ? { now } : {})
316
- });
317
- siblingReminted = true;
318
- }
319
- const usableSibling = sibling;
320
- const standingWas = new WasClient({
321
- serverUrl: wasServerUrl,
322
- zcapClient: standingClient.zcapClient
323
- });
324
- const storeFor = (generationId) => clientAnnexLogStore({
325
- was: standingWas,
326
- spaceId: annexSpaceId,
327
- generationId,
328
- capability: usableSibling
329
- });
330
- const annexPin = (generationId) => pinStore !== undefined
331
- ? {
332
- pinStore,
333
- logId: clientAnnexLogPinId({ spaceId: annexSpaceId, generationId })
334
- }
335
- : {};
336
- // RENEW PRECEDES MINT: a live, verifiable pointed generation is renewed in
337
- // place; only a rung this generation never committed falls through to the
338
- // fresh mint (the GC swap's no-committed-survivor escape).
339
- if (pointer !== undefined) {
340
- const parts = clientAnnexDidParts({ did: pointer });
341
- const pointedLog = await readPublishedLog({
342
- idStore: storeFor(parts.generationId),
343
- expectedDid: pointer,
344
- ...annexPin(parts.generationId)
572
+ if (annexSpaceId === undefined) {
573
+ // NEITHER THE POINTER NOR A SIBLING NAMES A SPACE. The pre-flight
574
+ // attribution runs before any Space or generation is minted (a bridge
575
+ // delegation mint writes nothing durable).
576
+ await attributePointerEntryRung({ ladderSeed, log: account.log });
577
+ const freshSpaceId = await mintFreshAnnexSpace();
578
+ spaceMinted = true;
579
+ return runInAnnexSpace({
580
+ annexSpaceId: freshSpaceId,
581
+ allowSpaceReplacement: false
345
582
  });
346
- if (pointedLog !== undefined) {
347
- try {
348
- const ensured = await ensureGenerationDelegationCurrent({
349
- store: storeFor(parts.generationId),
350
- ladderSeed,
351
- generationId: parts.generationId,
352
- mintGenerationDelegation: mintDelegation,
353
- expectedDid: pointer,
354
- accountDoc: account.doc,
355
- ...annexPin(parts.generationId),
356
- ...(now !== undefined ? { now } : {})
357
- });
358
- const resealed = await resealRecord({
359
- delegatedClients: usableSibling,
360
- siblingReminted
361
- });
362
- return {
363
- clientAnnexDid: pointer,
364
- generationDelegation: ensured.delegation,
365
- delegation: usableBridge,
366
- delegatedClients: usableSibling,
367
- generationMinted: false,
368
- spaceMinted: false,
369
- delegationRenewed: ensured.renewed,
370
- siblingReminted,
371
- bridgeReminted,
372
- ...resealed
373
- };
374
- }
375
- catch (err) {
376
- if (err.name !== 'ClientAnnexRungUncommittedError') {
377
- throw err;
378
- }
379
- // This credential's rung was never committed into the pointed
380
- // generation (bound mid-generation): fall through to the fresh mint,
381
- // which commits it with the fresh genesis.
382
- }
383
- }
384
583
  }
385
- // THE FRESH-GENERATION ARM, existing Space: pre-flight attribution first
386
- // (never mint a generation the pointer entry cannot then name), then the
387
- // GC swap's stage order minus its revoke -- mint, install the delegation,
388
- // re-point. The fresh genesis commits only the acting credential's annex
389
- // rung; other standing credentials' per-generation rungs are re-committed
390
- // only by their own later ceremonies (a property of every generation
391
- // swap).
392
- await assertPointerEntryAttributable({ ladderSeed, log: account.log });
393
- const minted = await mintCredentialClientAnnexGeneration({
394
- was: standingWas,
395
- wasServerUrl,
396
- spaceId: annexSpaceId,
397
- controller: account.did,
398
- ladderSeed,
399
- capability: usableSibling
584
+ return runInAnnexSpace({
585
+ annexSpaceId,
586
+ allowSpaceReplacement: true,
587
+ ...(pointer !== undefined ? { pointer } : {})
400
588
  });
401
- const ensured = await ensureGenerationDelegationCurrent({
402
- store: storeFor(minted.generationId),
403
- ladderSeed,
404
- generationId: minted.generationId,
405
- mintGenerationDelegation: mintDelegation,
406
- expectedDid: minted.did,
407
- ...annexPin(minted.generationId),
408
- ...(now !== undefined ? { now } : {})
409
- });
410
- // No revocation of the superseded generation's delegation is attempted:
411
- // a transient visit has no reach that could invoke it (the standing client
412
- // is neither the Space controller nor in that delegation's chain). The
413
- // pointer move itself retires it on a conforming server -- the inspector
414
- // clause compares the delegation's controller against the document's
415
- // pointer -- and it otherwise rots on its TTL.
416
- await movePointerAsLadder({
417
- idStore,
418
- ladderSeed,
419
- clientAnnexDid: minted.did,
420
- accountDid: account.did,
421
- ...(pinStore !== undefined
422
- ? { pinStore, logId: accountLogPinId({ spaceId }) }
423
- : {})
424
- });
425
- const resealed = await resealRecord({
426
- delegatedClients: usableSibling,
427
- siblingReminted
428
- });
429
- return {
430
- clientAnnexDid: minted.did,
431
- generationDelegation: ensured.delegation,
432
- delegation: usableBridge,
433
- delegatedClients: usableSibling,
434
- generationMinted: true,
435
- spaceMinted: false,
436
- delegationRenewed: false,
437
- siblingReminted,
438
- bridgeReminted,
439
- ...resealed
440
- };
441
- }
442
- /**
443
- * The one staleness predicate for the standing recorded delegations this
444
- * ensure may renew: the record's bridge delegation and its `delegatedClients`
445
- * sibling. Two axes, the established pair -- expiry (past, or inside the
446
- * renewal window) and signer death (the proof's verification method no longer
447
- * under `capabilityDelegation` in the verified account document, the
448
- * current-key-set rule). One helper rather than a copy per delegation, so the
449
- * two can never drift onto different rules.
450
- *
451
- * @param options {object}
452
- * @param options.zcap {IZcap} the recorded delegation
453
- * @param options.doc {object} the VERIFIED account document
454
- * @param [options.now] {number} epoch milliseconds, for tests
455
- * @returns {boolean}
456
- */
457
- function standingZcapStale({ zcap, doc, now }) {
458
- const { expires } = zcap;
459
- const delegationKeyId = delegationProofKeyId(zcap);
460
- return (zcapExpiring({
461
- ...(expires !== undefined ? { expires } : {}),
462
- ...(now !== undefined ? { now } : {})
463
- }) ||
464
- !delegationKeyInDocument({
465
- doc: doc,
466
- ...(delegationKeyId !== undefined ? { delegationKeyId } : {})
467
- }));
468
589
  }
469
590
  /**
470
591
  * The annex Space, in the settled resolution order: the account document's
@@ -497,85 +618,65 @@ export function resolveClientAnnexSpaceId({ doc, delegatedClients }) {
497
618
  };
498
619
  }
499
620
  /**
500
- * The pre-flight rung attribution: the `{ updateSeed, stagedSeed }` pair the
501
- * pointer entry signs with, recovered from the verified account log's
502
- * current parameters. The signer must be a REVEALED rung (the entry verifies
503
- * against the log's `updateKeys`), with the next rung staged per the
504
- * carry-over convention. No rung of this ladder standing -- or only a
505
- * committed hash, which cannot sign -- refuses with
506
- * {@link ClientAnnexGenerationUnavailableError} before anything is minted.
507
- * Exported for the establishment's stage-3 primitive, whose pointer entry
508
- * signs by the same attribution.
621
+ * The pre-flight rung attribution every pointer-moving arm runs before
622
+ * minting anything: this ladder has a rung the pointer entry will be able to
623
+ * sign with, either standing in `updateKeys` already (`revealed`) or
624
+ * committed in `nextKeyHashes` and revealable by {@link movePointerAsLadder}
625
+ * (`committed`). A ladder the log carries no rung of at all, and an
626
+ * ambiguous attribution, refuse with
627
+ * {@link ClientAnnexGenerationUnavailableError} before a generation or a
628
+ * Space is minted -- the one place the ladder's `LadderAttributionError`
629
+ * maps onto that refusal.
509
630
  *
510
631
  * @param options {object}
511
632
  * @param options.ladderSeed {Uint8Array}
512
633
  * @param options.log {DIDLog} the VERIFIED account log
513
- * @returns {Promise<ClientWebvhUpdateKeys>}
634
+ * @returns {Promise<{ rung: LadderRung, state: LadderRungState }>}
514
635
  */
515
- export async function pointerEntryUpdateKeys({ ladderSeed, log }) {
516
- const params = effectiveParameters(log);
517
- const current = params[params.length - 1] ?? {
518
- updateKeys: [],
519
- nextKeyHashes: []
520
- };
521
- const unattributable = () => new ClientAnnexGenerationUnavailableError({
522
- reason: 'update-key-not-attributable',
523
- message: "No current account-log update key is a rung of this credential's " +
524
- 'ladder; the pointer entry could not be signed, so nothing is minted.'
525
- });
526
- let attributed;
636
+ export async function attributePointerEntryRung({ ladderSeed, log }) {
637
+ const current = currentLogParameters({ log });
527
638
  try {
528
- attributed = await attributeLadderRung({ ladderSeed, published: current });
639
+ return await attributeLadderRung({ ladderSeed, published: current });
529
640
  }
530
641
  catch (err) {
531
642
  if (err.name === 'LadderAttributionError') {
532
- throw unattributable();
643
+ throw new ClientAnnexGenerationUnavailableError({
644
+ reason: 'update-key-not-attributable',
645
+ message: "The account log carries no rung of this credential's ladder, or " +
646
+ 'the attribution is ambiguous; the pointer entry could not be ' +
647
+ 'signed, so nothing is minted.'
648
+ });
533
649
  }
534
650
  throw err;
535
651
  }
536
- if (attributed.state !== 'revealed') {
537
- throw unattributable();
538
- }
539
- const staged = await ladderRung({
540
- ladderSeed,
541
- index: attributed.rung.index + 1
542
- });
543
- return { updateSeed: attributed.rung.seed, stagedSeed: staged.seed };
544
652
  }
545
653
  /**
546
- * The pre-flight the pointer-moving arms run before minting anything: this
547
- * ladder has a rung the pointer entry will be able to sign with, either
548
- * standing in `updateKeys` already or committed in `nextKeyHashes` and
549
- * revealable by {@link movePointerAsLadder}. A ladder the log carries no rung
550
- * of at all, and an ambiguous attribution, refuse here with
551
- * {@link ClientAnnexGenerationUnavailableError} before a generation or a
552
- * Space is minted.
654
+ * The `{ updateSeed, stagedSeed }` pair the pointer entry signs with, over
655
+ * {@link attributePointerEntryRung}. The signer must be a REVEALED rung (the
656
+ * entry verifies against the log's `updateKeys`), with the next rung staged
657
+ * per the carry-over convention; a rung standing only as a committed hash
658
+ * cannot sign and refuses the same way. Exported for the establishment's
659
+ * stage-3 primitive, whose pointer entry signs by the same attribution.
553
660
  *
554
661
  * @param options {object}
555
662
  * @param options.ladderSeed {Uint8Array}
556
663
  * @param options.log {DIDLog} the VERIFIED account log
557
- * @returns {Promise<void>}
664
+ * @returns {Promise<ClientWebvhUpdateKeys>}
558
665
  */
559
- async function assertPointerEntryAttributable({ ladderSeed, log }) {
560
- const params = effectiveParameters(log);
561
- const current = params[params.length - 1] ?? {
562
- updateKeys: [],
563
- nextKeyHashes: []
564
- };
565
- try {
566
- await attributeLadderRung({ ladderSeed, published: current });
567
- }
568
- catch (err) {
569
- if (err.name === 'LadderAttributionError') {
570
- throw new ClientAnnexGenerationUnavailableError({
571
- reason: 'update-key-not-attributable',
572
- message: "The account log carries no rung of this credential's ladder, or " +
573
- 'the attribution is ambiguous; the pointer entry could not be ' +
574
- 'signed, so nothing is minted.'
575
- });
576
- }
577
- throw err;
666
+ export async function pointerEntryUpdateKeys({ ladderSeed, log }) {
667
+ const attributed = await attributePointerEntryRung({ ladderSeed, log });
668
+ if (attributed.state !== 'revealed') {
669
+ throw new ClientAnnexGenerationUnavailableError({
670
+ reason: 'update-key-not-attributable',
671
+ message: "No current account-log update key is a rung of this credential's " +
672
+ 'ladder; the pointer entry could not be signed, so nothing is minted.'
673
+ });
578
674
  }
675
+ const staged = await ladderRung({
676
+ ladderSeed,
677
+ index: attributed.rung.index + 1
678
+ });
679
+ return { updateSeed: attributed.rung.seed, stagedSeed: staged.seed };
579
680
  }
580
681
  /**
581
682
  * The `#DelegatedClients` pointer move as a credential-only visit makes it:
@@ -614,7 +715,7 @@ async function assertPointerEntryAttributable({ ladderSeed, log }) {
614
715
  * racing entry landing between the attribution and the PUT loses the CAS and
615
716
  * surfaces as a `WebvhLogConflictError` -- the refusal the outer loop
616
717
  * re-attributes from. The pre-flight guard
617
- * ({@link assertPointerEntryAttributable}) therefore cannot fire from
718
+ * ({@link attributePointerEntryRung}) therefore cannot fire from
618
719
  * staleness here: it runs on the caller's snapshot before anything is minted,
619
720
  * while every entry this function publishes is built on a head it read
620
721
  * itself.
@@ -641,14 +742,12 @@ async function movePointerAsLadder({ idStore, ladderSeed, clientAnnexDid, accoun
641
742
  });
642
743
  // The head the reveal entry just published (or the unchanged head, when
643
744
  // the rung was revealed already), under the same pin.
644
- const published = await readPublishedLog({
745
+ const published = await readPublishedLogOrThrow({
645
746
  idStore,
646
747
  expectedDid: accountDid,
647
- ...pin
748
+ ...pin,
749
+ missingMessage: 'did:webvh: did.jsonl is missing; nothing to point at a client annex.'
648
750
  });
649
- if (published === undefined) {
650
- throw new Error('did:webvh: did.jsonl is missing; nothing to point at a client annex.');
651
- }
652
751
  // A racing ceremony that consumed the rung between this reveal and this
653
752
  // read leaves the ladder committed-only again, which the attribution
654
753
  // reports as `update-key-not-attributable`. Inside this loop that is a
@@ -674,7 +773,7 @@ async function movePointerAsLadder({ idStore, ladderSeed, clientAnnexDid, accoun
674
773
  }
675
774
  await setDelegatedClientsPointerOnce({
676
775
  idStore,
677
- updateKeys,
776
+ signer: { kind: 'client', updateKeys },
678
777
  clientAnnexDid,
679
778
  expectedDid: accountDid,
680
779
  logOnly: true,