@interop/wallet-core 0.61.0 → 0.62.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 (83) hide show
  1. package/dist/clientAnnex/forgetLast.d.ts +66 -19
  2. package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
  3. package/dist/clientAnnex/forgetLast.js +120 -38
  4. package/dist/clientAnnex/forgetLast.js.map +1 -1
  5. package/dist/clientAnnex/heal.d.ts +64 -29
  6. package/dist/clientAnnex/heal.d.ts.map +1 -1
  7. package/dist/clientAnnex/heal.js +287 -50
  8. package/dist/clientAnnex/heal.js.map +1 -1
  9. package/dist/clientAnnex/index.d.ts +2 -2
  10. package/dist/clientAnnex/index.d.ts.map +1 -1
  11. package/dist/clientAnnex/index.js +2 -2
  12. package/dist/clientAnnex/index.js.map +1 -1
  13. package/dist/clientAnnex/ladder.d.ts +246 -18
  14. package/dist/clientAnnex/ladder.d.ts.map +1 -1
  15. package/dist/clientAnnex/ladder.js +742 -53
  16. package/dist/clientAnnex/ladder.js.map +1 -1
  17. package/dist/clientAnnex/ladderAnchored.d.ts +113 -6
  18. package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
  19. package/dist/clientAnnex/ladderAnchored.js +208 -27
  20. package/dist/clientAnnex/ladderAnchored.js.map +1 -1
  21. package/dist/clientAnnex/log.d.ts +37 -1
  22. package/dist/clientAnnex/log.d.ts.map +1 -1
  23. package/dist/clientAnnex/log.js +34 -10
  24. package/dist/clientAnnex/log.js.map +1 -1
  25. package/dist/clientAnnex/recoveryLadderAnchored.d.ts +32 -7
  26. package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
  27. package/dist/clientAnnex/recoveryLadderAnchored.js +124 -23
  28. package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
  29. package/dist/clientAnnex/zcap.js +2 -2
  30. package/dist/clientAnnex/zcap.js.map +1 -1
  31. package/dist/identity/agents.js +2 -2
  32. package/dist/identity/agents.js.map +1 -1
  33. package/dist/keys/index.d.ts +1 -1
  34. package/dist/keys/index.d.ts.map +1 -1
  35. package/dist/keys/index.js +1 -1
  36. package/dist/keys/index.js.map +1 -1
  37. package/dist/keys/userKeyRoster.d.ts +32 -2
  38. package/dist/keys/userKeyRoster.d.ts.map +1 -1
  39. package/dist/keys/userKeyRoster.js +40 -2
  40. package/dist/keys/userKeyRoster.js.map +1 -1
  41. package/dist/recovery/recoveryDelegation.d.ts +4 -1
  42. package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
  43. package/dist/recovery/recoveryDelegation.js +4 -2
  44. package/dist/recovery/recoveryDelegation.js.map +1 -1
  45. package/dist/recovery/recoveryWebvh.d.ts +42 -2
  46. package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
  47. package/dist/recovery/recoveryWebvh.js +160 -18
  48. package/dist/recovery/recoveryWebvh.js.map +1 -1
  49. package/dist/unlock/index.d.ts +2 -2
  50. package/dist/unlock/index.d.ts.map +1 -1
  51. package/dist/unlock/index.js +1 -1
  52. package/dist/unlock/index.js.map +1 -1
  53. package/dist/unlock/retire.d.ts +62 -9
  54. package/dist/unlock/retire.d.ts.map +1 -1
  55. package/dist/unlock/retire.js +59 -5
  56. package/dist/unlock/retire.js.map +1 -1
  57. package/dist/unlock/standingWebvh.d.ts +131 -21
  58. package/dist/unlock/standingWebvh.d.ts.map +1 -1
  59. package/dist/unlock/standingWebvh.js +239 -54
  60. package/dist/unlock/standingWebvh.js.map +1 -1
  61. package/dist/webvh/didWebvh.d.ts +3 -2
  62. package/dist/webvh/didWebvh.d.ts.map +1 -1
  63. package/dist/webvh/didWebvh.js +7 -5
  64. package/dist/webvh/didWebvh.js.map +1 -1
  65. package/dist/webvh/index.d.ts +2 -2
  66. package/dist/webvh/index.d.ts.map +1 -1
  67. package/dist/webvh/index.js +1 -1
  68. package/dist/webvh/index.js.map +1 -1
  69. package/dist/webvh/keyAgreement.d.ts +25 -0
  70. package/dist/webvh/keyAgreement.d.ts.map +1 -1
  71. package/dist/webvh/keyAgreement.js +24 -0
  72. package/dist/webvh/keyAgreement.js.map +1 -1
  73. package/dist/webvh/listClients.d.ts +7 -5
  74. package/dist/webvh/listClients.d.ts.map +1 -1
  75. package/dist/webvh/listClients.js +7 -5
  76. package/dist/webvh/listClients.js.map +1 -1
  77. package/dist/webvh/revokeClient.d.ts +48 -0
  78. package/dist/webvh/revokeClient.d.ts.map +1 -1
  79. package/dist/webvh/revokeClient.js +85 -1
  80. package/dist/webvh/revokeClient.js.map +1 -1
  81. package/dist/webvh/zcap.js +3 -3
  82. package/dist/webvh/zcap.js.map +1 -1
  83. package/package.json +5 -5
