@interop/wallet-core 0.48.0 → 0.49.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/dist/space/activity.d.ts +38 -0
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +41 -1
- package/dist/space/activity.js.map +1 -1
- package/dist/space/index.d.ts +1 -1
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +1 -1
- package/dist/space/index.js.map +1 -1
- package/dist/unlock/ladder.d.ts +13 -11
- package/dist/unlock/ladder.d.ts.map +1 -1
- package/dist/unlock/ladder.js +17 -13
- package/dist/unlock/ladder.js.map +1 -1
- package/dist/webvh/companion.d.ts +50 -43
- package/dist/webvh/companion.d.ts.map +1 -1
- package/dist/webvh/companion.js +92 -83
- package/dist/webvh/companion.js.map +1 -1
- package/dist/webvh/companionGc.d.ts +221 -0
- package/dist/webvh/companionGc.d.ts.map +1 -0
- package/dist/webvh/companionGc.js +413 -0
- package/dist/webvh/companionGc.js.map +1 -0
- package/dist/webvh/didWebvh.d.ts +1 -1
- package/dist/webvh/didWebvh.js +1 -1
- package/dist/webvh/index.d.ts +4 -2
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +3 -2
- package/dist/webvh/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Companion GC: the quarterly wholesale replacement of the companion
|
|
6
|
+
* generation, and the collection of everything it leaves behind.
|
|
7
|
+
*
|
|
8
|
+
* The ceremony has two halves with different rhythms:
|
|
9
|
+
*
|
|
10
|
+
* - The SWAP runs on the fixed quarterly cadence (90 days, at the first
|
|
11
|
+
* durable login after the period elapses -- coarse on purpose, so the
|
|
12
|
+
* account log's permanent pointer-entry rhythm reveals little about
|
|
13
|
+
* transient-use frequency), and only when the pointed generation is
|
|
14
|
+
* GC-quiet (the 24-hour max-visit quiet bound over its newest entry's
|
|
15
|
+
* `versionTime`, with a skew-margin grace hour -- a deferral policy only,
|
|
16
|
+
* never a session expiry). Its stage order is fixed: mint + genesis,
|
|
17
|
+
* install the fresh generation's delegation service entry, revoke the old
|
|
18
|
+
* generation's delegation, re-point the account document. Revoke lands
|
|
19
|
+
* before the re-point (closing the window where a fail-open non-conforming
|
|
20
|
+
* server still honors the old delegation -- and the revocation POST itself
|
|
21
|
+
* only verifies while the pointer still makes the old chain resolve), and
|
|
22
|
+
* before the delete (the POST needs the capability bytes the delete
|
|
23
|
+
* destroys).
|
|
24
|
+
*
|
|
25
|
+
* - The COLLECT fan-out is predicate-driven and runs at every durable login:
|
|
26
|
+
* every `gen-` collection the pointer does not name -- the generation a
|
|
27
|
+
* swap just superseded, a torn GC's leftover, a torn signup's orphan, a
|
|
28
|
+
* double-genesis loser -- gets identical treatment (revoke its embedded
|
|
29
|
+
* delegation blind, reading the server's 400 already-revoked answer as
|
|
30
|
+
* success; write the digest; delete), so a GC torn anywhere resumes at the
|
|
31
|
+
* next login instead of waiting a quarter. Failures are collected per
|
|
32
|
+
* generation and never abort the fan-out: a partial pass is a resumable
|
|
33
|
+
* success.
|
|
34
|
+
*
|
|
35
|
+
* The completion predicate is durable state alone (exactly one `gen-`
|
|
36
|
+
* collection exists in the auxiliary Space and it is the one the pointer
|
|
37
|
+
* names); no marker resource exists anywhere -- the account document's
|
|
38
|
+
* pointer-update entry is the record, and the cadence is read off its
|
|
39
|
+
* `versionTime`. The digest (`GenerationCollect`, built by the caller's
|
|
40
|
+
* `recordDigest` over `@interop/wallet-core/space`'s builder) is written
|
|
41
|
+
* before the delete: it is the owner's only record of the collected window's
|
|
42
|
+
* visits surviving the delete, and compromise detection ends at digest
|
|
43
|
+
* granularity.
|
|
44
|
+
*
|
|
45
|
+
* Honest limitations: the "no unexpired delegation names a dead generation"
|
|
46
|
+
* conjunct is an ordering obligation, not a check (the revocation protocol
|
|
47
|
+
* exposes no read endpoint, and the dead generation's delegation bytes are
|
|
48
|
+
* destroyed with its collection); orphaned generations are
|
|
49
|
+
* authorization-inert (no delegation ever names an unpointed generation
|
|
50
|
+
* under pointer equality), so what accretes between passes is a storage
|
|
51
|
+
* leak, never an authority leak.
|
|
52
|
+
*/
|
|
53
|
+
import type { DIDLog } from '@interop/did-method-webvh';
|
|
54
|
+
import type { ZcapClient } from '@interop/ezcap';
|
|
55
|
+
import type { WasClient } from '@interop/was-client';
|
|
56
|
+
import type { ResourceLogPinStore } from '../resourceLog/pin.js';
|
|
57
|
+
import type { ClientWebvhUpdateKeys, PublishedWebvhLog, WebvhIdStore } from './didWebvh.js';
|
|
58
|
+
/**
|
|
59
|
+
* The fixed GC cadence: a generation is replaced at the first durable login
|
|
60
|
+
* 90 days after the current pointer value was established. Wallet GC policy
|
|
61
|
+
* over the account log's own timestamps, never a stored or wire value.
|
|
62
|
+
*/
|
|
63
|
+
export declare const GENERATION_GC_PERIOD_MS: number;
|
|
64
|
+
/**
|
|
65
|
+
* The quiet bound: a generation is GC-quiet when its newest entry's
|
|
66
|
+
* `versionTime` is over 24 hours old. The bound defers the swap only; it
|
|
67
|
+
* never expires a session. A visit outliving it merely loses guaranteed
|
|
68
|
+
* guard protection, and in the rare case a quarterly pass lands on one, the
|
|
69
|
+
* session's next authorization failure maps to the generation-lapse retry
|
|
70
|
+
* state.
|
|
71
|
+
*/
|
|
72
|
+
export declare const GENERATION_QUIET_BOUND_MS: number;
|
|
73
|
+
/**
|
|
74
|
+
* The skew-margin grace floor on the quiet bound: three clocks meet at the
|
|
75
|
+
* guard check (the enrolling writer's, any prior entry writer's, and the
|
|
76
|
+
* GC-running client's), and `versionTime` is asserted by the writer's clock,
|
|
77
|
+
* so the guard compares against the bound plus this margin. An hour is
|
|
78
|
+
* generous against real-world skew and defers the swap by at most an hour
|
|
79
|
+
* against a quarterly cadence.
|
|
80
|
+
*/
|
|
81
|
+
export declare const GENERATION_QUIET_GRACE_MS: number;
|
|
82
|
+
/**
|
|
83
|
+
* The `versionTime` of the account-log entry that established the CURRENT
|
|
84
|
+
* `#DelegatedClients` pointer value: the newest entry whose state names a
|
|
85
|
+
* different companion DID than the entry before it (or the first entry, when
|
|
86
|
+
* the pointer has been there since genesis). This is the cadence's clock --
|
|
87
|
+
* "the pointer-update entry is the record" -- and it is read off the log a
|
|
88
|
+
* durable login has already verified, so the cadence costs no extra fetch
|
|
89
|
+
* and every enrolled client agrees on it.
|
|
90
|
+
*
|
|
91
|
+
* @param options {object}
|
|
92
|
+
* @param options.log {DIDLog} the VERIFIED account log
|
|
93
|
+
* @returns {string | undefined} the establishing entry's `versionTime`,
|
|
94
|
+
* or undefined when no entry carries a pointer
|
|
95
|
+
*/
|
|
96
|
+
export declare function delegatedClientsPointerEstablishedAt({ log }: {
|
|
97
|
+
log: DIDLog;
|
|
98
|
+
}): string | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Whether the quarterly swap is due: the current pointer value was
|
|
101
|
+
* established {@link GENERATION_GC_PERIOD_MS} or more ago. A log with no
|
|
102
|
+
* pointer is never due (there is no generation to replace).
|
|
103
|
+
*
|
|
104
|
+
* @param options {object}
|
|
105
|
+
* @param options.log {DIDLog} the VERIFIED account log
|
|
106
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
*/
|
|
109
|
+
export declare function companionGcDue({ log, now }: {
|
|
110
|
+
log: DIDLog;
|
|
111
|
+
now?: number;
|
|
112
|
+
}): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* The live-entry guard: whether a generation is GC-quiet -- its newest
|
|
115
|
+
* entry's `versionTime` is older than the quiet bound plus the skew grace
|
|
116
|
+
* margin. Applies to the POINTED generation only (an unpointed generation
|
|
117
|
+
* authorizes nothing under pointer equality, so nothing inside it ever
|
|
118
|
+
* defers deletion). An unparseable `versionTime` reads as not quiet: the
|
|
119
|
+
* swap defers rather than abandoning a possibly-live visit.
|
|
120
|
+
*
|
|
121
|
+
* @param options {object}
|
|
122
|
+
* @param options.log {DIDLog} the pointed generation's VERIFIED companion
|
|
123
|
+
* log
|
|
124
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
125
|
+
* @returns {boolean}
|
|
126
|
+
*/
|
|
127
|
+
export declare function generationQuiet({ log, now }: {
|
|
128
|
+
log: DIDLog;
|
|
129
|
+
now?: number;
|
|
130
|
+
}): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* What the swap half of one GC pass did. `replaced` is the successful swap;
|
|
133
|
+
* `not-due` and `deferred-live` are the two healthy skips (cadence and quiet
|
|
134
|
+
* bound); `no-pointer` means the account has no companion posture (the whole
|
|
135
|
+
* pass no-ops -- without a pointer there is no auxiliary Space to list);
|
|
136
|
+
* `no-ladder-seed` means the swap was due but the login held no ladder seed
|
|
137
|
+
* to mint with (a non-standing record); `failed` means a swap stage threw --
|
|
138
|
+
* reported in `failed` under the pointed generation's id, with the collect
|
|
139
|
+
* fan-out still run.
|
|
140
|
+
*/
|
|
141
|
+
export type CompanionGcSwapOutcome = 'replaced' | 'not-due' | 'deferred-live' | 'no-pointer' | 'no-ladder-seed' | 'failed';
|
|
142
|
+
/**
|
|
143
|
+
* One GC pass's report: the swap outcome, the companion DID the account
|
|
144
|
+
* points at after the pass, the generation ids collected (revoked, digested,
|
|
145
|
+
* deleted), and the per-generation failures. A report with `failed` entries
|
|
146
|
+
* is a resumable success -- the next durable login's pass picks up exactly
|
|
147
|
+
* the generations still listed.
|
|
148
|
+
*/
|
|
149
|
+
export interface CompanionGcReport {
|
|
150
|
+
swap: CompanionGcSwapOutcome;
|
|
151
|
+
pointedDid?: string;
|
|
152
|
+
collected: string[];
|
|
153
|
+
failed: Array<{
|
|
154
|
+
generationId: string;
|
|
155
|
+
error: unknown;
|
|
156
|
+
}>;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* One companion GC pass: the quarterly swap when due and quiet, then the
|
|
160
|
+
* predicate-driven collect fan-out over every non-pointed `gen-` collection.
|
|
161
|
+
* See the module header for the stage order and its load-bearing constraints.
|
|
162
|
+
*
|
|
163
|
+
* Convergence: every stage detects completion from durable state. A re-run
|
|
164
|
+
* after a tear re-POSTs the revocation blind (400 already-revoked reads as
|
|
165
|
+
* success), re-writes the digest (the deterministic payload id collapses the
|
|
166
|
+
* second row at read time), and re-runs the idempotent delete; a swap torn
|
|
167
|
+
* before its re-point leaves an unpointed fresh generation the same fan-out
|
|
168
|
+
* collects.
|
|
169
|
+
*
|
|
170
|
+
* @param options {object}
|
|
171
|
+
* @param options.was {WasClient} the storage client, signing as an
|
|
172
|
+
* enrolled client (root tier on both the account and auxiliary Spaces)
|
|
173
|
+
* @param options.wasServerUrl {string} the account pointer's host
|
|
174
|
+
* @param options.accountSpaceId {string} the ACCOUNT Space's id (the
|
|
175
|
+
* generation delegation's target subtree)
|
|
176
|
+
* @param options.account {object} the VERIFIED account log
|
|
177
|
+
* (`{ did, doc, log }` -- `verifyAccountLog`'s shape)
|
|
178
|
+
* @param options.idStore {WebvhIdStore} the account log's id store, for
|
|
179
|
+
* the re-point
|
|
180
|
+
* @param options.updateKeys {ClientWebvhUpdateKeys} this enrolled client's
|
|
181
|
+
* update keys, signing the re-point entry
|
|
182
|
+
* @param options.zcapClient {ZcapClient} signs the fresh generation
|
|
183
|
+
* delegation (the promoted account keyId)
|
|
184
|
+
* @param [options.ladderSeed] {Uint8Array} the login credential's ladder
|
|
185
|
+
* seed; absent, a due swap reports `no-ladder-seed` and only the collect
|
|
186
|
+
* fan-out runs
|
|
187
|
+
* @param options.recordDigest {Function}
|
|
188
|
+
* `({ generationId, firstEntry, lastEntry, entryCount }) => Promise<void>`
|
|
189
|
+
* -- writes the GenerationCollect wallet-activity row; called before the
|
|
190
|
+
* delete, and a throw keeps the generation for the next pass
|
|
191
|
+
* @param [options.onCollected] {Function}
|
|
192
|
+
* `({ generationId }) => Promise<void>` -- local cleanup after a
|
|
193
|
+
* generation's delete (the caller's companion pin-slot drop); a throw is
|
|
194
|
+
* reported but cannot be retried (the collection is already gone)
|
|
195
|
+
* @param [options.pinStore] {ResourceLogPinStore} chain-head pins for the
|
|
196
|
+
* account-log re-point and the pointed generation's read
|
|
197
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
198
|
+
* @returns {Promise<CompanionGcReport>}
|
|
199
|
+
*/
|
|
200
|
+
export declare function runCompanionGc({ was, wasServerUrl, accountSpaceId, account, idStore, updateKeys, zcapClient, ladderSeed, recordDigest, onCollected, pinStore, now }: {
|
|
201
|
+
was: WasClient;
|
|
202
|
+
wasServerUrl: string;
|
|
203
|
+
accountSpaceId: string;
|
|
204
|
+
account: Pick<PublishedWebvhLog, 'did' | 'doc' | 'log'>;
|
|
205
|
+
idStore: WebvhIdStore;
|
|
206
|
+
updateKeys: ClientWebvhUpdateKeys;
|
|
207
|
+
zcapClient: ZcapClient;
|
|
208
|
+
ladderSeed?: Uint8Array;
|
|
209
|
+
recordDigest: (digest: {
|
|
210
|
+
generationId: string;
|
|
211
|
+
firstEntry?: string;
|
|
212
|
+
lastEntry?: string;
|
|
213
|
+
entryCount?: number;
|
|
214
|
+
}) => Promise<void>;
|
|
215
|
+
onCollected?: (options: {
|
|
216
|
+
generationId: string;
|
|
217
|
+
}) => Promise<void>;
|
|
218
|
+
pinStore?: ResourceLogPinStore;
|
|
219
|
+
now?: number;
|
|
220
|
+
}): Promise<CompanionGcReport>;
|
|
221
|
+
//# sourceMappingURL=companionGc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companionGc.d.ts","sourceRoot":"","sources":["../../src/webvh/companionGc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { companionDidParts, companionLogPinId, companionLogStore, delegatedClientsPointer, embeddedGenerationDelegation, ensureGenerationDelegationCurrent, GENERATION_ID_PREFIX, mintCredentialCompanionGeneration, mintGenerationDelegation, setDelegatedClientsPointer } from './companion.js';
|
|
2
|
+
import { readPublishedLog } from './didWebvh.js';
|
|
3
|
+
import { accountLogPinId } from './verifyLog.js';
|
|
4
|
+
/**
|
|
5
|
+
* The fixed GC cadence: a generation is replaced at the first durable login
|
|
6
|
+
* 90 days after the current pointer value was established. Wallet GC policy
|
|
7
|
+
* over the account log's own timestamps, never a stored or wire value.
|
|
8
|
+
*/
|
|
9
|
+
export const GENERATION_GC_PERIOD_MS = 90 * 24 * 60 * 60 * 1000;
|
|
10
|
+
/**
|
|
11
|
+
* The quiet bound: a generation is GC-quiet when its newest entry's
|
|
12
|
+
* `versionTime` is over 24 hours old. The bound defers the swap only; it
|
|
13
|
+
* never expires a session. A visit outliving it merely loses guaranteed
|
|
14
|
+
* guard protection, and in the rare case a quarterly pass lands on one, the
|
|
15
|
+
* session's next authorization failure maps to the generation-lapse retry
|
|
16
|
+
* state.
|
|
17
|
+
*/
|
|
18
|
+
export const GENERATION_QUIET_BOUND_MS = 24 * 60 * 60 * 1000;
|
|
19
|
+
/**
|
|
20
|
+
* The skew-margin grace floor on the quiet bound: three clocks meet at the
|
|
21
|
+
* guard check (the enrolling writer's, any prior entry writer's, and the
|
|
22
|
+
* GC-running client's), and `versionTime` is asserted by the writer's clock,
|
|
23
|
+
* so the guard compares against the bound plus this margin. An hour is
|
|
24
|
+
* generous against real-world skew and defers the swap by at most an hour
|
|
25
|
+
* against a quarterly cadence.
|
|
26
|
+
*/
|
|
27
|
+
export const GENERATION_QUIET_GRACE_MS = 60 * 60 * 1000;
|
|
28
|
+
/**
|
|
29
|
+
* The `versionTime` of the account-log entry that established the CURRENT
|
|
30
|
+
* `#DelegatedClients` pointer value: the newest entry whose state names a
|
|
31
|
+
* different companion DID than the entry before it (or the first entry, when
|
|
32
|
+
* the pointer has been there since genesis). This is the cadence's clock --
|
|
33
|
+
* "the pointer-update entry is the record" -- and it is read off the log a
|
|
34
|
+
* durable login has already verified, so the cadence costs no extra fetch
|
|
35
|
+
* and every enrolled client agrees on it.
|
|
36
|
+
*
|
|
37
|
+
* @param options {object}
|
|
38
|
+
* @param options.log {DIDLog} the VERIFIED account log
|
|
39
|
+
* @returns {string | undefined} the establishing entry's `versionTime`,
|
|
40
|
+
* or undefined when no entry carries a pointer
|
|
41
|
+
*/
|
|
42
|
+
export function delegatedClientsPointerEstablishedAt({ log }) {
|
|
43
|
+
let establishedAt;
|
|
44
|
+
let previous;
|
|
45
|
+
for (const entry of log) {
|
|
46
|
+
const pointed = delegatedClientsPointer({ doc: entry.state });
|
|
47
|
+
if (pointed !== undefined && pointed !== previous) {
|
|
48
|
+
establishedAt = entry.versionTime;
|
|
49
|
+
}
|
|
50
|
+
if (pointed === undefined) {
|
|
51
|
+
// A document with no pointer has no companion posture; a later entry
|
|
52
|
+
// restoring one establishes afresh.
|
|
53
|
+
establishedAt = undefined;
|
|
54
|
+
}
|
|
55
|
+
previous = pointed;
|
|
56
|
+
}
|
|
57
|
+
return establishedAt;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Whether the quarterly swap is due: the current pointer value was
|
|
61
|
+
* established {@link GENERATION_GC_PERIOD_MS} or more ago. A log with no
|
|
62
|
+
* pointer is never due (there is no generation to replace).
|
|
63
|
+
*
|
|
64
|
+
* @param options {object}
|
|
65
|
+
* @param options.log {DIDLog} the VERIFIED account log
|
|
66
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
export function companionGcDue({ log, now = Date.now() }) {
|
|
70
|
+
const establishedAt = delegatedClientsPointerEstablishedAt({ log });
|
|
71
|
+
if (establishedAt === undefined) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const establishedMs = Date.parse(establishedAt);
|
|
75
|
+
return (Number.isFinite(establishedMs) &&
|
|
76
|
+
now - establishedMs >= GENERATION_GC_PERIOD_MS);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The live-entry guard: whether a generation is GC-quiet -- its newest
|
|
80
|
+
* entry's `versionTime` is older than the quiet bound plus the skew grace
|
|
81
|
+
* margin. Applies to the POINTED generation only (an unpointed generation
|
|
82
|
+
* authorizes nothing under pointer equality, so nothing inside it ever
|
|
83
|
+
* defers deletion). An unparseable `versionTime` reads as not quiet: the
|
|
84
|
+
* swap defers rather than abandoning a possibly-live visit.
|
|
85
|
+
*
|
|
86
|
+
* @param options {object}
|
|
87
|
+
* @param options.log {DIDLog} the pointed generation's VERIFIED companion
|
|
88
|
+
* log
|
|
89
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
90
|
+
* @returns {boolean}
|
|
91
|
+
*/
|
|
92
|
+
export function generationQuiet({ log, now = Date.now() }) {
|
|
93
|
+
const newest = log[log.length - 1]?.versionTime;
|
|
94
|
+
if (newest === undefined) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const newestMs = Date.parse(newest);
|
|
98
|
+
return (Number.isFinite(newestMs) &&
|
|
99
|
+
now - newestMs >= GENERATION_QUIET_BOUND_MS + GENERATION_QUIET_GRACE_MS);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* One companion GC pass: the quarterly swap when due and quiet, then the
|
|
103
|
+
* predicate-driven collect fan-out over every non-pointed `gen-` collection.
|
|
104
|
+
* See the module header for the stage order and its load-bearing constraints.
|
|
105
|
+
*
|
|
106
|
+
* Convergence: every stage detects completion from durable state. A re-run
|
|
107
|
+
* after a tear re-POSTs the revocation blind (400 already-revoked reads as
|
|
108
|
+
* success), re-writes the digest (the deterministic payload id collapses the
|
|
109
|
+
* second row at read time), and re-runs the idempotent delete; a swap torn
|
|
110
|
+
* before its re-point leaves an unpointed fresh generation the same fan-out
|
|
111
|
+
* collects.
|
|
112
|
+
*
|
|
113
|
+
* @param options {object}
|
|
114
|
+
* @param options.was {WasClient} the storage client, signing as an
|
|
115
|
+
* enrolled client (root tier on both the account and auxiliary Spaces)
|
|
116
|
+
* @param options.wasServerUrl {string} the account pointer's host
|
|
117
|
+
* @param options.accountSpaceId {string} the ACCOUNT Space's id (the
|
|
118
|
+
* generation delegation's target subtree)
|
|
119
|
+
* @param options.account {object} the VERIFIED account log
|
|
120
|
+
* (`{ did, doc, log }` -- `verifyAccountLog`'s shape)
|
|
121
|
+
* @param options.idStore {WebvhIdStore} the account log's id store, for
|
|
122
|
+
* the re-point
|
|
123
|
+
* @param options.updateKeys {ClientWebvhUpdateKeys} this enrolled client's
|
|
124
|
+
* update keys, signing the re-point entry
|
|
125
|
+
* @param options.zcapClient {ZcapClient} signs the fresh generation
|
|
126
|
+
* delegation (the promoted account keyId)
|
|
127
|
+
* @param [options.ladderSeed] {Uint8Array} the login credential's ladder
|
|
128
|
+
* seed; absent, a due swap reports `no-ladder-seed` and only the collect
|
|
129
|
+
* fan-out runs
|
|
130
|
+
* @param options.recordDigest {Function}
|
|
131
|
+
* `({ generationId, firstEntry, lastEntry, entryCount }) => Promise<void>`
|
|
132
|
+
* -- writes the GenerationCollect wallet-activity row; called before the
|
|
133
|
+
* delete, and a throw keeps the generation for the next pass
|
|
134
|
+
* @param [options.onCollected] {Function}
|
|
135
|
+
* `({ generationId }) => Promise<void>` -- local cleanup after a
|
|
136
|
+
* generation's delete (the caller's companion pin-slot drop); a throw is
|
|
137
|
+
* reported but cannot be retried (the collection is already gone)
|
|
138
|
+
* @param [options.pinStore] {ResourceLogPinStore} chain-head pins for the
|
|
139
|
+
* account-log re-point and the pointed generation's read
|
|
140
|
+
* @param [options.now] {number} epoch milliseconds, for tests
|
|
141
|
+
* @returns {Promise<CompanionGcReport>}
|
|
142
|
+
*/
|
|
143
|
+
export async function runCompanionGc({ was, wasServerUrl, accountSpaceId, account, idStore, updateKeys, zcapClient, ladderSeed, recordDigest, onCollected, pinStore, now = Date.now() }) {
|
|
144
|
+
const pointedDid = delegatedClientsPointer({ doc: account.doc });
|
|
145
|
+
if (pointedDid === undefined) {
|
|
146
|
+
return { swap: 'no-pointer', collected: [], failed: [] };
|
|
147
|
+
}
|
|
148
|
+
const { spaceId } = companionDidParts({ did: pointedDid });
|
|
149
|
+
const failed = [];
|
|
150
|
+
// 1. The swap, when the quarterly cadence is due. Its own failure is
|
|
151
|
+
// collected under the pointed generation's id rather than aborting the
|
|
152
|
+
// pass: the collect fan-out below still cleans what it can, and the next
|
|
153
|
+
// durable login re-attempts the swap from durable state.
|
|
154
|
+
let swap = 'not-due';
|
|
155
|
+
let currentDid = pointedDid;
|
|
156
|
+
if (companionGcDue({ log: account.log, now })) {
|
|
157
|
+
swap =
|
|
158
|
+
ladderSeed === undefined
|
|
159
|
+
? 'no-ladder-seed'
|
|
160
|
+
: await (async () => {
|
|
161
|
+
const oldParts = companionDidParts({ did: pointedDid });
|
|
162
|
+
try {
|
|
163
|
+
const old = await readCompanionGeneration({
|
|
164
|
+
was,
|
|
165
|
+
spaceId,
|
|
166
|
+
generationId: oldParts.generationId,
|
|
167
|
+
expectedDid: pointedDid,
|
|
168
|
+
pinStore
|
|
169
|
+
});
|
|
170
|
+
if (old === undefined ||
|
|
171
|
+
!generationQuiet({ log: old.log, now })) {
|
|
172
|
+
// A missing pointed log is a broken state the collect
|
|
173
|
+
// fan-out cannot touch (the pointer still names it); defer
|
|
174
|
+
// rather than swap onto a generation this pass could not
|
|
175
|
+
// read as quiet.
|
|
176
|
+
return old === undefined ? 'failed' : 'deferred-live';
|
|
177
|
+
}
|
|
178
|
+
currentDid = await replaceCompanionGeneration({
|
|
179
|
+
was,
|
|
180
|
+
wasServerUrl,
|
|
181
|
+
accountSpaceId,
|
|
182
|
+
account,
|
|
183
|
+
idStore,
|
|
184
|
+
updateKeys,
|
|
185
|
+
zcapClient,
|
|
186
|
+
ladderSeed,
|
|
187
|
+
companionSpaceId: spaceId,
|
|
188
|
+
oldGeneration: old,
|
|
189
|
+
pinStore
|
|
190
|
+
});
|
|
191
|
+
return 'replaced';
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
failed.push({ generationId: oldParts.generationId, error: err });
|
|
195
|
+
return 'failed';
|
|
196
|
+
}
|
|
197
|
+
})();
|
|
198
|
+
}
|
|
199
|
+
// 2. The collect fan-out: every `gen-` collection the (possibly fresh)
|
|
200
|
+
// pointer does not name. Orphan discovery is a plain prefix match over the
|
|
201
|
+
// auxiliary Space's collection listing -- no registry of generations
|
|
202
|
+
// exists anywhere -- and a torn GC's old generation, a torn signup's
|
|
203
|
+
// orphan, and a double-genesis loser get identical treatment.
|
|
204
|
+
const currentGenerationId = companionDidParts({
|
|
205
|
+
did: currentDid
|
|
206
|
+
}).generationId;
|
|
207
|
+
const space = was.space(spaceId);
|
|
208
|
+
const stale = [];
|
|
209
|
+
for await (const page of space.collectionsPages()) {
|
|
210
|
+
for (const item of page.items) {
|
|
211
|
+
if (item.id.startsWith(GENERATION_ID_PREFIX) &&
|
|
212
|
+
item.id !== currentGenerationId) {
|
|
213
|
+
stale.push(item.id);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const collected = [];
|
|
218
|
+
await Promise.all(stale.map(async (generationId) => {
|
|
219
|
+
try {
|
|
220
|
+
await collectOneGeneration({
|
|
221
|
+
was,
|
|
222
|
+
spaceId,
|
|
223
|
+
generationId,
|
|
224
|
+
recordDigest,
|
|
225
|
+
onCollected
|
|
226
|
+
});
|
|
227
|
+
collected.push(generationId);
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
failed.push({ generationId, error: err });
|
|
231
|
+
}
|
|
232
|
+
}));
|
|
233
|
+
return { swap, pointedDid: currentDid, collected, failed };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Reads and verifies one generation's published companion log, or resolves
|
|
237
|
+
* undefined when its `did.jsonl` does not exist (a generation that never
|
|
238
|
+
* finished minting, or whose collection outlived a torn delete).
|
|
239
|
+
*
|
|
240
|
+
* @param options {object}
|
|
241
|
+
* @param options.was {WasClient}
|
|
242
|
+
* @param options.spaceId {string} the auxiliary companion Space's id
|
|
243
|
+
* @param options.generationId {string}
|
|
244
|
+
* @param [options.expectedDid] {string}
|
|
245
|
+
* @param [options.pinStore] {ResourceLogPinStore}
|
|
246
|
+
* @returns {Promise<PublishedWebvhLog | undefined>}
|
|
247
|
+
*/
|
|
248
|
+
async function readCompanionGeneration({ was, spaceId, generationId, expectedDid, pinStore }) {
|
|
249
|
+
const store = companionLogStore({ was, spaceId, generationId });
|
|
250
|
+
return readPublishedLog({
|
|
251
|
+
idStore: store,
|
|
252
|
+
...(expectedDid !== undefined ? { expectedDid } : {}),
|
|
253
|
+
...(pinStore !== undefined
|
|
254
|
+
? { pinStore, logId: companionLogPinId({ spaceId, generationId }) }
|
|
255
|
+
: {})
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The swap's four stages, in the fixed order: mint + genesis; install the
|
|
260
|
+
* fresh generation's delegation service entry; revoke the old generation's
|
|
261
|
+
* delegation; re-point the account document. Returns the fresh companion
|
|
262
|
+
* DID. The digest and the delete are deliberately NOT here -- once the
|
|
263
|
+
* re-point lands, the old generation is an ordinary non-pointed `gen-`
|
|
264
|
+
* collection and the standing collect fan-out handles it, which is also
|
|
265
|
+
* what makes a swap torn after its re-point resume for free.
|
|
266
|
+
*
|
|
267
|
+
* @param options {object} see {@link runCompanionGc}, plus:
|
|
268
|
+
* @param options.companionSpaceId {string} the auxiliary Space's id
|
|
269
|
+
* @param options.oldGeneration {PublishedWebvhLog} the pointed
|
|
270
|
+
* generation's verified log, read by the quiet check
|
|
271
|
+
* @returns {Promise<string>} the fresh companion DID
|
|
272
|
+
*/
|
|
273
|
+
async function replaceCompanionGeneration({ was, wasServerUrl, accountSpaceId, account, idStore, updateKeys, zcapClient, ladderSeed, companionSpaceId, oldGeneration, pinStore }) {
|
|
274
|
+
// 1. Mint + genesis: a fresh generation in the existing auxiliary Space
|
|
275
|
+
// (the typed-Space ensure no-ops on it; the controller argument is only
|
|
276
|
+
// read when the Space does not exist). The genesis commits the minting
|
|
277
|
+
// credential's rung-0 hash for the fresh generation id.
|
|
278
|
+
const minted = await mintCredentialCompanionGeneration({
|
|
279
|
+
was,
|
|
280
|
+
wasServerUrl,
|
|
281
|
+
spaceId: companionSpaceId,
|
|
282
|
+
controller: account.did,
|
|
283
|
+
ladderSeed
|
|
284
|
+
});
|
|
285
|
+
// 2. Install the fresh generation's delegation service entry (the
|
|
286
|
+
// install-when-absent half of the renew-precedes-mint helper), the
|
|
287
|
+
// delegation signed by this enrolled client's promoted account key and the
|
|
288
|
+
// installing companion entry by the credential's rung 0.
|
|
289
|
+
await ensureGenerationDelegationCurrent({
|
|
290
|
+
store: companionLogStore({
|
|
291
|
+
was,
|
|
292
|
+
spaceId: companionSpaceId,
|
|
293
|
+
generationId: minted.generationId
|
|
294
|
+
}),
|
|
295
|
+
ladderSeed,
|
|
296
|
+
generationId: minted.generationId,
|
|
297
|
+
mintGenerationDelegation: async ({ companionDid }) => mintGenerationDelegation({
|
|
298
|
+
zcapClient,
|
|
299
|
+
wasServerUrl,
|
|
300
|
+
spaceId: accountSpaceId,
|
|
301
|
+
companionDid
|
|
302
|
+
}),
|
|
303
|
+
expectedDid: minted.did,
|
|
304
|
+
...(pinStore !== undefined
|
|
305
|
+
? {
|
|
306
|
+
pinStore,
|
|
307
|
+
logId: companionLogPinId({
|
|
308
|
+
spaceId: companionSpaceId,
|
|
309
|
+
generationId: minted.generationId
|
|
310
|
+
})
|
|
311
|
+
}
|
|
312
|
+
: {})
|
|
313
|
+
});
|
|
314
|
+
// 3. Revoke the old generation's delegation, before the re-point (the
|
|
315
|
+
// revocation POST verifies against the currently resolved document, so it
|
|
316
|
+
// only chains while the pointer still names the old generation) and
|
|
317
|
+
// before the delete (the POST needs bytes the delete destroys).
|
|
318
|
+
const oldDelegation = embeddedGenerationDelegation({ doc: oldGeneration.doc });
|
|
319
|
+
if (oldDelegation !== undefined) {
|
|
320
|
+
await revokeTreatingAlreadyRevokedAsSuccess({
|
|
321
|
+
was,
|
|
322
|
+
delegation: oldDelegation
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
// 4. Re-point the account document at the fresh generation. On a
|
|
326
|
+
// conforming server the pointer equality itself kills the old
|
|
327
|
+
// generation's delegations; the explicit revoke above covered the
|
|
328
|
+
// fail-open case.
|
|
329
|
+
await setDelegatedClientsPointer({
|
|
330
|
+
idStore,
|
|
331
|
+
updateKeys,
|
|
332
|
+
companionDid: minted.did,
|
|
333
|
+
expectedDid: account.did,
|
|
334
|
+
...(pinStore !== undefined
|
|
335
|
+
? { pinStore, logId: accountLogPinId({ spaceId: accountSpaceId }) }
|
|
336
|
+
: {})
|
|
337
|
+
});
|
|
338
|
+
return minted.did;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Collects one non-pointed generation: revoke its embedded delegation
|
|
342
|
+
* (blind; the server's 400 already-revoked answer reads as success), write
|
|
343
|
+
* the digest from its verified log, delete the collection, then the
|
|
344
|
+
* caller's local cleanup. A generation whose `did.jsonl` does not exist
|
|
345
|
+
* held no visits and is deleted without a digest row; one whose log exists
|
|
346
|
+
* but fails verification is kept and reported (deleting it would destroy
|
|
347
|
+
* the evidence of tampering).
|
|
348
|
+
*
|
|
349
|
+
* @param options {object}
|
|
350
|
+
* @param options.was {WasClient}
|
|
351
|
+
* @param options.spaceId {string}
|
|
352
|
+
* @param options.generationId {string}
|
|
353
|
+
* @param options.recordDigest {Function} see {@link runCompanionGc}
|
|
354
|
+
* @param [options.onCollected] {Function} see {@link runCompanionGc}
|
|
355
|
+
* @returns {Promise<void>}
|
|
356
|
+
*/
|
|
357
|
+
async function collectOneGeneration({ was, spaceId, generationId, recordDigest, onCollected }) {
|
|
358
|
+
// No pin, no expectedDid: an orphan was possibly never pointed from this
|
|
359
|
+
// client, and its chain-head slot is about to be dropped either way. The
|
|
360
|
+
// log still fully verifies (hash chain, prerotation, rung signatures) --
|
|
361
|
+
// the digest quotes only a log that resolves.
|
|
362
|
+
const published = await readCompanionGeneration({
|
|
363
|
+
was,
|
|
364
|
+
spaceId,
|
|
365
|
+
generationId
|
|
366
|
+
});
|
|
367
|
+
if (published !== undefined) {
|
|
368
|
+
const oldDelegation = embeddedGenerationDelegation({ doc: published.doc });
|
|
369
|
+
if (oldDelegation !== undefined) {
|
|
370
|
+
await revokeTreatingAlreadyRevokedAsSuccess({
|
|
371
|
+
was,
|
|
372
|
+
delegation: oldDelegation
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
// The digest, strictly before the delete: the delete destroys the
|
|
376
|
+
// owner's only per-entry record of the window's visits, so a digest
|
|
377
|
+
// that cannot be written keeps the generation for the next pass.
|
|
378
|
+
await recordDigest({
|
|
379
|
+
generationId,
|
|
380
|
+
firstEntry: published.log[0]?.versionTime,
|
|
381
|
+
lastEntry: published.log[published.log.length - 1]?.versionTime,
|
|
382
|
+
entryCount: published.log.length
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
// Idempotent: a re-run's delete of an already-deleted collection resolves.
|
|
386
|
+
await was.space(spaceId).collection(generationId).delete();
|
|
387
|
+
await onCollected?.({ generationId });
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Submits the revocation of a generation delegation, reading the server's
|
|
391
|
+
* 400 answer as success: an already-revoked chain (a resumed GC's blind
|
|
392
|
+
* re-POST) and an expired delegation (which no longer needs revoking) both
|
|
393
|
+
* land there, and the revocation protocol exposes no read endpoint to
|
|
394
|
+
* distinguish them beforehand. Matched on `err.name` -- error classes do not
|
|
395
|
+
* survive crossing package copies.
|
|
396
|
+
*
|
|
397
|
+
* @param options {object}
|
|
398
|
+
* @param options.was {WasClient}
|
|
399
|
+
* @param options.delegation {IZcap}
|
|
400
|
+
* @returns {Promise<void>}
|
|
401
|
+
*/
|
|
402
|
+
async function revokeTreatingAlreadyRevokedAsSuccess({ was, delegation }) {
|
|
403
|
+
try {
|
|
404
|
+
await was.revoke(delegation);
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
if (err.name === 'ValidationError') {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
throw err;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
//# sourceMappingURL=companionGc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companionGc.js","sourceRoot":"","sources":["../../src/webvh/companionGc.ts"],"names":[],"mappings":"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"}
|
package/dist/webvh/didWebvh.d.ts
CHANGED
|
@@ -288,7 +288,7 @@ export type DidWebKeyMapV2 = DidWebKeyMap & {
|
|
|
288
288
|
* creation. The host segment percent-encodes a port (`localhost:8080` becomes
|
|
289
289
|
* `localhost%3A8080`), matching the library's `toDidDomainComponent`. The
|
|
290
290
|
* collection defaults to the account log's `id` collection; a companion
|
|
291
|
-
* generation's log passes its own `gen-`
|
|
291
|
+
* generation's log passes its own `gen-` generation id.
|
|
292
292
|
*
|
|
293
293
|
* @param options {object}
|
|
294
294
|
* @param options.wasServerUrl {string}
|