@interop/wallet-core 0.49.0 → 0.51.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 +5 -2
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +127 -0
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -0
- package/dist/clientAnnex/credentialAnchoredGenesis.js +195 -0
- package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -0
- package/dist/clientAnnex/forget.d.ts +138 -0
- package/dist/clientAnnex/forget.d.ts.map +1 -0
- package/dist/clientAnnex/forget.js +133 -0
- package/dist/clientAnnex/forget.js.map +1 -0
- package/dist/clientAnnex/forgetLast.d.ts +291 -0
- package/dist/clientAnnex/forgetLast.d.ts.map +1 -0
- package/dist/clientAnnex/forgetLast.js +408 -0
- package/dist/clientAnnex/forgetLast.js.map +1 -0
- package/dist/{webvh/companionGc.d.ts → clientAnnex/gc.d.ts} +50 -16
- package/dist/clientAnnex/gc.d.ts.map +1 -0
- package/dist/{webvh/companionGc.js → clientAnnex/gc.js} +103 -71
- package/dist/clientAnnex/gc.js.map +1 -0
- package/dist/clientAnnex/index.d.ts +60 -0
- package/dist/clientAnnex/index.d.ts.map +1 -0
- package/dist/clientAnnex/index.js +60 -0
- package/dist/clientAnnex/index.js.map +1 -0
- package/dist/{unlock → clientAnnex}/ladder.d.ts +89 -15
- package/dist/clientAnnex/ladder.d.ts.map +1 -0
- package/dist/clientAnnex/ladder.js +474 -0
- package/dist/clientAnnex/ladder.js.map +1 -0
- package/dist/clientAnnex/ladderAnchored.d.ts +276 -0
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -0
- package/dist/clientAnnex/ladderAnchored.js +631 -0
- package/dist/clientAnnex/ladderAnchored.js.map +1 -0
- package/dist/{webvh/companion.d.ts → clientAnnex/log.d.ts} +333 -119
- package/dist/clientAnnex/log.d.ts.map +1 -0
- package/dist/{webvh/companion.js → clientAnnex/log.js} +583 -199
- package/dist/clientAnnex/log.js.map +1 -0
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +103 -0
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -0
- package/dist/clientAnnex/recoveryLadderAnchored.js +263 -0
- package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -0
- package/dist/{unlock → clientAnnex}/selfEnroll.d.ts +1 -1
- package/dist/clientAnnex/selfEnroll.d.ts.map +1 -0
- package/dist/{unlock → clientAnnex}/selfEnroll.js +1 -1
- package/dist/clientAnnex/selfEnroll.js.map +1 -0
- package/dist/clientAnnex/zcap.d.ts +49 -0
- package/dist/clientAnnex/zcap.d.ts.map +1 -0
- package/dist/clientAnnex/zcap.js +101 -0
- package/dist/clientAnnex/zcap.js.map +1 -0
- package/dist/clients/index.d.ts +9 -6
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +8 -5
- package/dist/clients/index.js.map +1 -1
- package/dist/clients/listing.d.ts +32 -0
- package/dist/clients/listing.d.ts.map +1 -1
- package/dist/clients/listing.js +47 -1
- package/dist/clients/listing.js.map +1 -1
- package/dist/clients/revocation.d.ts +33 -1
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +16 -4
- package/dist/clients/revocation.js.map +1 -1
- package/dist/enrollment/index.d.ts +6 -4
- package/dist/enrollment/index.d.ts.map +1 -1
- package/dist/enrollment/index.js +6 -4
- package/dist/enrollment/index.js.map +1 -1
- package/dist/enrollment/onboardingInvite.d.ts +5 -88
- package/dist/enrollment/onboardingInvite.d.ts.map +1 -1
- package/dist/enrollment/onboardingInvite.js +5 -168
- package/dist/enrollment/onboardingInvite.js.map +1 -1
- package/dist/genesis/accountGenesis.d.ts +12 -0
- package/dist/genesis/accountGenesis.d.ts.map +1 -1
- package/dist/genesis/accountGenesis.js.map +1 -1
- package/dist/genesis/index.d.ts +5 -0
- package/dist/genesis/index.d.ts.map +1 -1
- package/dist/genesis/index.js +5 -0
- package/dist/genesis/index.js.map +1 -1
- package/dist/keys/index.d.ts +1 -1
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +1 -1
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/spaceEpochs.d.ts +7 -2
- package/dist/keys/spaceEpochs.d.ts.map +1 -1
- package/dist/keys/spaceEpochs.js +8 -2
- package/dist/keys/spaceEpochs.js.map +1 -1
- package/dist/keys/userKeyRoster.d.ts +39 -0
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +43 -1
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/recovery/index.d.ts +5 -3
- package/dist/recovery/index.d.ts.map +1 -1
- package/dist/recovery/index.js +4 -2
- package/dist/recovery/index.js.map +1 -1
- package/dist/recovery/recoveryDelegation.d.ts +35 -12
- package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
- package/dist/recovery/recoveryDelegation.js +84 -86
- package/dist/recovery/recoveryDelegation.js.map +1 -1
- package/dist/recovery/recoveryWebvh.d.ts +32 -1
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.js +2 -2
- package/dist/recovery/recoveryWebvh.js.map +1 -1
- package/dist/request/capabilityRequest.d.ts +33 -0
- package/dist/request/capabilityRequest.d.ts.map +1 -0
- package/dist/request/capabilityRequest.js +35 -0
- package/dist/request/capabilityRequest.js.map +1 -0
- package/dist/request/ephemeralExchange.d.ts +118 -0
- package/dist/request/ephemeralExchange.d.ts.map +1 -0
- package/dist/request/ephemeralExchange.js +224 -0
- package/dist/request/ephemeralExchange.js.map +1 -0
- package/dist/request/index.d.ts +6 -0
- package/dist/request/index.d.ts.map +1 -1
- package/dist/request/index.js +6 -0
- package/dist/request/index.js.map +1 -1
- package/dist/space/activity.d.ts +2 -2
- package/dist/space/activity.js +3 -3
- package/dist/space/activity.js.map +1 -1
- package/dist/unlock/index.d.ts +11 -23
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/index.js +10 -21
- package/dist/unlock/index.js.map +1 -1
- package/dist/unlock/retire.d.ts +47 -3
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js +21 -5
- package/dist/unlock/retire.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +37 -82
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +64 -247
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/unlock/unlockRecord.d.ts +13 -6
- package/dist/unlock/unlockRecord.d.ts.map +1 -1
- package/dist/unlock/unlockRecord.js +14 -8
- package/dist/unlock/unlockRecord.js.map +1 -1
- package/dist/webvh/delegatedLogStore.d.ts +5 -5
- package/dist/webvh/delegatedLogStore.js +1 -1
- package/dist/webvh/didWebvh.d.ts +19 -9
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +16 -16
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/index.d.ts +9 -25
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +9 -23
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +77 -5
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +154 -61
- package/dist/webvh/revokeClient.js.map +1 -1
- package/dist/webvh/standingZcap.d.ts +11 -1
- package/dist/webvh/standingZcap.d.ts.map +1 -1
- package/dist/webvh/standingZcap.js +13 -14
- package/dist/webvh/standingZcap.js.map +1 -1
- package/dist/webvh/wasIdStore.d.ts +13 -7
- package/dist/webvh/wasIdStore.d.ts.map +1 -1
- package/dist/webvh/wasIdStore.js +8 -4
- package/dist/webvh/wasIdStore.js.map +1 -1
- package/dist/webvh/zcap.d.ts +0 -24
- package/dist/webvh/zcap.d.ts.map +1 -1
- package/dist/webvh/zcap.js +0 -42
- package/dist/webvh/zcap.js.map +1 -1
- package/package.json +41 -35
- package/dist/unlock/ladder.d.ts.map +0 -1
- package/dist/unlock/ladder.js +0 -258
- package/dist/unlock/ladder.js.map +0 -1
- package/dist/unlock/selfEnroll.d.ts.map +0 -1
- package/dist/unlock/selfEnroll.js.map +0 -1
- package/dist/webvh/companion.d.ts.map +0 -1
- package/dist/webvh/companion.js.map +0 -1
- package/dist/webvh/companionGc.d.ts.map +0 -1
- package/dist/webvh/companionGc.js.map +0 -1
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { readPublishedLog, relationIds } from '../webvh/didWebvh.js';
|
|
2
|
+
import { clientRemovalTarget } from '../webvh/revokeClient.js';
|
|
3
|
+
import { delegationProofKeyId } from '../webvh/standingZcap.js';
|
|
4
|
+
import { vmFragmentOf } from '../resourceLog/index.js';
|
|
5
|
+
import { cascadeCollectionsToUserKey, readUserKeyRoster, rosterRecipientKid, rotateUserKeyRoster } from '../keys/index.js';
|
|
6
|
+
import { readLogOrThrow } from '../unlock/standingWebvh.js';
|
|
7
|
+
import { recordSignerFromAgent } from '../keyring/record.js';
|
|
8
|
+
import { remintRecoveryDelegations } from '../recovery/recoveryDelegation.js';
|
|
9
|
+
import { ladderVmKeyMultibase } from './ladder.js';
|
|
10
|
+
import { ladderVmAgent, ladderVmZcapClient } from './zcap.js';
|
|
11
|
+
import { forgetLastWebvhClient, installLadderVmWebvh } from './ladderAnchored.js';
|
|
12
|
+
import { clientAnnexDidParts, clientAnnexLogPinId, delegatedClientsDelegationMinter, delegatedClientsPointer, ensureGenerationDelegationCurrent, generationDelegationHistory, mintGenerationDelegation, revokeTreatingAlreadyRevokedAsSuccess } from './log.js';
|
|
13
|
+
/**
|
|
14
|
+
* The record re-mint stage could not reach every other unlock method's
|
|
15
|
+
* record, so the removal entry was refused: `failed` names the entries whose
|
|
16
|
+
* re-mint threw (each carrying its cause), and `unlockMethods` is the whole
|
|
17
|
+
* stage report. The forgotten client is still enrolled and every stage
|
|
18
|
+
* before this one has landed, so a re-run resumes at the re-mint. Matched
|
|
19
|
+
* on `name` (the errors cross app-injected seams that may resolve to another
|
|
20
|
+
* copy of this package).
|
|
21
|
+
*/
|
|
22
|
+
export class RecordRemintFailedError extends Error {
|
|
23
|
+
failed;
|
|
24
|
+
unlockMethods;
|
|
25
|
+
constructor({ unlockMethods }) {
|
|
26
|
+
const failed = unlockMethods.outcomes.filter(outcome => outcome.outcome === 'failed');
|
|
27
|
+
super('did:webvh: the last-client forget could not re-mint the record of ' +
|
|
28
|
+
`${failed.length} other unlock method(s) (` +
|
|
29
|
+
failed.map(outcome => `"${outcome.label}"`).join(', ') +
|
|
30
|
+
'); the removal entry was not published. The client stays enrolled; ' +
|
|
31
|
+
'run the forget again.');
|
|
32
|
+
this.name = 'RecordRemintFailedError';
|
|
33
|
+
this.failed = failed;
|
|
34
|
+
this.unlockMethods = unlockMethods;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Forgets the account's LAST enrolled durable client -- this browser's own
|
|
39
|
+
* -- transitioning the account to the client-less, ladder-anchored state.
|
|
40
|
+
* See the module doc for the stage order and the torn-state map. The caller
|
|
41
|
+
* runs the local wipe only after this resolves. An account with another
|
|
42
|
+
* enrolled durable client refuses: that forget is the ordinary ceremony
|
|
43
|
+
* (`forgetDurableClient`), reached first, whose `LastDurableClientForgetError`
|
|
44
|
+
* is what routes callers here.
|
|
45
|
+
*
|
|
46
|
+
* @param options {object}
|
|
47
|
+
* @param options.logStore {UnlockLogStore} the credential's delegated
|
|
48
|
+
* `did.jsonl` bridge store; also serves the ceremony's public reads. The
|
|
49
|
+
* caller is expected to have verified the account log under its own
|
|
50
|
+
* chain-head pins in the same session (the ceremony re-reads through the
|
|
51
|
+
* seam and checks `expectedDid`, but carries no account-log pin store
|
|
52
|
+
* itself)
|
|
53
|
+
* @param options.ladderSeed {Uint8Array} the login credential's ladder seed
|
|
54
|
+
* @param options.forgottenClient {RevokedClientKeys} this client's public
|
|
55
|
+
* halves; an `updateKeyMultibase` the log does not authorize (stale, or the
|
|
56
|
+
* staged key) is re-derived from the log
|
|
57
|
+
* @param options.forgottenKeyAgreementKeyMultibase {string} this client's
|
|
58
|
+
* identity key-agreement key (the X25519 twin), naming its roster wrap
|
|
59
|
+
* @param [options.knownLatentHashes] {string[]} standing latent commitments
|
|
60
|
+
* the caller vouches for (the recovery registry's update-key hashes),
|
|
61
|
+
* excluded from the staged-hash attribution
|
|
62
|
+
* @param options.expectedDid {string} the account DID from the caller's
|
|
63
|
+
* stored account pointer
|
|
64
|
+
* @param options.rosterStoreFor {Function} `({ did, log }) => store` --
|
|
65
|
+
* builds the `key-map/user-key.jsonl` roster store whose appends are
|
|
66
|
+
* SIGNED BY THE LADDER VM and whose controller view resolves from the
|
|
67
|
+
* supplied post-install log (the posture-changing anchor the ceremony-tail
|
|
68
|
+
* license admits), while its HTTP requests invoke under the still-standing
|
|
69
|
+
* client
|
|
70
|
+
* @param options.credentialKeyAgreementKey {IKeyAgreementKey} the standing
|
|
71
|
+
* credential's key-agreement key -- the recipient whose wrap survives the
|
|
72
|
+
* rotation, reading the fresh key back and unwrapping the generations for
|
|
73
|
+
* the fan-out
|
|
74
|
+
* @param [options.userKey] {UserKey} this client's cached user key
|
|
75
|
+
* @param [options.pinnedEpochId] {string} the locally pinned latest-seen
|
|
76
|
+
* roster epoch
|
|
77
|
+
* @param [options.onUserKeyAdopted] {Function} persists a rotated key:
|
|
78
|
+
* called with `{ userKey, latestEpochId, descriptor }` after the roster
|
|
79
|
+
* read and BEFORE the fan-out
|
|
80
|
+
* @param options.collections {CascadeCollections} the fan-out's work
|
|
81
|
+
* @param options.annex {object} the generation stage's reach:
|
|
82
|
+
* @param options.annex.storeFor {Function}
|
|
83
|
+
* `({ spaceId, generationId }) => ClientAnnexWriteStore` -- the pointed
|
|
84
|
+
* generation's log store, reading and writing under the still-standing
|
|
85
|
+
* client's authority
|
|
86
|
+
* @param options.annex.revoke {Function} `(delegation) => Promise<void>`
|
|
87
|
+
* -- POSTs a revocation (was-client's `WasClient#revoke`, bound by the
|
|
88
|
+
* caller; the invocation signs as the still-standing client)
|
|
89
|
+
* @param options.annex.wasServerUrl {string} the ACCOUNT Space's storage
|
|
90
|
+
* server (the fresh generation delegation's target host)
|
|
91
|
+
* @param options.annex.accountSpaceId {string} the ACCOUNT Space's id (the
|
|
92
|
+
* fresh delegation's target subtree)
|
|
93
|
+
* @param [options.annex.pinStore] {ResourceLogPinStore} chain-head pins
|
|
94
|
+
* for the pointed generation's read
|
|
95
|
+
* @param [options.unlockMethods] {UnlockMethodsRemintReach} the other
|
|
96
|
+
* unlock methods' record re-mint reach (stage 5): the registry entries
|
|
97
|
+
* whose bridge (and sibling) the ladder VM re-signs and whose records it
|
|
98
|
+
* re-seals through their management zcaps, invoked as the still-standing
|
|
99
|
+
* client. Omitted, the stage is skipped and the result carries no
|
|
100
|
+
* `unlockMethods` report -- the residue decision 0004's amendment stated.
|
|
101
|
+
* Supplied, an entry the pass could not re-mint refuses the removal entry
|
|
102
|
+
* (`RecordRemintFailedError`)
|
|
103
|
+
* @param [options.onBeforeRemoval] {Function}
|
|
104
|
+
* `({ did, doc, log }) => Promise<void>` -- the record re-bind seam: runs
|
|
105
|
+
* after the record re-mint stage, immediately before the removal entry,
|
|
106
|
+
* with the post-install published state. The caller re-signs the login
|
|
107
|
+
* credential's bridge and `delegatedClients` sibling with the ladder VM
|
|
108
|
+
* and re-seals its unlock record here. Must be idempotent (a resumed run
|
|
109
|
+
* invokes it again)
|
|
110
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
111
|
+
* @returns {Promise<LastDurableClientForgetResult>}
|
|
112
|
+
*/
|
|
113
|
+
export async function forgetLastDurableClient({ logStore, ladderSeed, forgottenClient, forgottenKeyAgreementKeyMultibase, knownLatentHashes, expectedDid, rosterStoreFor, credentialKeyAgreementKey, userKey, pinnedEpochId, onUserKeyAdopted, collections, annex, unlockMethods, onBeforeRemoval, now = Date.now() }) {
|
|
114
|
+
// The pre-install read and the two guards: a client with no remaining
|
|
115
|
+
// presence means the removal entry already landed (the finish-the-wipe
|
|
116
|
+
// state the app's next login maps -- nothing here can still invoke), and
|
|
117
|
+
// an account with another enrolled durable client belongs to the ordinary
|
|
118
|
+
// forget ceremony.
|
|
119
|
+
const before = await readLogOrThrow({ store: logStore, expectedDid });
|
|
120
|
+
const preTarget = await clientRemovalTarget({
|
|
121
|
+
published: before,
|
|
122
|
+
client: forgottenClient
|
|
123
|
+
});
|
|
124
|
+
if (!preTarget.present) {
|
|
125
|
+
return {
|
|
126
|
+
installed: false,
|
|
127
|
+
rotated: false,
|
|
128
|
+
collections: { outcomes: {}, failed: [] },
|
|
129
|
+
generation: { revoked: [], replaced: false, skipped: 'already-removed' },
|
|
130
|
+
did: before.did,
|
|
131
|
+
document: before.doc
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const signingVmId = `${before.did}#${forgottenClient.signingKeyMultibase}`;
|
|
135
|
+
const invocationIds = relationIds(before.doc.capabilityInvocation);
|
|
136
|
+
if (invocationIds.some(id => id !== signingVmId)) {
|
|
137
|
+
throw new Error('did:webvh: another enrolled durable client remains; the last-client ' +
|
|
138
|
+
'transition ceremony does not apply -- run the ordinary forget.');
|
|
139
|
+
}
|
|
140
|
+
// Stage 1: the install entry -- the ladder VM in, the client untouched.
|
|
141
|
+
const install = await installLadderVmWebvh({
|
|
142
|
+
store: logStore,
|
|
143
|
+
ladderSeed,
|
|
144
|
+
expectedDid
|
|
145
|
+
});
|
|
146
|
+
// Stage 2: the roster rotation off this client's wrap, ladder-signed and
|
|
147
|
+
// anchored at the install entry, then stage 3, the collection fan-out --
|
|
148
|
+
// both HTTP-invoked under this client's still-standing authority. An
|
|
149
|
+
// already-rotated roster skips the append entirely, so the one-shot
|
|
150
|
+
// license is never asked for a second append at the same anchor.
|
|
151
|
+
let rotated = false;
|
|
152
|
+
let read;
|
|
153
|
+
let cascade = { outcomes: {}, failed: [] };
|
|
154
|
+
const rosterStore = rosterStoreFor({ did: install.did, log: install.log });
|
|
155
|
+
const current = await rosterStore.read();
|
|
156
|
+
if (current !== null) {
|
|
157
|
+
const forgottenKid = rosterRecipientKid({
|
|
158
|
+
signingKeyMultibase: forgottenClient.signingKeyMultibase,
|
|
159
|
+
keyAgreementKeyMultibase: forgottenKeyAgreementKeyMultibase
|
|
160
|
+
});
|
|
161
|
+
let descriptor = current.descriptor;
|
|
162
|
+
const currentEpoch = (descriptor.epochs ?? []).find(epoch => epoch.id === descriptor.currentEpoch);
|
|
163
|
+
const wrapped = currentEpoch?.recipients.some(entry => entry.header.kid === forgottenKid);
|
|
164
|
+
if (wrapped) {
|
|
165
|
+
descriptor = await rotateUserKeyRoster({
|
|
166
|
+
store: rosterStore,
|
|
167
|
+
document: install.doc,
|
|
168
|
+
retireRecipientId: forgottenKid
|
|
169
|
+
});
|
|
170
|
+
rotated = true;
|
|
171
|
+
}
|
|
172
|
+
// The fresh key comes back through the credential's standing wrap -- this
|
|
173
|
+
// client's own is gone from the current epoch -- with the continuity and
|
|
174
|
+
// possession checks still running on the threaded descriptor.
|
|
175
|
+
const adopted = await readUserKeyRoster({
|
|
176
|
+
store: rosterStore,
|
|
177
|
+
descriptor,
|
|
178
|
+
...(userKey ? { userKey } : {}),
|
|
179
|
+
clientKeyAgreementKey: credentialKeyAgreementKey,
|
|
180
|
+
pinnedEpochId
|
|
181
|
+
});
|
|
182
|
+
if (adopted.rotated) {
|
|
183
|
+
await onUserKeyAdopted?.({
|
|
184
|
+
userKey: adopted.userKey,
|
|
185
|
+
latestEpochId: adopted.latestEpochId,
|
|
186
|
+
descriptor: adopted.descriptor
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
read = { userKey: adopted.userKey, descriptor: adopted.descriptor };
|
|
190
|
+
cascade = await cascadeCollectionsToUserKey({
|
|
191
|
+
collectionIds: typeof collections.collectionIds === 'function'
|
|
192
|
+
? await collections.collectionIds()
|
|
193
|
+
: collections.collectionIds,
|
|
194
|
+
storeFor: collections.storeFor,
|
|
195
|
+
...(collections.isEncrypted
|
|
196
|
+
? { isEncrypted: collections.isEncrypted }
|
|
197
|
+
: {}),
|
|
198
|
+
rosterDescriptor: adopted.descriptor,
|
|
199
|
+
clientKeyAgreementKey: credentialKeyAgreementKey,
|
|
200
|
+
userKey: adopted.userKey
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Stage 4: the generation-delegation replacement and revocations.
|
|
204
|
+
const generation = await retireLadderGenerationDelegations({
|
|
205
|
+
doc: install.doc,
|
|
206
|
+
accountDid: install.did,
|
|
207
|
+
ladderSeed,
|
|
208
|
+
annex,
|
|
209
|
+
now
|
|
210
|
+
});
|
|
211
|
+
// Stage 5: the other unlock methods' record re-mint, ladder-signed, with
|
|
212
|
+
// the forgotten client named as retiring -- the post-install document
|
|
213
|
+
// still lists it, so without that axis every bridge it signed would read
|
|
214
|
+
// as standing and be left to rot at the removal entry.
|
|
215
|
+
let remint;
|
|
216
|
+
if (unlockMethods !== undefined) {
|
|
217
|
+
remint = await remintUnlockMethodRecordsAsLadder({
|
|
218
|
+
doc: install.doc,
|
|
219
|
+
accountDid: install.did,
|
|
220
|
+
ladderSeed,
|
|
221
|
+
retiringSigningKeyMultibase: forgottenClient.signingKeyMultibase,
|
|
222
|
+
reach: unlockMethods,
|
|
223
|
+
now
|
|
224
|
+
});
|
|
225
|
+
// The one pass that will ever reach these records on a client-less
|
|
226
|
+
// account: a record it could not re-seal would be left with a bridge the
|
|
227
|
+
// removal entry rots for good, so the removal is refused instead. The
|
|
228
|
+
// stages already landed are idempotent and the client still stands, so
|
|
229
|
+
// the re-run resumes here.
|
|
230
|
+
if (remint.outcomes.some(outcome => outcome.outcome === 'failed')) {
|
|
231
|
+
throw new RecordRemintFailedError({ unlockMethods: remint });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Stage 6: the record re-bind seam, while the removal has not landed (a
|
|
235
|
+
// ladder-VM-signed bridge verifies from the install entry on, and the old
|
|
236
|
+
// client-signed one keeps verifying until the removal -- so a tear on
|
|
237
|
+
// either side of this callback leaves a working login).
|
|
238
|
+
await onBeforeRemoval?.({
|
|
239
|
+
did: install.did,
|
|
240
|
+
doc: install.doc,
|
|
241
|
+
log: install.log
|
|
242
|
+
});
|
|
243
|
+
// Stage 7: the removal entry -- the client's whole footprint out, the
|
|
244
|
+
// installed ladder VM keeping the account anchored.
|
|
245
|
+
const removed = await forgetLastWebvhClient({
|
|
246
|
+
store: logStore,
|
|
247
|
+
ladderSeed,
|
|
248
|
+
forgottenClient,
|
|
249
|
+
...(knownLatentHashes ? { knownLatentHashes } : {}),
|
|
250
|
+
expectedDid
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
installed: install.installed,
|
|
254
|
+
rotated,
|
|
255
|
+
collections: cascade,
|
|
256
|
+
generation,
|
|
257
|
+
...(remint ? { unlockMethods: remint } : {}),
|
|
258
|
+
did: removed.did,
|
|
259
|
+
document: removed.doc,
|
|
260
|
+
...(read
|
|
261
|
+
? { userKey: read.userKey, rosterDescriptor: read.descriptor }
|
|
262
|
+
: {})
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The generation stage: reads the pointed generation's log, force-replaces
|
|
267
|
+
* the embedded delegation with a fresh ladder-signed one (so the account
|
|
268
|
+
* stays transient-login-reachable), then revokes every still-unexpired
|
|
269
|
+
* delegation the log's history embedded that this credential's ladder VM
|
|
270
|
+
* signed. Replace-before-revoke is the tear-safety order: the fresh
|
|
271
|
+
* delegation is never in the pre-replacement history, so the revocation loop
|
|
272
|
+
* cannot touch it, and a run torn between the two leaves the generation with
|
|
273
|
+
* a live delegation either way.
|
|
274
|
+
*
|
|
275
|
+
* @param options {object}
|
|
276
|
+
* @param options.doc {DIDDoc} the post-install account document
|
|
277
|
+
* @param options.accountDid {string}
|
|
278
|
+
* @param options.ladderSeed {Uint8Array}
|
|
279
|
+
* @param options.annex {object} see {@link forgetLastDurableClient}
|
|
280
|
+
* @param options.now {number}
|
|
281
|
+
* @returns {Promise<GenerationDelegationRetirement>}
|
|
282
|
+
*/
|
|
283
|
+
async function retireLadderGenerationDelegations({ doc, accountDid, ladderSeed, annex, now }) {
|
|
284
|
+
const pointedDid = delegatedClientsPointer({ doc });
|
|
285
|
+
if (pointedDid === undefined) {
|
|
286
|
+
return { revoked: [], replaced: false, skipped: 'no-pointer' };
|
|
287
|
+
}
|
|
288
|
+
const parts = clientAnnexDidParts({ did: pointedDid });
|
|
289
|
+
const store = annex.storeFor(parts);
|
|
290
|
+
const logId = clientAnnexLogPinId(parts);
|
|
291
|
+
// readPublishedLog only calls getIdResourceRaw, so the narrow seam is safe.
|
|
292
|
+
const published = await readPublishedLog({
|
|
293
|
+
idStore: store,
|
|
294
|
+
expectedDid: pointedDid,
|
|
295
|
+
...(annex.pinStore !== undefined ? { pinStore: annex.pinStore, logId } : {})
|
|
296
|
+
});
|
|
297
|
+
if (published === undefined) {
|
|
298
|
+
return { revoked: [], replaced: false, skipped: 'log-unreadable' };
|
|
299
|
+
}
|
|
300
|
+
// The doomed set, collected BEFORE the replacement so the fresh delegation
|
|
301
|
+
// can never join it: every delegation the history embedded whose proof key
|
|
302
|
+
// is this credential's ladder VM and whose expiry has not passed. An
|
|
303
|
+
// unparseable or absent expiry counts as unexpired -- fail-safe, since an
|
|
304
|
+
// unbounded delegation is the worst resurrection credential.
|
|
305
|
+
const ladderVmKey = await ladderVmKeyMultibase({ ladderSeed });
|
|
306
|
+
const doomed = generationDelegationHistory({ log: published.log }).filter(delegation => {
|
|
307
|
+
const proofKeyId = delegationProofKeyId(delegation);
|
|
308
|
+
const fragment = proofKeyId === undefined ? null : vmFragmentOf(proofKeyId);
|
|
309
|
+
if (fragment !== ladderVmKey) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
const expires = Date.parse(delegation.expires ?? '');
|
|
313
|
+
return Number.isNaN(expires) || expires > now;
|
|
314
|
+
});
|
|
315
|
+
// The forced replacement first: a ladder-signed fresh delegation under the
|
|
316
|
+
// reinstalled VM, the annex entry signed by this credential's committed
|
|
317
|
+
// annex rung. A credential the generation does not commit cannot write the
|
|
318
|
+
// entry -- the honest skip, leaving the generation delegation-less once
|
|
319
|
+
// the doomed set is revoked below.
|
|
320
|
+
let replaced = false;
|
|
321
|
+
const ladderClient = await ladderVmZcapClient({ accountDid, ladderSeed });
|
|
322
|
+
try {
|
|
323
|
+
await ensureGenerationDelegationCurrent({
|
|
324
|
+
store,
|
|
325
|
+
ladderSeed,
|
|
326
|
+
generationId: parts.generationId,
|
|
327
|
+
mintGenerationDelegation: async ({ clientAnnexDid }) => mintGenerationDelegation({
|
|
328
|
+
zcapClient: ladderClient,
|
|
329
|
+
wasServerUrl: annex.wasServerUrl,
|
|
330
|
+
spaceId: annex.accountSpaceId,
|
|
331
|
+
clientAnnexDid,
|
|
332
|
+
now
|
|
333
|
+
}),
|
|
334
|
+
expectedDid: pointedDid,
|
|
335
|
+
force: true,
|
|
336
|
+
...(annex.pinStore !== undefined
|
|
337
|
+
? { pinStore: annex.pinStore, logId }
|
|
338
|
+
: {}),
|
|
339
|
+
now
|
|
340
|
+
});
|
|
341
|
+
replaced = true;
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
if (err.name !== 'ClientAnnexRungUncommittedError') {
|
|
345
|
+
throw err;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// The revocations, blind and resumable (400 already-revoked as success).
|
|
349
|
+
const revoked = [];
|
|
350
|
+
for (const delegation of doomed) {
|
|
351
|
+
await revokeTreatingAlreadyRevokedAsSuccess({
|
|
352
|
+
revoke: annex.revoke,
|
|
353
|
+
delegation
|
|
354
|
+
});
|
|
355
|
+
const id = delegation.id;
|
|
356
|
+
if (typeof id === 'string') {
|
|
357
|
+
revoked.push(id);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return replaced
|
|
361
|
+
? { revoked, replaced }
|
|
362
|
+
: { revoked, replaced, skipped: 'rung-uncommitted' };
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* The record re-mint stage: the revocation cascade's re-mint pass over the
|
|
366
|
+
* other unlock methods' registry entries, with the ladder VM as both the
|
|
367
|
+
* delegating key (the fresh bridge and sibling) and the record-frame signer
|
|
368
|
+
* (`ladderVmAgent`'s did:key form, whose multibase the post-install document
|
|
369
|
+
* lists, so a reader settling the mixed-signer proof against the account
|
|
370
|
+
* document accepts it after the removal too -- `currentAccountRecordSigners`
|
|
371
|
+
* is that allowlist), and the forgotten client named as retiring. The sibling
|
|
372
|
+
* minter reads the annex pointer off the post-install document. The HTTP
|
|
373
|
+
* side rides the caller's management-zcap clients, still invocable here.
|
|
374
|
+
*
|
|
375
|
+
* @param options {object}
|
|
376
|
+
* @param options.doc {DIDDoc} the post-install account document
|
|
377
|
+
* @param options.accountDid {string}
|
|
378
|
+
* @param options.ladderSeed {Uint8Array}
|
|
379
|
+
* @param options.retiringSigningKeyMultibase {string} the forgotten
|
|
380
|
+
* client's signing key
|
|
381
|
+
* @param options.reach {UnlockMethodsRemintReach}
|
|
382
|
+
* @param options.now {number}
|
|
383
|
+
* @returns {Promise<object>} the pass's counts and per-entry outcomes
|
|
384
|
+
*/
|
|
385
|
+
async function remintUnlockMethodRecordsAsLadder({ doc, accountDid, ladderSeed, retiringSigningKeyMultibase, reach, now }) {
|
|
386
|
+
const ladderClient = await ladderVmZcapClient({ accountDid, ladderSeed });
|
|
387
|
+
const recordSigner = recordSignerFromAgent({
|
|
388
|
+
keyAgent: await ladderVmAgent({ ladderSeed })
|
|
389
|
+
});
|
|
390
|
+
return remintRecoveryDelegations({
|
|
391
|
+
doc,
|
|
392
|
+
entries: reach.entries,
|
|
393
|
+
pointer: reach.pointer,
|
|
394
|
+
storageServerUrl: reach.storageServerUrl,
|
|
395
|
+
zcapClient: ladderClient,
|
|
396
|
+
recordSigner,
|
|
397
|
+
managementZcapClient: reach.managementZcapClient,
|
|
398
|
+
recordEntry: reach.recordEntry,
|
|
399
|
+
mintDelegatedClientsDelegation: delegatedClientsDelegationMinter({
|
|
400
|
+
doc,
|
|
401
|
+
zcapClient: ladderClient,
|
|
402
|
+
wasServerUrl: reach.pointer.host
|
|
403
|
+
}),
|
|
404
|
+
retiringKeyMultibases: [retiringSigningKeyMultibase],
|
|
405
|
+
now
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=forgetLast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgetLast.js","sourceRoot":"","sources":["../../src/clientAnnex/forgetLast.ts"],"names":[],"mappings":"AA0FA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEpE,OAAO,EACL,mBAAmB,EAEpB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EAIpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EACL,yBAAyB,EAG1B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gCAAgC,EAChC,uBAAuB,EACvB,iCAAiC,EACjC,2BAA2B,EAC3B,wBAAwB,EACxB,qCAAqC,EAEtC,MAAM,UAAU,CAAA;AAmEjB;;;;;;;;GAQG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,MAAM,CAAuB;IAC7B,aAAa,CAErB;IAED,YAAY,EACV,aAAa,EAGd;QACC,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,CAC1C,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ,CACxC,CAAA;QACD,KAAK,CACH,oEAAoE;YAClE,GAAG,MAAM,CAAC,MAAM,2BAA2B;YAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACtD,qEAAqE;YACrE,uBAAuB,CAC1B,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAC5C,QAAQ,EACR,UAAU,EACV,eAAe,EACf,iCAAiC,EACjC,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,yBAAyB,EACzB,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,KAAK,EACL,aAAa,EACb,eAAe,EACf,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAsCjB;IACC,sEAAsE;IACtE,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,mBAAmB;IACnB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;IACrE,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC;QAC1C,SAAS,EAAE,MAAM;QACjB,MAAM,EAAE,eAAe;KACxB,CAAC,CAAA;IACF,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YACzC,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE;YACxE,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,QAAQ,EAAE,MAAM,CAAC,GAAG;SACrB,CAAA;IACH,CAAC;IACD,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,mBAAmB,EAAE,CAAA;IAC1E,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAClE,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,WAAW,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,gEAAgE,CACnE,CAAA;IACH,CAAC;IAED,wEAAwE;IACxE,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC;QACzC,KAAK,EAAE,QAAQ;QACf,UAAU;QACV,WAAW;KACZ,CAAC,CAAA;IAEF,yEAAyE;IACzE,yEAAyE;IACzE,qEAAqE;IACrE,oEAAoE;IACpE,iEAAiE;IACjE,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,IAAI,IAAwE,CAAA;IAC5E,IAAI,OAAO,GAAyB,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;IAChE,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAA;IACxC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,kBAAkB,CAAC;YACtC,mBAAmB,EAAE,eAAe,CAAC,mBAAmB;YACxD,wBAAwB,EAAE,iCAAiC;SAC5D,CAAC,CAAA;QACF,IAAI,UAAU,GAAG,OAAO,CAAC,UAAU,CAAA;QACnC,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CACjD,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,UAAU,CAAC,YAAY,CAC9C,CAAA;QACD,MAAM,OAAO,GAAG,YAAY,EAAE,UAAU,CAAC,IAAI,CAC3C,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,YAAY,CAC3C,CAAA;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,UAAU,GAAG,MAAM,mBAAmB,CAAC;gBACrC,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,OAAO,CAAC,GAAG;gBACrB,iBAAiB,EAAE,YAAY;aAChC,CAAC,CAAA;YACF,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;QACD,0EAA0E;QAC1E,yEAAyE;QACzE,8DAA8D;QAC9D,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC;YACtC,KAAK,EAAE,WAAW;YAClB,UAAU;YACV,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,qBAAqB,EAAE,yBAAyB;YAChD,aAAa;SACd,CAAC,CAAA;QACF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,gBAAgB,EAAE,CAAC;gBACvB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAA;QACnE,OAAO,GAAG,MAAM,2BAA2B,CAAC;YAC1C,aAAa,EACX,OAAO,WAAW,CAAC,aAAa,KAAK,UAAU;gBAC7C,CAAC,CAAC,MAAM,WAAW,CAAC,aAAa,EAAE;gBACnC,CAAC,CAAC,WAAW,CAAC,aAAa;YAC/B,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,GAAG,CAAC,WAAW,CAAC,WAAW;gBACzB,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,EAAE;gBAC1C,CAAC,CAAC,EAAE,CAAC;YACP,gBAAgB,EAAE,OAAO,CAAC,UAAU;YACpC,qBAAqB,EAAE,yBAAyB;YAChD,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,kEAAkE;IAClE,MAAM,UAAU,GAAG,MAAM,iCAAiC,CAAC;QACzD,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,UAAU,EAAE,OAAO,CAAC,GAAG;QACvB,UAAU;QACV,KAAK;QACL,GAAG;KACJ,CAAC,CAAA;IAEF,yEAAyE;IACzE,sEAAsE;IACtE,yEAAyE;IACzE,uDAAuD;IACvD,IAAI,MAAsD,CAAA;IAC1D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,GAAG,MAAM,iCAAiC,CAAC;YAC/C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,UAAU,EAAE,OAAO,CAAC,GAAG;YACvB,UAAU;YACV,2BAA2B,EAAE,eAAe,CAAC,mBAAmB;YAChE,KAAK,EAAE,aAAa;YACpB,GAAG;SACJ,CAAC,CAAA;QACF,mEAAmE;QACnE,yEAAyE;QACzE,sEAAsE;QACtE,uEAAuE;QACvE,2BAA2B;QAC3B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,uBAAuB,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,sEAAsE;IACtE,wDAAwD;IACxD,MAAM,eAAe,EAAE,CAAC;QACtB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAA;IAEF,sEAAsE;IACtE,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC;QAC1C,KAAK,EAAE,QAAQ;QACf,UAAU;QACV,eAAe;QACf,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,WAAW;KACZ,CAAC,CAAA;IAEF,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO;QACP,WAAW,EAAE,OAAO;QACpB,UAAU;QACV,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,GAAG;QACrB,GAAG,CAAC,IAAI;YACN,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,CAAC,UAAU,EAAE;YAC9D,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,KAAK,UAAU,iCAAiC,CAAC,EAC/C,GAAG,EACH,UAAU,EACV,UAAU,EACV,KAAK,EACL,GAAG,EAgBJ;IACC,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IACnD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,CAAA;IAChE,CAAC;IACD,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACnC,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IACxC,4EAA4E;IAC5E,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC;QACvC,OAAO,EAAE,KAAqB;QAC9B,WAAW,EAAE,UAAU;QACvB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7E,CAAC,CAAA;IACF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAA;IACpE,CAAC;IAED,2EAA2E;IAC3E,2EAA2E;IAC3E,qEAAqE;IACrE,0EAA0E;IAC1E,6DAA6D;IAC7D,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IAC9D,MAAM,MAAM,GAAG,2BAA2B,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CACvE,UAAU,CAAC,EAAE;QACX,MAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAA;QACnD,MAAM,QAAQ,GACZ,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;QAC5D,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACvB,UAAmC,CAAC,OAAO,IAAI,EAAE,CACnD,CAAA;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,GAAG,CAAA;IAC/C,CAAC,CACF,CAAA;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,wEAAwE;IACxE,mCAAmC;IACnC,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACzE,IAAI,CAAC;QACH,MAAM,iCAAiC,CAAC;YACtC,KAAK;YACL,UAAU;YACV,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,wBAAwB,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CACrD,wBAAwB,CAAC;gBACvB,UAAU,EAAE,YAAY;gBACxB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,OAAO,EAAE,KAAK,CAAC,cAAc;gBAC7B,cAAc;gBACd,GAAG;aACJ,CAAC;YACJ,WAAW,EAAE,UAAU;YACvB,KAAK,EAAE,IAAI;YACX,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;gBAC9B,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE;gBACrC,CAAC,CAAC,EAAE,CAAC;YACP,GAAG;SACJ,CAAC,CAAA;QACF,QAAQ,GAAG,IAAI,CAAA;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAAyB,CAAC,IAAI,KAAK,iCAAiC,EAAE,CAAC;YAC1E,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;QAChC,MAAM,qCAAqC,CAAC;YAC1C,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU;SACX,CAAC,CAAA;QACF,MAAM,EAAE,GAAI,UAA8B,CAAC,EAAE,CAAA;QAC7C,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ;QACb,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACvB,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAA;AACxD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,KAAK,UAAU,iCAAiC,CAAC,EAC/C,GAAG,EACH,UAAU,EACV,UAAU,EACV,2BAA2B,EAC3B,KAAK,EACL,GAAG,EAQJ;IACC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IACzE,MAAM,YAAY,GAAG,qBAAqB,CAAC;QACzC,QAAQ,EAAE,MAAM,aAAa,CAAC,EAAE,UAAU,EAAE,CAAC;KAC9C,CAAC,CAAA;IACF,OAAO,yBAAyB,CAAC;QAC/B,GAAG;QACH,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,UAAU,EAAE,YAAY;QACxB,YAAY;QACZ,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,8BAA8B,EAAE,gCAAgC,CAAC;YAC/D,GAAG;YACH,UAAU,EAAE,YAAY;YACxB,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI;SACjC,CAAC;QACF,qBAAqB,EAAE,CAAC,2BAA2B,CAAC;QACpD,GAAG;KACJ,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Client-annex GC: the quarterly wholesale replacement of the annex
|
|
6
6
|
* generation, and the collection of everything it leaves behind.
|
|
7
7
|
*
|
|
8
8
|
* The ceremony has two halves with different rhythms:
|
|
@@ -54,7 +54,7 @@ import type { DIDLog } from '@interop/did-method-webvh';
|
|
|
54
54
|
import type { ZcapClient } from '@interop/ezcap';
|
|
55
55
|
import type { WasClient } from '@interop/was-client';
|
|
56
56
|
import type { ResourceLogPinStore } from '../resourceLog/pin.js';
|
|
57
|
-
import type { ClientWebvhUpdateKeys, PublishedWebvhLog, WebvhIdStore } from '
|
|
57
|
+
import type { ClientWebvhUpdateKeys, PublishedWebvhLog, WebvhIdStore } from '../webvh/didWebvh.js';
|
|
58
58
|
/**
|
|
59
59
|
* The fixed GC cadence: a generation is replaced at the first durable login
|
|
60
60
|
* 90 days after the current pointer value was established. Wallet GC policy
|
|
@@ -82,7 +82,7 @@ export declare const GENERATION_QUIET_GRACE_MS: number;
|
|
|
82
82
|
/**
|
|
83
83
|
* The `versionTime` of the account-log entry that established the CURRENT
|
|
84
84
|
* `#DelegatedClients` pointer value: the newest entry whose state names a
|
|
85
|
-
* different
|
|
85
|
+
* different annex DID than the entry before it (or the first entry, when
|
|
86
86
|
* the pointer has been there since genesis). This is the cadence's clock --
|
|
87
87
|
* "the pointer-update entry is the record" -- and it is read off the log a
|
|
88
88
|
* durable login has already verified, so the cadence costs no extra fetch
|
|
@@ -106,7 +106,7 @@ export declare function delegatedClientsPointerEstablishedAt({ log }: {
|
|
|
106
106
|
* @param [options.now] {number} epoch milliseconds, for tests
|
|
107
107
|
* @returns {boolean}
|
|
108
108
|
*/
|
|
109
|
-
export declare function
|
|
109
|
+
export declare function clientAnnexGcDue({ log, now }: {
|
|
110
110
|
log: DIDLog;
|
|
111
111
|
now?: number;
|
|
112
112
|
}): boolean;
|
|
@@ -119,7 +119,7 @@ export declare function companionGcDue({ log, now }: {
|
|
|
119
119
|
* swap defers rather than abandoning a possibly-live visit.
|
|
120
120
|
*
|
|
121
121
|
* @param options {object}
|
|
122
|
-
* @param options.log {DIDLog} the pointed generation's VERIFIED
|
|
122
|
+
* @param options.log {DIDLog} the pointed generation's VERIFIED annex
|
|
123
123
|
* log
|
|
124
124
|
* @param [options.now] {number} epoch milliseconds, for tests
|
|
125
125
|
* @returns {boolean}
|
|
@@ -131,23 +131,23 @@ export declare function generationQuiet({ log, now }: {
|
|
|
131
131
|
/**
|
|
132
132
|
* What the swap half of one GC pass did. `replaced` is the successful swap;
|
|
133
133
|
* `not-due` and `deferred-live` are the two healthy skips (cadence and quiet
|
|
134
|
-
* bound); `no-pointer` means the account has no
|
|
134
|
+
* bound); `no-pointer` means the account has no annex posture (the whole
|
|
135
135
|
* pass no-ops -- without a pointer there is no auxiliary Space to list);
|
|
136
136
|
* `no-ladder-seed` means the swap was due but the login held no ladder seed
|
|
137
137
|
* to mint with (a non-standing record); `failed` means a swap stage threw --
|
|
138
138
|
* reported in `failed` under the pointed generation's id, with the collect
|
|
139
139
|
* fan-out still run.
|
|
140
140
|
*/
|
|
141
|
-
export type
|
|
141
|
+
export type ClientAnnexGcSwapOutcome = 'replaced' | 'not-due' | 'deferred-live' | 'no-pointer' | 'no-ladder-seed' | 'failed';
|
|
142
142
|
/**
|
|
143
|
-
* One GC pass's report: the swap outcome, the
|
|
143
|
+
* One GC pass's report: the swap outcome, the annex DID the account
|
|
144
144
|
* points at after the pass, the generation ids collected (revoked, digested,
|
|
145
145
|
* deleted), and the per-generation failures. A report with `failed` entries
|
|
146
146
|
* is a resumable success -- the next durable login's pass picks up exactly
|
|
147
147
|
* the generations still listed.
|
|
148
148
|
*/
|
|
149
|
-
export interface
|
|
150
|
-
swap:
|
|
149
|
+
export interface ClientAnnexGcReport {
|
|
150
|
+
swap: ClientAnnexGcSwapOutcome;
|
|
151
151
|
pointedDid?: string;
|
|
152
152
|
collected: string[];
|
|
153
153
|
failed: Array<{
|
|
@@ -156,7 +156,7 @@ export interface CompanionGcReport {
|
|
|
156
156
|
}>;
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* One
|
|
159
|
+
* One annex GC pass: the quarterly swap when due and quiet, then the
|
|
160
160
|
* predicate-driven collect fan-out over every non-pointed `gen-` collection.
|
|
161
161
|
* See the module header for the stage order and its load-bearing constraints.
|
|
162
162
|
*
|
|
@@ -190,14 +190,14 @@ export interface CompanionGcReport {
|
|
|
190
190
|
* delete, and a throw keeps the generation for the next pass
|
|
191
191
|
* @param [options.onCollected] {Function}
|
|
192
192
|
* `({ generationId }) => Promise<void>` -- local cleanup after a
|
|
193
|
-
* generation's delete (the caller's
|
|
193
|
+
* generation's delete (the caller's annex pin-slot drop); a throw is
|
|
194
194
|
* reported but cannot be retried (the collection is already gone)
|
|
195
195
|
* @param [options.pinStore] {ResourceLogPinStore} chain-head pins for the
|
|
196
196
|
* account-log re-point and the pointed generation's read
|
|
197
197
|
* @param [options.now] {number} epoch milliseconds, for tests
|
|
198
|
-
* @returns {Promise<
|
|
198
|
+
* @returns {Promise<ClientAnnexGcReport>}
|
|
199
199
|
*/
|
|
200
|
-
export declare function
|
|
200
|
+
export declare function runClientAnnexGc({ was, wasServerUrl, accountSpaceId, account, idStore, updateKeys, zcapClient, ladderSeed, recordDigest, onCollected, pinStore, now }: {
|
|
201
201
|
was: WasClient;
|
|
202
202
|
wasServerUrl: string;
|
|
203
203
|
accountSpaceId: string;
|
|
@@ -217,5 +217,39 @@ export declare function runCompanionGc({ was, wasServerUrl, accountSpaceId, acco
|
|
|
217
217
|
}) => Promise<void>;
|
|
218
218
|
pinStore?: ResourceLogPinStore;
|
|
219
219
|
now?: number;
|
|
220
|
-
}): Promise<
|
|
221
|
-
|
|
220
|
+
}): Promise<ClientAnnexGcReport>;
|
|
221
|
+
/**
|
|
222
|
+
* AN OFF-CADENCE GENERATION SWAP: replaces the pointed annex generation
|
|
223
|
+
* outside the quarterly rhythm -- the credential-rotation ceremony's
|
|
224
|
+
* fallback when no distinct committed rung can sign a strike entry
|
|
225
|
+
* (`retireClientAnnexRung`): a fresh generation minted from a SURVIVING
|
|
226
|
+
* credential's seed commits only that credential's rung-0 hash, so the
|
|
227
|
+
* retired credential's annex posture dies with the whole generation the
|
|
228
|
+
* moment the re-point lands. The abandoned generation is an ordinary
|
|
229
|
+
* non-pointed `gen-` collection the standing collect fan-out picks up at the
|
|
230
|
+
* next durable login.
|
|
231
|
+
*
|
|
232
|
+
* Same four swap stages and ordering as the quarterly GC swap, minus the
|
|
233
|
+
* cadence and quiet gates (the caller's reason for swapping is authority
|
|
234
|
+
* removal, not hygiene). The pointed generation's log is read for the revoke
|
|
235
|
+
* stage's delegation bytes; unreadable, the revoke is skipped and pointer
|
|
236
|
+
* equality retires the old delegation on a conforming server.
|
|
237
|
+
*
|
|
238
|
+
* @param options {object} see {@link runClientAnnexGc} for the shared
|
|
239
|
+
* members ({ was, wasServerUrl, accountSpaceId, account, idStore,
|
|
240
|
+
* updateKeys, zcapClient, pinStore }); `ladderSeed` here is the SURVIVING
|
|
241
|
+
* credential's seed the fresh generation is minted from
|
|
242
|
+
* @returns {Promise<string>} the fresh annex DID
|
|
243
|
+
*/
|
|
244
|
+
export declare function swapClientAnnexGeneration({ was, wasServerUrl, accountSpaceId, account, idStore, updateKeys, zcapClient, ladderSeed, pinStore }: {
|
|
245
|
+
was: WasClient;
|
|
246
|
+
wasServerUrl: string;
|
|
247
|
+
accountSpaceId: string;
|
|
248
|
+
account: Pick<PublishedWebvhLog, 'did' | 'doc'>;
|
|
249
|
+
idStore: WebvhIdStore;
|
|
250
|
+
updateKeys: ClientWebvhUpdateKeys;
|
|
251
|
+
zcapClient: ZcapClient;
|
|
252
|
+
ladderSeed: Uint8Array;
|
|
253
|
+
pinStore?: ResourceLogPinStore;
|
|
254
|
+
}): Promise<string>;
|
|
255
|
+
//# sourceMappingURL=gc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../src/clientAnnex/gc.ts"],"names":[],"mappings":"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"}
|