@@ -5,15 +5,17 @@
5
5
  * The client-annex generation ensure a TRANSIENT visit runs -- a session
6
6
  * holding nothing but a standing unlock credential (its ladder seed, its
7
7
  * `delegatedClients` sibling delegation, and the standing-client identity
8
- * derived from the typed secret). Four durable states make the annex
9
- * unreachable from such a visit: the account document carries no
10
- * `#DelegatedClients` pointer; the pointed generation's log is gone (GC'd,
11
- * or never minted); the embedded generation delegation is expired, inside
12
- * its renewal window, or signed by a key the document no longer lists; the
13
- * record carries no sibling delegation, or its sibling targets another
14
- * Space. On a ladder-anchored account -- the ladder VM a document
8
+ * derived from the typed secret). Five durable states cut such a visit off
9
+ * from the annex, or from the account log the annex is pointed at: the
10
+ * account document carries no `#DelegatedClients` pointer; the pointed
11
+ * generation's log is gone (GC'd, or never minted); the embedded generation
12
+ * delegation is expired, inside its renewal window, or signed by a key the
13
+ * document no longer lists; the record carries no sibling delegation, or its
14
+ * sibling targets another Space; the record's bridge delegation is expired,
15
+ * inside its renewal window, or signed by a key the document no longer
16
+ * lists. On a ladder-anchored account -- the ladder VM a document
15
17
  * verification method, the ladder's rungs the log's update keys -- the visit
16
- * itself can mend all four, and this module is the orchestrator: a
18
+ * itself can mend all five, and this module is the orchestrator: a
17
19
  * converging ensure that detects each state from durable state, mends it
18
20
  * with the existing annex primitives, and reports what ran.
19
21
  *
@@ -38,15 +40,25 @@
38
40
  * ordering exactly (Space under the ladder VM's bare did:key, mint
39
41
  * controller-tier, delegation embed while the Space still answers to the
40
42
  * bootstrap key, controller flip, then the pointer entry).
43
+ * - The BRIDGE RENEWAL PRECEDES EVERY ARM: the record's bridge delegation is
44
+ * the credential's one write path into the account log, so a stale one is
45
+ * replaced before any arm runs and the caller's account-log store is built
46
+ * over the usable bridge (the `idStoreFor` factory). A pointer entry in
47
+ * either minting arm would otherwise ride a delegation the server refuses.
41
48
  * - Pointer entries go through the caller's account-log store with
42
49
  * `logOnly: true`: a bridge-delegated writer has no `did.json` projection
43
50
  * rights, and the log is the source of truth.
44
51
  *
45
- * A fresh sibling delegation (minted when the record carries none, or one
46
- * targeting another Space) is handed back through the REQUIRED
47
- * `onRebindRecord` seam after the generation and pointer are durable -- the
48
- * caller re-seals the unlock record with it, and a run torn before that
49
- * re-seal re-derives everything from the ladder seed at the next visit.
52
+ * Both renewable record delegations -- the bridge, and the sibling (minted
53
+ * when the record carries none, when it targets another Space, or when it is
54
+ * stale) -- are handed back through the REQUIRED `onRebindRecord` seam after
55
+ * the generation and pointer are durable. The seam always receives BOTH
56
+ * usable delegations, whichever of them was freshly minted, so the caller
57
+ * re-seals the unlock record from one pair; a run torn before that re-seal
58
+ * re-derives everything from the ladder seed at the next visit. A re-seal
59
+ * that fails is fatal when the sibling was fresh and is reported on the
60
+ * outcome's `bridgeResealError` when only the bridge was, since the fresh
61
+ * bridge already served this visit and the next visit re-mints it.
50
62
  */
