@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.
- package/README.md +12 -8
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +6 -10
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.js +34 -56
- package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
- package/dist/clientAnnex/establish.d.ts +46 -29
- package/dist/clientAnnex/establish.d.ts.map +1 -1
- package/dist/clientAnnex/establish.js +111 -86
- package/dist/clientAnnex/establish.js.map +1 -1
- package/dist/clientAnnex/forget.d.ts +7 -16
- package/dist/clientAnnex/forget.d.ts.map +1 -1
- package/dist/clientAnnex/forget.js +13 -24
- package/dist/clientAnnex/forget.js.map +1 -1
- package/dist/clientAnnex/forgetLast.d.ts +33 -129
- package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
- package/dist/clientAnnex/forgetLast.js +43 -182
- package/dist/clientAnnex/forgetLast.js.map +1 -1
- package/dist/clientAnnex/gc.d.ts +26 -12
- package/dist/clientAnnex/gc.d.ts.map +1 -1
- package/dist/clientAnnex/gc.js +60 -57
- package/dist/clientAnnex/gc.js.map +1 -1
- package/dist/clientAnnex/heal.d.ts +75 -18
- package/dist/clientAnnex/heal.d.ts.map +1 -1
- package/dist/clientAnnex/heal.js +79 -147
- package/dist/clientAnnex/heal.js.map +1 -1
- package/dist/clientAnnex/index.d.ts +8 -8
- package/dist/clientAnnex/index.d.ts.map +1 -1
- package/dist/clientAnnex/index.js +5 -5
- package/dist/clientAnnex/index.js.map +1 -1
- package/dist/clientAnnex/ladder.d.ts +51 -4
- package/dist/clientAnnex/ladder.d.ts.map +1 -1
- package/dist/clientAnnex/ladder.js +283 -47
- package/dist/clientAnnex/ladder.js.map +1 -1
- package/dist/clientAnnex/ladderAnchored.d.ts +62 -73
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/ladderAnchored.js +103 -117
- package/dist/clientAnnex/ladderAnchored.js.map +1 -1
- package/dist/clientAnnex/log.d.ts +123 -125
- package/dist/clientAnnex/log.d.ts.map +1 -1
- package/dist/clientAnnex/log.js +174 -233
- package/dist/clientAnnex/log.js.map +1 -1
- package/dist/clientAnnex/mend.d.ts +0 -4
- package/dist/clientAnnex/mend.d.ts.map +1 -1
- package/dist/clientAnnex/mend.js +50 -51
- package/dist/clientAnnex/mend.js.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +25 -13
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.js +80 -303
- package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +13 -5
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.js +18 -9
- package/dist/clientAnnex/rosterDeliveredEpochs.js.map +1 -1
- package/dist/clientAnnex/selfEnroll.d.ts +6 -10
- package/dist/clientAnnex/selfEnroll.d.ts.map +1 -1
- package/dist/clientAnnex/selfEnroll.js +13 -18
- package/dist/clientAnnex/selfEnroll.js.map +1 -1
- package/dist/clientAnnex/zcap.d.ts +19 -0
- package/dist/clientAnnex/zcap.d.ts.map +1 -1
- package/dist/clientAnnex/zcap.js +80 -12
- package/dist/clientAnnex/zcap.js.map +1 -1
- package/dist/clients/index.d.ts +3 -2
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +3 -2
- package/dist/clients/index.js.map +1 -1
- package/dist/clients/listing.d.ts.map +1 -1
- package/dist/clients/listing.js +33 -15
- package/dist/clients/listing.js.map +1 -1
- package/dist/clients/policy.d.ts +18 -0
- package/dist/clients/policy.d.ts.map +1 -1
- package/dist/clients/policy.js +22 -8
- package/dist/clients/policy.js.map +1 -1
- package/dist/clients/revocation.d.ts +18 -30
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +12 -27
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +6 -1
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +27 -30
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/descriptors/errors.d.ts +6 -5
- package/dist/descriptors/errors.d.ts.map +1 -1
- package/dist/descriptors/errors.js +6 -5
- package/dist/descriptors/errors.js.map +1 -1
- package/dist/descriptors/index.d.ts +7 -3
- package/dist/descriptors/index.d.ts.map +1 -1
- package/dist/descriptors/index.js +7 -3
- package/dist/descriptors/index.js.map +1 -1
- package/dist/descriptors/logSource.d.ts +28 -6
- package/dist/descriptors/logSource.d.ts.map +1 -1
- package/dist/descriptors/logSource.js +33 -7
- package/dist/descriptors/logSource.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +3 -7
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/genesis/accountGenesis.d.ts +11 -16
- package/dist/genesis/accountGenesis.d.ts.map +1 -1
- package/dist/genesis/accountGenesis.js +43 -47
- package/dist/genesis/accountGenesis.js.map +1 -1
- package/dist/genesis/kmsAuthentication.d.ts +50 -0
- package/dist/genesis/kmsAuthentication.d.ts.map +1 -0
- package/dist/genesis/kmsAuthentication.js +49 -0
- package/dist/genesis/kmsAuthentication.js.map +1 -0
- package/dist/keyring/kdf.d.ts +16 -20
- package/dist/keyring/kdf.d.ts.map +1 -1
- package/dist/keyring/kdf.js +2 -2
- package/dist/keyring/kdf.js.map +1 -1
- package/dist/keyring/unlockSpace.d.ts +8 -30
- package/dist/keyring/unlockSpace.d.ts.map +1 -1
- package/dist/keyring/unlockSpace.js +8 -31
- package/dist/keyring/unlockSpace.js.map +1 -1
- package/dist/keys/clientKeyRecord.d.ts +2 -1
- package/dist/keys/clientKeyRecord.d.ts.map +1 -1
- package/dist/keys/clientKeyRecord.js +28 -11
- package/dist/keys/clientKeyRecord.js.map +1 -1
- package/dist/keys/index.d.ts +6 -2
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +5 -1
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterLogStore.d.ts.map +1 -1
- package/dist/keys/rosterLogStore.js +14 -5
- package/dist/keys/rosterLogStore.js.map +1 -1
- package/dist/keys/spaceEpochs.d.ts +92 -3
- package/dist/keys/spaceEpochs.d.ts.map +1 -1
- package/dist/keys/spaceEpochs.js +110 -4
- package/dist/keys/spaceEpochs.js.map +1 -1
- package/dist/keys/userKeyRoster.d.ts +30 -3
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +90 -15
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
- package/dist/keys/userKeyRosterCascade.js +5 -1
- package/dist/keys/userKeyRosterCascade.js.map +1 -1
- package/dist/recovery/continuation.d.ts +250 -0
- package/dist/recovery/continuation.d.ts.map +1 -0
- package/dist/recovery/continuation.js +467 -0
- package/dist/recovery/continuation.js.map +1 -0
- package/dist/recovery/index.d.ts +12 -8
- package/dist/recovery/index.d.ts.map +1 -1
- package/dist/recovery/index.js +11 -7
- package/dist/recovery/index.js.map +1 -1
- package/dist/recovery/recoveryDelegation.d.ts +23 -126
- package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
- package/dist/recovery/recoveryDelegation.js +1 -266
- package/dist/recovery/recoveryDelegation.js.map +1 -1
- package/dist/recovery/recoveryWebvh.d.ts +52 -107
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.js +54 -403
- package/dist/recovery/recoveryWebvh.js.map +1 -1
- package/dist/request/classify.d.ts +3 -14
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +19 -40
- package/dist/request/classify.js.map +1 -1
- package/dist/request/index.d.ts +1 -0
- package/dist/request/index.d.ts.map +1 -1
- package/dist/request/index.js +1 -0
- package/dist/request/index.js.map +1 -1
- package/dist/request/onboarding.d.ts.map +1 -1
- package/dist/request/onboarding.js +19 -27
- package/dist/request/onboarding.js.map +1 -1
- package/dist/request/parse.d.ts +5 -3
- package/dist/request/parse.d.ts.map +1 -1
- package/dist/request/parse.js +7 -6
- package/dist/request/parse.js.map +1 -1
- package/dist/request/processRequest.d.ts.map +1 -1
- package/dist/request/processRequest.js +2 -1
- package/dist/request/processRequest.js.map +1 -1
- package/dist/request/queryPredicates.d.ts +98 -0
- package/dist/request/queryPredicates.d.ts.map +1 -0
- package/dist/request/queryPredicates.js +107 -0
- package/dist/request/queryPredicates.js.map +1 -0
- package/dist/resourceLog/document.d.ts +39 -0
- package/dist/resourceLog/document.d.ts.map +1 -1
- package/dist/resourceLog/document.js +41 -0
- package/dist/resourceLog/document.js.map +1 -1
- package/dist/resourceLog/index.d.ts +2 -2
- package/dist/resourceLog/index.js +2 -2
- package/dist/resourceLog/ladderRungs.d.ts.map +1 -1
- package/dist/resourceLog/ladderRungs.js +3 -2
- package/dist/resourceLog/ladderRungs.js.map +1 -1
- package/dist/sync/contactsConflict.d.ts.map +1 -1
- package/dist/sync/contactsConflict.js +8 -2
- package/dist/sync/contactsConflict.js.map +1 -1
- package/dist/sync/engine.d.ts +38 -23
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +36 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/index.d.ts +9 -12
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +8 -11
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +1 -2
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/remint.d.ts +0 -31
- package/dist/sync/remint.d.ts.map +1 -1
- package/dist/sync/remint.js +32 -1
- package/dist/sync/remint.js.map +1 -1
- package/dist/sync/types.d.ts +4 -41
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/sync/types.js +4 -47
- package/dist/sync/types.js.map +1 -1
- package/dist/unlock/index.d.ts +1 -1
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/index.js +1 -1
- package/dist/unlock/index.js.map +1 -1
- package/dist/unlock/retire.d.ts +16 -64
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js +7 -86
- package/dist/unlock/retire.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +27 -61
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +40 -92
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/unlock/unlockRecord.d.ts.map +1 -1
- package/dist/unlock/unlockRecord.js +69 -44
- package/dist/unlock/unlockRecord.js.map +1 -1
- package/dist/webvh/accountEntry.d.ts +68 -19
- package/dist/webvh/accountEntry.d.ts.map +1 -1
- package/dist/webvh/accountEntry.js +117 -37
- package/dist/webvh/accountEntry.js.map +1 -1
- package/dist/webvh/delegatedLogStore.d.ts +24 -13
- package/dist/webvh/delegatedLogStore.d.ts.map +1 -1
- package/dist/webvh/delegatedLogStore.js +40 -11
- package/dist/webvh/delegatedLogStore.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +91 -86
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +117 -142
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/enrollClient.d.ts +2 -8
- package/dist/webvh/enrollClient.d.ts.map +1 -1
- package/dist/webvh/enrollClient.js +22 -31
- package/dist/webvh/enrollClient.js.map +1 -1
- package/dist/webvh/index.d.ts +12 -8
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +10 -7
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +102 -65
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/mergeMethods.d.ts +84 -0
- package/dist/webvh/mergeMethods.d.ts.map +1 -0
- package/dist/webvh/mergeMethods.js +46 -0
- package/dist/webvh/mergeMethods.js.map +1 -0
- package/dist/webvh/revokeClient.d.ts +15 -11
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +130 -57
- package/dist/webvh/revokeClient.js.map +1 -1
- package/dist/webvh/verifyLog.d.ts +45 -4
- package/dist/webvh/verifyLog.d.ts.map +1 -1
- package/dist/webvh/verifyLog.js +62 -21
- package/dist/webvh/verifyLog.js.map +1 -1
- package/dist/webvh/wasIdStore.d.ts +16 -3
- package/dist/webvh/wasIdStore.d.ts.map +1 -1
- package/dist/webvh/wasIdStore.js +18 -3
- package/dist/webvh/wasIdStore.js.map +1 -1
- package/package.json +11 -11
package/dist/clientAnnex/log.js
CHANGED
|
@@ -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 {
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
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
|
|
628
|
-
*
|
|
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
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
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,
|
|
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
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1308
|
-
*
|
|
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
|
|
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
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
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
|
-
*
|
|
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
|
|
1338
|
-
*
|
|
1339
|
-
*
|
|
1340
|
-
*
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
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
|
|
1355
|
-
* leaves standing: the post-entry one, paired with its
|
|
1356
|
-
* when the entry was appended; the head it stood on
|
|
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
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
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
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
*
|
|
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<
|
|
1400
|
-
* published: PublishedWebvhLog }>}
|
|
1381
|
+
* @returns {Promise<PointerEntryOutcome>}
|
|
1401
1382
|
*/
|
|
1402
|
-
export async function setDelegatedClientsPointerOnce({ idStore, signer, clientAnnexDid, expectedDid,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
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`):
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
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,
|
|
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
|
-
*
|
|
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
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
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,
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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,
|