51
63
  import type { IZcap } from '@interop/data-integrity-core';
52
64
  import type { ZcapClient } from '@interop/ezcap';
@@ -59,16 +71,18 @@ import type { ICapabilityAgent } from '../webvh/zcap.js';
59
71
  *
60
72
  * `'ladder-vm-not-anchored'`: this credential's ladder VM is not a
61
73
  * verification method of the account document, so nothing ladder-signed can
62
- * verify. Two distinct states land here: an account with enrolled clients
63
- * and no ladder VM at all (the self-enrollment's add entry removes
64
- * them; the mender there is the step-up ceremony, not this ensure), and a
65
- * client-less account anchored on ANOTHER standing credential's ladder --
66
- * e.g. a passkey visiting an account the passphrase's ladder anchors, whose
67
- * own VM no ceremony has published.
74
+ * verify. A standing credential's VM stands for as long as the credential
75
+ * does -- enrollment leaves it alone -- so this is the backstop for a
76
+ * document that never carried it: a credential whose establishment was torn
77
+ * before its document entry, or a visit by a credential to an account
78
+ * another credential's ladder anchors (a passkey visiting an account the
79
+ * passphrase established).
68
80
  *
69
- * `'update-key-not-attributable'`: a pointer entry is needed, but no current
70
- * account-log update key is a rung derivable from this ladder seed, so the
71
- * entry could not be signed.
81
+ * `'update-key-not-attributable'`: a pointer entry is needed, but the account
82
+ * log carries no rung of this ladder at all -- no revealed key and no
83
+ * committed hash -- or the attribution is ambiguous, so the entry could not
84
+ * be signed. A merely committed rung is not this state: the pointer move
85
+ * reveals it first.
72
86
  */
73
87
  export type ClientAnnexGenerationUnavailableReason = 'ladder-vm-not-anchored' | 'update-key-not-attributable';
74
88
  /**
@@ -121,6 +135,11 @@ export declare function ladderSignedGenerationDelegationMinter({ accountDid, lad
121
135
  export interface ClientAnnexGenerationEnsureOutcome {
122
136
  clientAnnexDid: string;
123
137
  generationDelegation: IZcap;
138
+ /**
139
+ * The usable bridge delegation -- the record's own, or the fresh one
140
+ * `onRebindRecord` was handed.
141
+ */
142
+ delegation: IZcap;
124
143
  /**
125
144
  * The usable sibling delegation -- the record's own, or the fresh one
126
145
  * `onRebindRecord` was handed.
@@ -130,6 +149,13 @@ export interface ClientAnnexGenerationEnsureOutcome {
130
149
  spaceMinted: boolean;
131
150
  delegationRenewed: boolean;
132
151
  siblingReminted: boolean;
152
+ bridgeReminted: boolean;
153
+ /**
154
+ * Set when the re-seal of a renewed bridge failed and nothing else needed
155
+ * the re-seal; the fresh bridge still served this visit, and the next
156
+ * visit re-mints.
157
+ */
158
+ bridgeResealError?: unknown;
133
159
  }
134
160
  /**
135
161
  * Ensures a transient visit can reach a live client-annex generation with a
@@ -161,13 +187,18 @@ export interface ClientAnnexGenerationEnsureOutcome {
161
187
  * -- the storage client for the fresh-Space arm, signing as the ladder
162
188
  * VM's bare did:key (the caller wires the transport; the agent is derived
163
189
  * here from the ladder seed)
164
- * @param options.idStore {WebvhIdStore} the ACCOUNT log's store (a
165
- * bridge-delegated one suffices: pointer entries publish with
166
- * `logOnly: true`)
190
+ * @param options.delegation {IZcap} the record's bridge delegation (PUT on
191
+ * the account's `did.jsonl`), renewed here when it is stale
192
+ * @param options.idStoreFor {Function}
193
+ * `({ delegation }) => WebvhIdStore` -- builds the ACCOUNT log's store over
194
+ * the usable bridge (a bridge-delegated store suffices: pointer entries
195
+ * publish with `logOnly: true`). Called once, after the bridge renewal, so
196
+ * a pointer entry never rides a lapsed delegation
167
197
  * @param options.onRebindRecord {Function}
168
- * `({ delegatedClients }) => Promise<void>` -- REQUIRED: re-seals the
169
- * unlock record with the fresh sibling delegation; called whenever one was
170
- * minted, after the generation and pointer are durable
198
+ * `({ delegation, delegatedClients }) => Promise<void>` -- REQUIRED:
199
+ * re-seals the unlock record with the usable bridge and sibling
200
+ * delegations; called whenever either was freshly minted, after the
201
+ * generation and pointer are durable
171
202
  * @param [options.delegatedClients] {IZcap} the record's sibling
172
203
  * delegation, when the record carries one
173
204
  * @param [options.pinStore] {ResourceLogPinStore} chain-head pins (a
@@ -188,8 +219,12 @@ export declare function ensureCredentialClientAnnexGeneration(options: {
188
219
  bootstrapWasFor: (options: {
189
220
  keyAgent: ICapabilityAgent;
190
221
  }) => WasClient;
191
- idStore: WebvhIdStore;
222
+ delegation: IZcap;
223
+ idStoreFor: (options: {
224
+ delegation: IZcap;
225
+ }) => WebvhIdStore;
192
226
  onRebindRecord: (options: {
227
+ delegation: IZcap;
193
228
  delegatedClients: IZcap;
194
229
  }) => Promise<void>;
195
230
  delegatedClients?: IZcap;
@@ -1 +1 @@
1
- {"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/heal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/heal.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,14 @@
1
1
  import { WasClient } from '@interop/was-client';
2
- import { effectiveParameters, readPublishedLog } from '../webvh/didWebvh.js';
2
+ import { effectiveParameters, readPublishedLog, WebvhLogConflictError, withLogConflictRetry } from '../webvh/didWebvh.js';
3
3
  import { delegationKeyInDocument, ladderVmIds } from '../webvh/listClients.js';
4
4
  import { delegationProofKeyId, zcapExpiring } from '../webvh/standingZcap.js';
5
+ import { delegateLogWrite } from '../recovery/recoveryDelegation.js';
5
6
  import { accountLogPinId } from '../webvh/verifyLog.js';
6
7
  import { mintSpaceId } from '../genesis/accountGenesis.js';
7
8
  import { attributeLadderRung, ladderRung, ladderVmKeyMultibase } from './ladder.js';
9
+ import { revealLadderRungWebvh } from './ladderAnchored.js';
8
10
  import { ladderVmAgent, ladderVmZcapClient } from './zcap.js';
9
- import { clientAnnexDidParts, clientAnnexLogPinId, clientAnnexLogStore, delegatedClientsDelegationSpaceId, delegatedClientsPointer, ensureGenerationDelegationCurrent, mintCredentialClientAnnexGeneration, mintDelegatedClientsDelegation, mintGenerationDelegation, setDelegatedClientsPointer } from './log.js';
11
+ import { clientAnnexDidParts, clientAnnexLogPinId, clientAnnexLogStore, delegatedClientsDelegationSpaceId, delegatedClientsPointer, ensureGenerationDelegationCurrent, mintCredentialClientAnnexGeneration, mintDelegatedClientsDelegation, mintGenerationDelegation, setDelegatedClientsPointerOnce } from './log.js';
10
12
  /**
11
13
  * The typed refusal of {@link ensureCredentialClientAnnexGeneration}: the
12
14
  * account is not in a shape this visit can mend, and nothing was written.
@@ -81,13 +83,18 @@ export function ladderSignedGenerationDelegationMinter({ accountDid, ladderSeed,
81
83
  * -- the storage client for the fresh-Space arm, signing as the ladder
82
84
  * VM's bare did:key (the caller wires the transport; the agent is derived
83
85
  * here from the ladder seed)
84
- * @param options.idStore {WebvhIdStore} the ACCOUNT log's store (a
85
- * bridge-delegated one suffices: pointer entries publish with
86
- * `logOnly: true`)
86
+ * @param options.delegation {IZcap} the record's bridge delegation (PUT on
87
+ * the account's `did.jsonl`), renewed here when it is stale
88
+ * @param options.idStoreFor {Function}
89
+ * `({ delegation }) => WebvhIdStore` -- builds the ACCOUNT log's store over
90
+ * the usable bridge (a bridge-delegated store suffices: pointer entries
91
+ * publish with `logOnly: true`). Called once, after the bridge renewal, so
92
+ * a pointer entry never rides a lapsed delegation
87
93
  * @param options.onRebindRecord {Function}
88
- * `({ delegatedClients }) => Promise<void>` -- REQUIRED: re-seals the
89
- * unlock record with the fresh sibling delegation; called whenever one was
90
- * minted, after the generation and pointer are durable
94
+ * `({ delegation, delegatedClients }) => Promise<void>` -- REQUIRED:
95
+ * re-seals the unlock record with the usable bridge and sibling
96
+ * delegations; called whenever either was freshly minted, after the
97
+ * generation and pointer are durable
91
98
  * @param [options.delegatedClients] {IZcap} the record's sibling
92
99
  * delegation, when the record carries one
93
100
  * @param [options.pinStore] {ResourceLogPinStore} chain-head pins (a
@@ -101,7 +108,8 @@ export function ensureCredentialClientAnnexGeneration(options) {
101
108
  // into the record would strand the very credential this ensure serves.
102
109
  if (typeof options.onRebindRecord !== 'function') {
103
110
  throw new TypeError('ensureCredentialClientAnnexGeneration requires onRebindRecord: a ' +
104
- 'fresh sibling delegation must be re-sealed into the unlock record.');
111
+ 'fresh bridge or sibling delegation must be re-sealed into the ' +
112
+ 'unlock record.');
105
113
  }
106
114
  return ensureCredentialClientAnnexGenerationChecked(options);
107
115
  }
@@ -111,14 +119,17 @@ export function ensureCredentialClientAnnexGeneration(options) {
111
119
  * @param options {object} see {@link ensureCredentialClientAnnexGeneration}
112
120
  * @returns {Promise<ClientAnnexGenerationEnsureOutcome>}
113
121
  */
114
- async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spaceId, account, ladderSeed, standingClient, bootstrapWasFor, idStore, onRebindRecord, delegatedClients, pinStore, now }) {
122
+ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spaceId, account, ladderSeed, standingClient, bootstrapWasFor, delegation, idStoreFor, onRebindRecord, delegatedClients, pinStore, now }) {
115
123
  // The gate: everything below signs as the ladder (the delegations as the
116
124
  // ladder VM, the annex entries as its per-generation rung), so unless THIS
117
125
  // ladder's VM stands in the document under the ladder-VM relation
118
126
  // asymmetry (`capabilityDelegation` without `capabilityInvocation` -- the
119
127
  // authority the mends actually exercise, which mere key presence says
120
128
  // nothing about), every mend is unverifiable. The honest refusal, before
121
- // anything is written.
129
+ // anything is written. A standing credential's VM stands whether or not the
130
+ // account has enrolled clients, so this fires only for a document that
131
+ // never carried it -- a torn establishment, or another credential's
132
+ // account.
122
133
  const vmKey = await ladderVmKeyMultibase({ ladderSeed });
123
134
  if (!ladderVmIds({ doc: account.doc }).includes(`${account.did}#${vmKey}`)) {
124
135
  throw new ClientAnnexGenerationUnavailableError({
@@ -144,14 +155,70 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
144
155
  spaceId,
145
156
  ...(now !== undefined ? { now } : {})
146
157
  });
158
+ // THE BRIDGE RENEWAL, before any arm. The bridge is the credential's one
159
+ // write path into the account log, and both minting arms end in a pointer
160
+ // entry that rides it. A stale one is replaced with a ladder-VM-signed
161
+ // delegation (the gate above proved the VM a document verification
162
+ // method), and the caller's account-log store is built over whichever
163
+ // bridge is usable.
164
+ let bridgeReminted = false;
165
+ let usableBridge = delegation;
166
+ if (standingZcapStale({
167
+ zcap: delegation,
168
+ doc: account.doc,
169
+ ...(now !== undefined ? { now } : {})
170
+ })) {
171
+ usableBridge = await delegateLogWrite({
172
+ zcapClient: ladderClient,
173
+ pointer: { did: account.did, spaceId, host: wasServerUrl },
174
+ recoveryClientDid: standingClient.did,
175
+ ...(now !== undefined ? { now } : {})
176
+ });
177
+ bridgeReminted = true;
178
+ }
179
+ const idStore = idStoreFor({ delegation: usableBridge });
180
+ /**
181
+ * The record re-seal, through the required `onRebindRecord` seam: the one
182
+ * call site for every arm, run once the generation and pointer are
183
+ * durable. It fires whenever either recorded delegation was freshly
184
+ * minted, and grades a failure by which one that was. A fresh sibling
185
+ * nothing re-seals would strand the credential, so that throw propagates.
186
+ * A bridge-only renewal needs nothing from the re-seal: the fresh bridge
187
+ * is minted offline and already served this visit, so a lost re-seal
188
+ * leaves no wrong state behind and the next visit re-mints. It is reported
189
+ * on the outcome instead.
190
+ *
191
+ * @param options {object}
192
+ * @param options.delegatedClients {IZcap} the usable sibling delegation
193
+ * @param options.siblingReminted {boolean} whether that sibling is fresh
194
+ * @returns {Promise<object>} the outcome's `bridgeResealError` member,
195
+ * present only when a bridge-only re-seal failed
196
+ */
197
+ async function resealRecord({ delegatedClients: usableSibling, siblingReminted }) {
198
+ if (!siblingReminted && !bridgeReminted) {
199
+ return {};
200
+ }
201
+ try {
202
+ await onRebindRecord({
203
+ delegation: usableBridge,
204
+ delegatedClients: usableSibling
205
+ });
206
+ }
207
+ catch (err) {
208
+ if (siblingReminted) {
209
+ throw err;
210
+ }
211
+ return { bridgeResealError: err };
212
+ }
213
+ return {};
214
+ }
147
215
  if (annexSpaceId === undefined) {
148
216
  // THE FRESH-SPACE ARM: neither the pointer nor a sibling names a Space.
149
- // The pre-flight attribution runs before anything is minted; the stage
150
- // order mirrors the credential-anchored genesis exactly.
151
- const updateKeys = await pointerEntryUpdateKeys({
152
- ladderSeed,
153
- log: account.log
154
- });
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 });
155
222
  const freshSpaceId = mintSpaceId();
156
223
  const keyAgent = await ladderVmAgent({ ladderSeed });
157
224
  const bootstrapWas = bootstrapWasFor({ keyAgent });
@@ -188,12 +255,11 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
188
255
  await bootstrapWas
189
256
  .space(freshSpaceId)
190
257
  .configure({ controller: account.did, force: true });
191
- await setDelegatedClientsPointer({
258
+ await movePointerAsLadder({
192
259
  idStore,
193
- updateKeys,
260
+ ladderSeed,
194
261
  clientAnnexDid: minted.did,
195
- expectedDid: account.did,
196
- logOnly: true,
262
+ accountDid: account.did,
197
263
  ...(pinStore !== undefined
198
264
  ? { pinStore, logId: accountLogPinId({ spaceId }) }
199
265
  : {})
@@ -205,15 +271,21 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
205
271
  controller: standingClient.did,
206
272
  ...(now !== undefined ? { now } : {})
207
273
  });
208
- await onRebindRecord({ delegatedClients: sibling });
274
+ const resealed = await resealRecord({
275
+ delegatedClients: sibling,
276
+ siblingReminted: true
277
+ });
209
278
  return {
210
279
  clientAnnexDid: minted.did,
211
280
  generationDelegation: ensured.delegation,
281
+ delegation: usableBridge,
212
282
  delegatedClients: sibling,
213
283
  generationMinted: true,
214
284
  spaceMinted: true,
215
285
  delegationRenewed: false,
216
- siblingReminted: true
286
+ siblingReminted: true,
287
+ bridgeReminted,
288
+ ...resealed
217
289
  };
218
290
  }
219
291
  // THE EXISTING-SPACE ARMS. A usable sibling first: absent, targeting a
@@ -227,18 +299,11 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
227
299
  let sibling = delegatedClients;
228
300
  let siblingReminted = false;
229
301
  const siblingStale = sibling !== undefined &&
230
- (zcapExpiring({
231
- ...(sibling.expires !== undefined
232
- ? { expires: sibling.expires }
233
- : {}),
302
+ standingZcapStale({
303
+ zcap: sibling,
304
+ doc: account.doc,
234
305
  ...(now !== undefined ? { now } : {})
235
- }) ||
236
- !delegationKeyInDocument({
237
- doc: account.doc,
238
- ...(delegationProofKeyId(sibling) !== undefined
239
- ? { delegationKeyId: delegationProofKeyId(sibling) }
240
- : {})
241
- }));
306
+ });
242
307
  if (sibling === undefined ||
243
308
  siblingSpaceId !== annexSpaceId ||
244
309
  siblingStale) {
@@ -290,17 +355,21 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
290
355
  ...annexPin(parts.generationId),
291
356
  ...(now !== undefined ? { now } : {})
292
357
  });
293
- if (siblingReminted) {
294
- await onRebindRecord({ delegatedClients: usableSibling });
295
- }
358
+ const resealed = await resealRecord({
359
+ delegatedClients: usableSibling,
360
+ siblingReminted
361
+ });
296
362
  return {
297
363
  clientAnnexDid: pointer,
298
364
  generationDelegation: ensured.delegation,
365
+ delegation: usableBridge,
299
366
  delegatedClients: usableSibling,
300
367
  generationMinted: false,
301
368
  spaceMinted: false,
302
369
  delegationRenewed: ensured.renewed,
303
- siblingReminted
370
+ siblingReminted,
371
+ bridgeReminted,
372
+ ...resealed
304
373
  };
305
374
  }
306
375
  catch (err) {
@@ -320,10 +389,7 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
320
389
  // rung; other standing credentials' per-generation rungs are re-committed
321
390
  // only by their own later ceremonies (a property of every generation
322
391
  // swap).
323
- const updateKeys = await pointerEntryUpdateKeys({
324
- ladderSeed,
325
- log: account.log
326
- });
392
+ await assertPointerEntryAttributable({ ladderSeed, log: account.log });
327
393
  const minted = await mintCredentialClientAnnexGeneration({
328
394
  was: standingWas,
329
395
  wasServerUrl,
@@ -347,29 +413,59 @@ async function ensureCredentialClientAnnexGenerationChecked({ wasServerUrl, spac
347
413
  // pointer move itself retires it on a conforming server -- the inspector
348
414
  // clause compares the delegation's controller against the document's
349
415
  // pointer -- and it otherwise rots on its TTL.
350
- await setDelegatedClientsPointer({
416
+ await movePointerAsLadder({
351
417
  idStore,
352
- updateKeys,
418
+ ladderSeed,
353
419
  clientAnnexDid: minted.did,
354
- expectedDid: account.did,
355
- logOnly: true,
420
+ accountDid: account.did,
356
421
  ...(pinStore !== undefined
357
422
  ? { pinStore, logId: accountLogPinId({ spaceId }) }
358
423
  : {})
359
424
  });
360
- if (siblingReminted) {
361
- await onRebindRecord({ delegatedClients: usableSibling });
362
- }
425
+ const resealed = await resealRecord({
426
+ delegatedClients: usableSibling,
427
+ siblingReminted
428
+ });
363
429
  return {
364
430
  clientAnnexDid: minted.did,
365
431
  generationDelegation: ensured.delegation,
432
+ delegation: usableBridge,
366
433
  delegatedClients: usableSibling,
367
434
  generationMinted: true,
368
435
  spaceMinted: false,
369
436
  delegationRenewed: false,
370
- siblingReminted
437
+ siblingReminted,
438
+ bridgeReminted,
439
+ ...resealed
371
440
  };
372
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
+ }
373
469
  /**
374
470
  * The annex Space, in the settled resolution order: the account document's
375
471
  * `#DelegatedClients` pointer names it; else the record's sibling
@@ -446,4 +542,145 @@ export async function pointerEntryUpdateKeys({ ladderSeed, log }) {
446
542
  });
447
543
  return { updateSeed: attributed.rung.seed, stagedSeed: staged.seed };
448
544
  }
545
+ /**
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.
553
+ *
554
+ * @param options {object}
555
+ * @param options.ladderSeed {Uint8Array}
556
+ * @param options.log {DIDLog} the VERIFIED account log
557
+ * @returns {Promise<void>}
558
+ */
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;
578
+ }
579
+ }
580
+ /**
581
+ * The `#DelegatedClients` pointer move as a credential-only visit makes it:
582
+ * reveal this ladder's rung when only its hash stands committed, re-read, and
583
+ * write the pointer entry signed by the now-revealed rung.
584
+ *
585
+ * A self-enrollment's add entry spends the revealed rung, so on any account
586
+ * that has ever self-enrolled the rung is merely committed and the reveal is
587
+ * what makes the pointer entry signable at all.
588
+ *
589
+ * ACCEPTED CONSEQUENCE (design FW-356, finding R3): the reveal retires
590
+ * nothing, and the pointer entry re-states `updateKeys` verbatim, so the
591
+ * acting rung stands in the account log's `updateKeys` afterwards. The price
592
+ * of a pointer move is therefore a standing account update key in the
593
+ * credential's hand -- direct document-edit authority through the bridge with
594
+ * no further reveal -- retired at that credential's next self-enrollment
595
+ * (whose add entry drops the attributed rung) or at its retirement. This is
596
+ * documented rather than prevented.
597
+ *
598
+ * Both entries run inside ONE conflict retry, and every attempt re-reads the
599
+ * head and re-attributes the rung from it, so a racing ceremony that consumes
600
+ * the rung climbs to the winner's committed rung instead of refusing
601
+ * `update-key-not-attributable` on a rung that is no longer current.
602
+ *
603
+ * Three things make that hold. A rung the winner consumed between this
604
+ * attempt's reveal and its re-read reads back as
605
+ * `update-key-not-attributable`, which inside this loop is staleness rather
606
+ * than a refusal -- the pre-flight already found a rung -- so it is raised as
607
+ * a conflict and the next attempt reveals the winner's committed rung. The pointer entry runs as
608
+ * {@link setDelegatedClientsPointerOnce} rather than through its retrying
609
+ * wrapper: the wrapper's inner loop would re-invoke the attempt with the
610
+ * attribution's stale `updateKeys`, and a rung the racing winner consumed
611
+ * cannot become authorized by re-reading, so the attempt would end on the
612
+ * plain not-authorized refusal, which the outer loop does not retry. And the
613
+ * attempt is handed the very head this attempt attributed against, so a
614
+ * racing entry landing between the attribution and the PUT loses the CAS and
615
+ * surfaces as a `WebvhLogConflictError` -- the refusal the outer loop
616
+ * re-attributes from. The pre-flight guard
617
+ * ({@link assertPointerEntryAttributable}) therefore cannot fire from
618
+ * staleness here: it runs on the caller's snapshot before anything is minted,
619
+ * while every entry this function publishes is built on a head it read
620
+ * itself.
621
+ *
622
+ * @param options {object}
623
+ * @param options.idStore {WebvhIdStore} the account log's store, from the
624
+ * record's bridge delegation
625
+ * @param options.ladderSeed {Uint8Array} the credential's ladder seed
626
+ * @param options.clientAnnexDid {string} the generation to point at
627
+ * @param options.accountDid {string} the account DID the log must resolve to
628
+ * @param [options.pinStore] {ResourceLogPinStore} the visit's chain-head pins
629
+ * @param [options.logId] {string} the account log's pin slot; required
630
+ * whenever a `pinStore` is supplied
631
+ * @returns {Promise<void>}
632
+ */
633
+ async function movePointerAsLadder({ idStore, ladderSeed, clientAnnexDid, accountDid, pinStore, logId }) {
634
+ const pin = pinStore !== undefined && logId !== undefined ? { pinStore, logId } : {};
635
+ await withLogConflictRetry(async () => {
636
+ await revealLadderRungWebvh({
637
+ store: idStore,
638
+ ladderSeed,
639
+ expectedDid: accountDid,
640
+ ...pin
641
+ });
642
+ // The head the reveal entry just published (or the unchanged head, when
643
+ // the rung was revealed already), under the same pin.
644
+ const published = await readPublishedLog({
645
+ idStore,
646
+ expectedDid: accountDid,
647
+ ...pin
648
+ });
649
+ if (published === undefined) {
650
+ throw new Error('did:webvh: did.jsonl is missing; nothing to point at a client annex.');
651
+ }
652
+ // A racing ceremony that consumed the rung between this reveal and this
653
+ // read leaves the ladder committed-only again, which the attribution
654
+ // reports as `update-key-not-attributable`. Inside this loop that is a
655
+ // staleness signal rather than a refusal -- the pre-flight already found
656
+ // a rung, and a fresh reveal is exactly what the next attempt does -- so
657
+ // it becomes a conflict for the retry to re-run.
658
+ let updateKeys;
659
+ try {
660
+ updateKeys = await pointerEntryUpdateKeys({
661
+ ladderSeed,
662
+ log: published.log
663
+ });
664
+ }
665
+ catch (err) {
666
+ if (err.name ===
667
+ 'ClientAnnexGenerationUnavailableError' &&
668
+ err.reason ===
669
+ 'update-key-not-attributable') {
670
+ throw new WebvhLogConflictError('did:webvh: a concurrent ceremony consumed the rung this pointer ' +
671
+ 'move just revealed; the move re-runs from a fresh reveal.', { cause: err });
672
+ }
673
+ throw err;
674
+ }
675
+ await setDelegatedClientsPointerOnce({
676
+ idStore,
677
+ updateKeys,
678
+ clientAnnexDid,
679
+ expectedDid: accountDid,
680
+ logOnly: true,
681
+ published,
682
+ ...pin
683
+ });
684
+ });
685
+ }
449
686
  //# sourceMappingURL=heal.js.map