@interop/wallet-core 0.107.1 → 0.108.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 +21 -19
- package/dist/clientAnnex/establish.d.ts +6 -5
- package/dist/clientAnnex/establish.d.ts.map +1 -1
- package/dist/clientAnnex/establish.js +9 -8
- package/dist/clientAnnex/establish.js.map +1 -1
- package/dist/clientAnnex/forget.d.ts +5 -5
- package/dist/clientAnnex/forget.d.ts.map +1 -1
- package/dist/clientAnnex/forget.js +1 -1
- package/dist/clientAnnex/forget.js.map +1 -1
- package/dist/clientAnnex/forgetLast.d.ts +8 -8
- package/dist/clientAnnex/forgetLast.d.ts.map +1 -1
- package/dist/clientAnnex/forgetLast.js +2 -2
- package/dist/clientAnnex/forgetLast.js.map +1 -1
- package/dist/clientAnnex/gc.d.ts.map +1 -1
- package/dist/clientAnnex/gc.js +4 -1
- package/dist/clientAnnex/gc.js.map +1 -1
- package/dist/clientAnnex/heal.d.ts +16 -14
- package/dist/clientAnnex/heal.d.ts.map +1 -1
- package/dist/clientAnnex/heal.js +9 -9
- package/dist/clientAnnex/heal.js.map +1 -1
- package/dist/clientAnnex/ladderAnchored.d.ts +35 -27
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/ladderAnchored.js +26 -37
- package/dist/clientAnnex/ladderAnchored.js.map +1 -1
- package/dist/clientAnnex/log.d.ts +31 -31
- package/dist/clientAnnex/log.d.ts.map +1 -1
- package/dist/clientAnnex/log.js +28 -28
- package/dist/clientAnnex/log.js.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +4 -3
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.js +1 -1
- package/dist/clientAnnex/selfEnroll.d.ts +3 -3
- package/dist/clientAnnex/selfEnroll.d.ts.map +1 -1
- package/dist/clientAnnex/selfEnroll.js +1 -1
- package/dist/clients/revocation.d.ts +2 -2
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js.map +1 -1
- package/dist/connections/entry.d.ts +100 -9
- package/dist/connections/entry.d.ts.map +1 -1
- package/dist/connections/entry.js +104 -12
- package/dist/connections/entry.js.map +1 -1
- package/dist/connections/grants.d.ts.map +1 -1
- package/dist/connections/grants.js +3 -5
- package/dist/connections/grants.js.map +1 -1
- package/dist/connections/index.d.ts +9 -5
- package/dist/connections/index.d.ts.map +1 -1
- package/dist/connections/index.js +7 -4
- package/dist/connections/index.js.map +1 -1
- package/dist/connections/replicas.d.ts +227 -0
- package/dist/connections/replicas.d.ts.map +1 -0
- package/dist/connections/replicas.js +539 -0
- package/dist/connections/replicas.js.map +1 -0
- package/dist/connections/upsert.d.ts +75 -1
- package/dist/connections/upsert.d.ts.map +1 -1
- package/dist/connections/upsert.js +62 -34
- package/dist/connections/upsert.js.map +1 -1
- package/dist/recovery/continuation.d.ts +3 -9
- package/dist/recovery/continuation.d.ts.map +1 -1
- package/dist/recovery/continuation.js +1 -3
- package/dist/recovery/continuation.js.map +1 -1
- package/dist/recovery/index.d.ts +2 -1
- package/dist/recovery/index.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.d.ts +21 -15
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -1
- package/dist/recovery/recoveryWebvh.js +12 -7
- package/dist/recovery/recoveryWebvh.js.map +1 -1
- package/dist/testing/accountBuilder.d.ts.map +1 -1
- package/dist/testing/accountBuilder.js +1 -3
- package/dist/testing/accountBuilder.js.map +1 -1
- package/dist/unlock/index.d.ts +2 -1
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/retire.d.ts +7 -5
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js +5 -4
- package/dist/unlock/retire.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +24 -15
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +32 -19
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/webvh/accountEntry.d.ts +39 -50
- package/dist/webvh/accountEntry.d.ts.map +1 -1
- package/dist/webvh/accountEntry.js +133 -55
- package/dist/webvh/accountEntry.js.map +1 -1
- package/dist/webvh/delegatedLogStore.d.ts +4 -11
- package/dist/webvh/delegatedLogStore.d.ts.map +1 -1
- package/dist/webvh/delegatedLogStore.js +1 -1
- package/dist/webvh/delegatedLogStore.js.map +1 -1
- package/dist/webvh/didWebProjection.d.ts +30 -49
- package/dist/webvh/didWebProjection.d.ts.map +1 -1
- package/dist/webvh/didWebProjection.js +9 -56
- package/dist/webvh/didWebProjection.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +13 -8
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +11 -7
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/enrollClient.d.ts +5 -3
- package/dist/webvh/enrollClient.d.ts.map +1 -1
- package/dist/webvh/enrollClient.js +12 -10
- package/dist/webvh/enrollClient.js.map +1 -1
- package/dist/webvh/index.d.ts +1 -1
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +10 -4
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +22 -22
- package/dist/webvh/revokeClient.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The upsert helpers a replica registration and its maintenance write a
|
|
6
|
+
* `replica-server` entry through: `recordReplicas` (the registration's entry
|
|
7
|
+
* write, before anything touches the replica server), `recordReplicaGrant`
|
|
8
|
+
* (a pull grant, with a first registration's pending id in the same write),
|
|
9
|
+
* `settleReplicaRegistration` (the landed id), `setReplicaMarker` and
|
|
10
|
+
* `clearReplicaMarker` over `stoppedAt`, `restartedAt`, and `lostAt`, and
|
|
11
|
+
* `removeReplica`.
|
|
12
|
+
*
|
|
13
|
+
* Each runs `writeConnection` (`upsert.ts`), the one bounded compare-and-swap
|
|
14
|
+
* loop at the party's resource id, and refuses an entry of another kind with
|
|
15
|
+
* `ConnectionKindMismatchError` before writing. Each changes only the
|
|
16
|
+
* members it owns, so every other member, on the entry or on an item, is
|
|
17
|
+
* written back verbatim. Every `fromSpace` is stored and matched in its
|
|
18
|
+
* URL-normalized form (`spaceContainerUrl`). The members and their rules are
|
|
19
|
+
* decision 0031's.
|
|
20
|
+
*/
|
|
21
|
+
import { normalizeDisplayName } from '../labelText.js';
|
|
22
|
+
import { REPLICA_SERVER_KIND, isConnectionFreshId, newConnectionEntry, spaceContainerUrl } from './entry.js';
|
|
23
|
+
import { isTargetInSpace, normalizedActions } from './grants.js';
|
|
24
|
+
import { assertKind, checkedDelegatedZcap, renewedGrantRecord, writePartyConnection } from './upsert.js';
|
|
25
|
+
/**
|
|
26
|
+
* The intent markers a replica item carries.
|
|
27
|
+
*/
|
|
28
|
+
export const REPLICA_MARKERS = ['stoppedAt', 'restartedAt', 'lostAt'];
|
|
29
|
+
/**
|
|
30
|
+
* The named source Spaces of a marker write, normalized, or `undefined`
|
|
31
|
+
* when none are named (every item). Refuses an empty list with a
|
|
32
|
+
* `TypeError`, since a write naming no item would mark nothing while its
|
|
33
|
+
* side effects (the re-start's decline clearing) still ran.
|
|
34
|
+
*
|
|
35
|
+
* @param fromSpaces {Iterable<string> | undefined}
|
|
36
|
+
* @returns {Set<string> | undefined}
|
|
37
|
+
*/
|
|
38
|
+
function namedSourceSpaces(fromSpaces) {
|
|
39
|
+
if (fromSpaces === undefined) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const named = new Set([...fromSpaces].map(spaceContainerUrl));
|
|
43
|
+
if (named.size === 0) {
|
|
44
|
+
throw new TypeError('A marker write names at least one source Space, or omits the list ' +
|
|
45
|
+
'to name every item.');
|
|
46
|
+
}
|
|
47
|
+
return named;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Refuses a value that is not a fresh id (32 bytes, base64url with no
|
|
51
|
+
* padding) with a `TypeError`.
|
|
52
|
+
*
|
|
53
|
+
* @param options {object}
|
|
54
|
+
* @param options.value {string}
|
|
55
|
+
* @param options.what {string} the id's name, for the message
|
|
56
|
+
*/
|
|
57
|
+
function assertFreshId({ value, what }) {
|
|
58
|
+
if (!isConnectionFreshId(value)) {
|
|
59
|
+
throw new TypeError(`A ${what} is 32 random bytes as base64url with no padding; got ` +
|
|
60
|
+
`"${value}".`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The index of the item whose `fromSpace` is `fromSpace`, or a thrown
|
|
65
|
+
* `Error` when the entry lists none.
|
|
66
|
+
*
|
|
67
|
+
* @param options {object}
|
|
68
|
+
* @param options.entry {ConnectionEntry}
|
|
69
|
+
* @param options.fromSpace {string}
|
|
70
|
+
* @returns {number}
|
|
71
|
+
*/
|
|
72
|
+
function replicaIndex({ entry, fromSpace }) {
|
|
73
|
+
const index = entry.replicas.findIndex(item => item.fromSpace === fromSpace);
|
|
74
|
+
if (index === -1) {
|
|
75
|
+
throw new Error(`The connections entry lists no replica of the Space "${fromSpace}".`);
|
|
76
|
+
}
|
|
77
|
+
return index;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The stored `replicas` list with the item at `index` replaced.
|
|
81
|
+
*
|
|
82
|
+
* @param options {object}
|
|
83
|
+
* @param options.entry {ConnectionEntry}
|
|
84
|
+
* @param options.index {number}
|
|
85
|
+
* @param options.item {ConnectionReplica}
|
|
86
|
+
* @returns {ConnectionReplica[]}
|
|
87
|
+
*/
|
|
88
|
+
function withReplica({ entry, index, item }) {
|
|
89
|
+
return entry.replicas.map((held, heldIndex) => heldIndex === index ? item : held);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The registration ceremony's entry write, before anything touches the
|
|
93
|
+
* replica server: creates the `replica-server` entry, or merges into it.
|
|
94
|
+
* `url` is set, `name` when it passes the display-name rule, and `lastSeen`
|
|
95
|
+
* moves to `now`. Each item of `replicas` is added by its `fromSpace` (stored
|
|
96
|
+
* URL-normalized) with its freshly minted replica Space id; an item already
|
|
97
|
+
* listed for that source Space is left as stored, so a re-run adopts the ids
|
|
98
|
+
* an earlier run persisted. An item already listed that carries `lostAt` is
|
|
99
|
+
* refused with an `Error`: its replica Space is gone, so adopting its id
|
|
100
|
+
* would register under a lost Space while the item kept reading as lost.
|
|
101
|
+
* Delete removes the item (`removeReplica`) before the Space is registered
|
|
102
|
+
* again. `retired` and `declined` are cleared, since the user's registration
|
|
103
|
+
* is a fresh consent toward the server. `firstSeen` is set only on create,
|
|
104
|
+
* and `label` is never touched.
|
|
105
|
+
*
|
|
106
|
+
* A `seed` and its `seedTag` (both or neither) are written when the entry
|
|
107
|
+
* carries no seed, and left as stored when it carries the same one. An entry
|
|
108
|
+
* carrying a different seed is refused with an `Error`, since the seed is
|
|
109
|
+
* written once and a retired entry keeps it.
|
|
110
|
+
*
|
|
111
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
112
|
+
* and a `fromSpace` that is not a container URL, a `spaceId` that is not a
|
|
113
|
+
* fresh id, two items naming one source Space, or a `seed` without its tag
|
|
114
|
+
* (or the reverse) with a `TypeError`, before anything is written. The tag
|
|
115
|
+
* is not verified here; the caller minted both under the directory's key.
|
|
116
|
+
*
|
|
117
|
+
* @param options {object}
|
|
118
|
+
* @param options.store {ConnectionsStore}
|
|
119
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
120
|
+
* @param options.did {string} the replica server's `serverDid`
|
|
121
|
+
* @param options.url {string} the replica server's base URL
|
|
122
|
+
* @param options.replicas {Array<object>} `{ fromSpace, spaceId }` per
|
|
123
|
+
* replica Space to record
|
|
124
|
+
* @param [options.name] {string} the replica server's host name
|
|
125
|
+
* @param [options.seed] {string} the bootstrap seed, base64url with no
|
|
126
|
+
* padding
|
|
127
|
+
* @param [options.seedTag] {string} the seed's tag (`connectionSeedTag`)
|
|
128
|
+
* @param [options.now] {Date}
|
|
129
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
130
|
+
*/
|
|
131
|
+
export async function recordReplicas({ store, hmacKey, did, url, replicas, name, seed, seedTag, now = new Date() }) {
|
|
132
|
+
if ((seed === undefined) !== (seedTag === undefined)) {
|
|
133
|
+
throw new TypeError('A connection seed is written with its tag, or not.');
|
|
134
|
+
}
|
|
135
|
+
const incoming = [];
|
|
136
|
+
for (const { fromSpace: value, spaceId } of replicas) {
|
|
137
|
+
const fromSpace = spaceContainerUrl(value);
|
|
138
|
+
assertFreshId({ value: spaceId, what: 'replica Space id' });
|
|
139
|
+
if (incoming.some(item => item.fromSpace === fromSpace)) {
|
|
140
|
+
throw new TypeError(`A replica-server entry lists one replica per source Space; ` +
|
|
141
|
+
`"${fromSpace}" is named twice.`);
|
|
142
|
+
}
|
|
143
|
+
incoming.push({ fromSpace, spaceId });
|
|
144
|
+
}
|
|
145
|
+
const named = new Set(incoming.map(item => item.fromSpace));
|
|
146
|
+
const stamp = now.toISOString();
|
|
147
|
+
const normalizedName = name === undefined ? undefined : normalizeDisplayName({ value: name });
|
|
148
|
+
const declared = {
|
|
149
|
+
...(normalizedName !== undefined && { name: normalizedName }),
|
|
150
|
+
url
|
|
151
|
+
};
|
|
152
|
+
return writePartyConnection({
|
|
153
|
+
store,
|
|
154
|
+
hmacKey,
|
|
155
|
+
did,
|
|
156
|
+
change(current) {
|
|
157
|
+
if (current === undefined) {
|
|
158
|
+
return {
|
|
159
|
+
body: {
|
|
160
|
+
...newConnectionEntry({ kind: REPLICA_SERVER_KIND, did, now }),
|
|
161
|
+
...declared,
|
|
162
|
+
...(seed !== undefined && { seed, seedTag }),
|
|
163
|
+
replicas: incoming
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const { entry } = current;
|
|
168
|
+
assertKind({ entry, kind: REPLICA_SERVER_KIND });
|
|
169
|
+
if (seed !== undefined &&
|
|
170
|
+
entry.seed !== undefined &&
|
|
171
|
+
entry.seed !== seed) {
|
|
172
|
+
throw new Error('The connections entry already carries a different pairwise seed; ' +
|
|
173
|
+
'a seed is written once.');
|
|
174
|
+
}
|
|
175
|
+
const held = new Set(entry.replicas.map(item => item.fromSpace));
|
|
176
|
+
const lost = entry.replicas.find(item => item.lostAt !== undefined && named.has(item.fromSpace));
|
|
177
|
+
if (lost !== undefined) {
|
|
178
|
+
throw new Error(`The replica of "${lost.fromSpace}" is marked lost; it is removed ` +
|
|
179
|
+
'before the Space is registered again.');
|
|
180
|
+
}
|
|
181
|
+
const body = {
|
|
182
|
+
...current.body,
|
|
183
|
+
...declared,
|
|
184
|
+
lastSeen: stamp,
|
|
185
|
+
...(seed !== undefined &&
|
|
186
|
+
entry.seed === undefined && { seed, seedTag }),
|
|
187
|
+
replicas: [
|
|
188
|
+
...entry.replicas,
|
|
189
|
+
...incoming.filter(item => !held.has(item.fromSpace))
|
|
190
|
+
]
|
|
191
|
+
};
|
|
192
|
+
delete body.retired;
|
|
193
|
+
delete body.declined;
|
|
194
|
+
return { body };
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Records one pull grant on the entry, and with it a first registration's
|
|
200
|
+
* pending id, in one write. The grant is appended as a `'grant'` record
|
|
201
|
+
* stamped `grantedAt: now`; one already recorded by its capability id is
|
|
202
|
+
* left as stored. With `pendingRegistrationId`, the item for `fromSpace`
|
|
203
|
+
* gains it, unless its first registration already landed (`registrationId`
|
|
204
|
+
* present) or it is pending under another id, each refused with an `Error`:
|
|
205
|
+
* the pending id is recorded before its POST, so a second id would orphan a
|
|
206
|
+
* registration that may have landed under the first.
|
|
207
|
+
*
|
|
208
|
+
* With `renews`, the id of the recorded grant the capability renews, the
|
|
209
|
+
* record is a renewal under `renewedGrantRecord`, the rule
|
|
210
|
+
* `recordRenewedGrants` applies: it keeps the source's `grantKind` and
|
|
211
|
+
* `grantedAt` and carries `renewedAt: now`, the source stays as stored, and
|
|
212
|
+
* the capability must share the source's scope (controller, invocation
|
|
213
|
+
* target, allowed actions) and expire strictly later. A source no longer on
|
|
214
|
+
* the entry, no longer the latest record of its scope, or a capability not
|
|
215
|
+
* expiring strictly later, is refused with an `Error`. The login pass records a renewal this
|
|
216
|
+
* way, with no pending id; the two together are refused with a `TypeError`.
|
|
217
|
+
*
|
|
218
|
+
* This write touches neither `declined` nor `retired`: the pass records a
|
|
219
|
+
* renewal through it, and a declined entry must stay declined until the
|
|
220
|
+
* owner's re-start (`setReplicaMarker` with `restartedAt`) clears it.
|
|
221
|
+
*
|
|
222
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
223
|
+
* a retired entry with an `Error`, and a capability not delegated to the
|
|
224
|
+
* server's DID or not targeting `fromSpace` (`checkedDelegatedZcap`), one
|
|
225
|
+
* allowing any action but `GET` (a pull grant reads and nothing else), or a
|
|
226
|
+
* `pendingRegistrationId` that is not a fresh id, with a `TypeError`. An entry listing no item for
|
|
227
|
+
* `fromSpace` is refused with an `Error`. An absent entry writes nothing.
|
|
228
|
+
*
|
|
229
|
+
* @param options {object}
|
|
230
|
+
* @param options.store {ConnectionsStore}
|
|
231
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
232
|
+
* @param options.did {string} the replica server's `serverDid`, the
|
|
233
|
+
* grant's controller
|
|
234
|
+
* @param options.fromSpace {string} the source Space the grant reads from
|
|
235
|
+
* @param options.zcap {object} the pull capability
|
|
236
|
+
* @param [options.pendingRegistrationId] {string} a first registration's
|
|
237
|
+
* id, recorded before its POST
|
|
238
|
+
* @param [options.renews] {string} the capability id of the recorded grant
|
|
239
|
+
* this one renews
|
|
240
|
+
* @param [options.now] {Date}
|
|
241
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
242
|
+
*/
|
|
243
|
+
export async function recordReplicaGrant({ store, hmacKey, did, fromSpace: spaceValue, zcap: zcapValue, pendingRegistrationId, renews, now = new Date() }) {
|
|
244
|
+
const fromSpace = spaceContainerUrl(spaceValue);
|
|
245
|
+
if (pendingRegistrationId !== undefined && renews !== undefined) {
|
|
246
|
+
throw new TypeError('A first registration has no recorded grant to renew; pass a pending ' +
|
|
247
|
+
'registration id or a renewed grant, not both.');
|
|
248
|
+
}
|
|
249
|
+
const zcap = checkedDelegatedZcap({
|
|
250
|
+
did,
|
|
251
|
+
spaceUrl: fromSpace,
|
|
252
|
+
zcap: zcapValue
|
|
253
|
+
});
|
|
254
|
+
const actions = normalizedActions({ allowedAction: zcap.allowedAction });
|
|
255
|
+
if (actions.length !== 1 || actions[0] !== 'GET') {
|
|
256
|
+
throw new TypeError(`A pull grant allows GET and nothing else; its allowed actions are ` +
|
|
257
|
+
`${JSON.stringify(actions)}.`);
|
|
258
|
+
}
|
|
259
|
+
if (pendingRegistrationId !== undefined) {
|
|
260
|
+
assertFreshId({ value: pendingRegistrationId, what: 'registration id' });
|
|
261
|
+
}
|
|
262
|
+
const stamp = now.toISOString();
|
|
263
|
+
return writePartyConnection({
|
|
264
|
+
store,
|
|
265
|
+
hmacKey,
|
|
266
|
+
did,
|
|
267
|
+
change(current) {
|
|
268
|
+
if (current === undefined) {
|
|
269
|
+
return { stop: 'absent' };
|
|
270
|
+
}
|
|
271
|
+
const { entry } = current;
|
|
272
|
+
assertKind({ entry, kind: REPLICA_SERVER_KIND });
|
|
273
|
+
if (entry.retired !== undefined) {
|
|
274
|
+
throw new Error('The connections entry is retired; it records no pull grants.');
|
|
275
|
+
}
|
|
276
|
+
const index = replicaIndex({ entry, fromSpace });
|
|
277
|
+
const item = entry.replicas[index];
|
|
278
|
+
const grantHeld = entry.grants.some(grant => grant.zcap.id === zcap.id);
|
|
279
|
+
const record = renews === undefined
|
|
280
|
+
? { zcap, grantKind: 'grant', grantedAt: stamp }
|
|
281
|
+
: renewedGrantRecord({ entry, zcap, sourceZcapId: renews, stamp });
|
|
282
|
+
let replicas = entry.replicas;
|
|
283
|
+
if (pendingRegistrationId !== undefined) {
|
|
284
|
+
if (item.registrationId !== undefined) {
|
|
285
|
+
throw new Error(`The replica of "${fromSpace}" is registered already; a ` +
|
|
286
|
+
'replacement mints no new registration id.');
|
|
287
|
+
}
|
|
288
|
+
if (item.pendingRegistrationId !== undefined &&
|
|
289
|
+
item.pendingRegistrationId !== pendingRegistrationId) {
|
|
290
|
+
throw new Error(`The replica of "${fromSpace}" has a registration pending under ` +
|
|
291
|
+
`"${item.pendingRegistrationId}"; it settles or is removed ` +
|
|
292
|
+
'before another id is recorded.');
|
|
293
|
+
}
|
|
294
|
+
if (item.pendingRegistrationId !== pendingRegistrationId) {
|
|
295
|
+
replicas = withReplica({
|
|
296
|
+
entry,
|
|
297
|
+
index,
|
|
298
|
+
item: { ...item, pendingRegistrationId }
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (grantHeld && replicas === entry.replicas) {
|
|
303
|
+
return { stop: 'unchanged' };
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
body: {
|
|
307
|
+
...current.body,
|
|
308
|
+
...(!grantHeld && { grants: [...entry.grants, record] }),
|
|
309
|
+
replicas
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Moves a landed first registration's id from `pendingRegistrationId` to
|
|
317
|
+
* `registrationId` on the item for `fromSpace`. An item already settled on
|
|
318
|
+
* `registrationId` with no pending id writes nothing. An item whose pending
|
|
319
|
+
* id is another, or that carries neither, is refused with an `Error`.
|
|
320
|
+
*
|
|
321
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
322
|
+
* and an entry listing no item for `fromSpace` with an `Error`. An absent
|
|
323
|
+
* entry writes nothing.
|
|
324
|
+
*
|
|
325
|
+
* @param options {object}
|
|
326
|
+
* @param options.store {ConnectionsStore}
|
|
327
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
328
|
+
* @param options.did {string} the replica server's `serverDid`
|
|
329
|
+
* @param options.fromSpace {string} the item's source Space
|
|
330
|
+
* @param options.registrationId {string} the id that landed
|
|
331
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
332
|
+
*/
|
|
333
|
+
export async function settleReplicaRegistration({ store, hmacKey, did, fromSpace: value, registrationId }) {
|
|
334
|
+
const fromSpace = spaceContainerUrl(value);
|
|
335
|
+
assertFreshId({ value: registrationId, what: 'registration id' });
|
|
336
|
+
return writePartyConnection({
|
|
337
|
+
store,
|
|
338
|
+
hmacKey,
|
|
339
|
+
did,
|
|
340
|
+
change(current) {
|
|
341
|
+
if (current === undefined) {
|
|
342
|
+
return { stop: 'absent' };
|
|
343
|
+
}
|
|
344
|
+
const { entry } = current;
|
|
345
|
+
assertKind({ entry, kind: REPLICA_SERVER_KIND });
|
|
346
|
+
const index = replicaIndex({ entry, fromSpace });
|
|
347
|
+
const item = entry.replicas[index];
|
|
348
|
+
if (item.registrationId === registrationId &&
|
|
349
|
+
item.pendingRegistrationId === undefined) {
|
|
350
|
+
return { stop: 'unchanged' };
|
|
351
|
+
}
|
|
352
|
+
if (item.pendingRegistrationId !== registrationId) {
|
|
353
|
+
throw new Error(`The replica of "${fromSpace}" has no pending registration ` +
|
|
354
|
+
`"${registrationId}" to settle.`);
|
|
355
|
+
}
|
|
356
|
+
const settled = { ...item, registrationId };
|
|
357
|
+
delete settled.pendingRegistrationId;
|
|
358
|
+
return {
|
|
359
|
+
body: {
|
|
360
|
+
...current.body,
|
|
361
|
+
replicas: withReplica({ entry, index, item: settled })
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* One marker write over the named items, or every item when `fromSpaces` is
|
|
369
|
+
* omitted: `apply` returns the item's replacement, or `undefined` to leave it
|
|
370
|
+
* as stored. `finish` edits the body beside `replicas` and says whether it
|
|
371
|
+
* changed anything, so a write that touches no item may still land. Nothing
|
|
372
|
+
* changed writes nothing.
|
|
373
|
+
*
|
|
374
|
+
* @param options {object}
|
|
375
|
+
* @param options.store {ConnectionsStore}
|
|
376
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
377
|
+
* @param options.did {string}
|
|
378
|
+
* @param [options.fromSpaces] {Iterable<string>}
|
|
379
|
+
* @param options.apply {Function}
|
|
380
|
+
* @param [options.finish] {Function}
|
|
381
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
382
|
+
*/
|
|
383
|
+
async function writeReplicaMarkers({ store, hmacKey, did, fromSpaces, apply, finish = () => false }) {
|
|
384
|
+
const named = namedSourceSpaces(fromSpaces);
|
|
385
|
+
return writePartyConnection({
|
|
386
|
+
store,
|
|
387
|
+
hmacKey,
|
|
388
|
+
did,
|
|
389
|
+
change(current) {
|
|
390
|
+
if (current === undefined) {
|
|
391
|
+
return { stop: 'absent' };
|
|
392
|
+
}
|
|
393
|
+
const { entry } = current;
|
|
394
|
+
assertKind({ entry, kind: REPLICA_SERVER_KIND });
|
|
395
|
+
for (const fromSpace of named ?? []) {
|
|
396
|
+
replicaIndex({ entry, fromSpace });
|
|
397
|
+
}
|
|
398
|
+
let changed = false;
|
|
399
|
+
const replicas = entry.replicas.map(item => {
|
|
400
|
+
const applied = named !== undefined && !named.has(item.fromSpace)
|
|
401
|
+
? undefined
|
|
402
|
+
: apply(item);
|
|
403
|
+
if (applied === undefined) {
|
|
404
|
+
return item;
|
|
405
|
+
}
|
|
406
|
+
changed = true;
|
|
407
|
+
return applied;
|
|
408
|
+
});
|
|
409
|
+
const body = { ...current.body, replicas };
|
|
410
|
+
if (!finish({ entry, body }) && !changed) {
|
|
411
|
+
return { stop: 'unchanged' };
|
|
412
|
+
}
|
|
413
|
+
return { body };
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Sets one intent marker to `now` on each named item, or on every item when
|
|
419
|
+
* `fromSpaces` is omitted: `stoppedAt` is the user's Stop, `restartedAt` the
|
|
420
|
+
* re-start, and `lostAt` the replica Space reading absent under the account's
|
|
421
|
+
* own authority. An item already carrying the marker keeps its time. Setting
|
|
422
|
+
* `restartedAt` also clears the entry's `declined`, in the same write, since
|
|
423
|
+
* the re-start is the owner's consent. Nothing to set writes nothing.
|
|
424
|
+
*
|
|
425
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
426
|
+
* a named source Space the entry lists no item for with an `Error`, and an
|
|
427
|
+
* empty `fromSpaces` with a `TypeError`, since it would mark nothing while
|
|
428
|
+
* the re-start's decline clearing still ran. An absent entry writes nothing.
|
|
429
|
+
*
|
|
430
|
+
* @param options {object}
|
|
431
|
+
* @param options.store {ConnectionsStore}
|
|
432
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
433
|
+
* @param options.did {string} the replica server's `serverDid`
|
|
434
|
+
* @param options.marker {ReplicaMarker}
|
|
435
|
+
* @param [options.fromSpaces] {Iterable<string>} the items to mark, by
|
|
436
|
+
* source Space; omitted, every item
|
|
437
|
+
* @param [options.now] {Date}
|
|
438
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
439
|
+
*/
|
|
440
|
+
export async function setReplicaMarker({ store, hmacKey, did, marker, fromSpaces, now = new Date() }) {
|
|
441
|
+
const stamp = now.toISOString();
|
|
442
|
+
return writeReplicaMarkers({
|
|
443
|
+
store,
|
|
444
|
+
hmacKey,
|
|
445
|
+
did,
|
|
446
|
+
fromSpaces,
|
|
447
|
+
apply: item => item[marker] === undefined ? { ...item, [marker]: stamp } : undefined,
|
|
448
|
+
finish({ entry, body }) {
|
|
449
|
+
if (marker !== 'restartedAt') {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
delete body.declined;
|
|
453
|
+
return entry.declined !== undefined;
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Clears one intent marker on each named item, or on every item when
|
|
459
|
+
* `fromSpaces` is omitted: a completed re-start clears `stoppedAt` and then
|
|
460
|
+
* `restartedAt`. An item without the marker is left as stored, and nothing
|
|
461
|
+
* to clear writes nothing.
|
|
462
|
+
*
|
|
463
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
464
|
+
* a named source Space the entry lists no item for with an `Error`, and an
|
|
465
|
+
* empty `fromSpaces` with a `TypeError`. An absent entry writes nothing.
|
|
466
|
+
*
|
|
467
|
+
* @param options {object}
|
|
468
|
+
* @param options.store {ConnectionsStore}
|
|
469
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
470
|
+
* @param options.did {string} the replica server's `serverDid`
|
|
471
|
+
* @param options.marker {ReplicaMarker}
|
|
472
|
+
* @param [options.fromSpaces] {Iterable<string>} the items to clear, by
|
|
473
|
+
* source Space; omitted, every item
|
|
474
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
475
|
+
*/
|
|
476
|
+
export async function clearReplicaMarker({ store, hmacKey, did, marker, fromSpaces }) {
|
|
477
|
+
return writeReplicaMarkers({
|
|
478
|
+
store,
|
|
479
|
+
hmacKey,
|
|
480
|
+
did,
|
|
481
|
+
fromSpaces,
|
|
482
|
+
apply(item) {
|
|
483
|
+
if (item[marker] === undefined) {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
const cleared = { ...item };
|
|
487
|
+
delete cleared[marker];
|
|
488
|
+
return cleared;
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Removes the item for `fromSpace`, once its replica Space is gone. An
|
|
494
|
+
* entry listing no such item writes nothing. The entry is not retired here:
|
|
495
|
+
* `retireConnection` runs once the list is empty.
|
|
496
|
+
*
|
|
497
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
498
|
+
* and an item whose source Space a recorded grant still targets with an
|
|
499
|
+
* `Error`: Stop revokes and removes the pull grants first, so a grant left
|
|
500
|
+
* recorded means a Stop torn before its last step, and the removal would
|
|
501
|
+
* hide it from the readers that finish it. An absent entry writes nothing.
|
|
502
|
+
*
|
|
503
|
+
* @param options {object}
|
|
504
|
+
* @param options.store {ConnectionsStore}
|
|
505
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
506
|
+
* @param options.did {string} the replica server's `serverDid`
|
|
507
|
+
* @param options.fromSpace {string} the item's source Space
|
|
508
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
509
|
+
*/
|
|
510
|
+
export async function removeReplica({ store, hmacKey, did, fromSpace: value }) {
|
|
511
|
+
const fromSpace = spaceContainerUrl(value);
|
|
512
|
+
return writePartyConnection({
|
|
513
|
+
store,
|
|
514
|
+
hmacKey,
|
|
515
|
+
did,
|
|
516
|
+
change(current) {
|
|
517
|
+
if (current === undefined) {
|
|
518
|
+
return { stop: 'absent' };
|
|
519
|
+
}
|
|
520
|
+
const { entry } = current;
|
|
521
|
+
assertKind({ entry, kind: REPLICA_SERVER_KIND });
|
|
522
|
+
const kept = entry.replicas.filter(item => item.fromSpace !== fromSpace);
|
|
523
|
+
if (kept.length === entry.replicas.length) {
|
|
524
|
+
return { stop: 'unchanged' };
|
|
525
|
+
}
|
|
526
|
+
const standing = entry.grants.filter(grant => isTargetInSpace({
|
|
527
|
+
target: grant.zcap.invocationTarget,
|
|
528
|
+
spaceUrl: fromSpace
|
|
529
|
+
}));
|
|
530
|
+
if (standing.length > 0) {
|
|
531
|
+
throw new Error(`The connections entry still records ${standing.length} pull ` +
|
|
532
|
+
`grant(s) on "${fromSpace}"; Stop removes them before the ` +
|
|
533
|
+
'replica is removed.');
|
|
534
|
+
}
|
|
535
|
+
return { body: { ...current.body, replicas: kept } };
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
//# sourceMappingURL=replicas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replicas.js","sourceRoot":"","sources":["../../src/connections/replicas.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
3
|
*/
|
|
4
|
-
import type { ConnectionEntry, ConnectionKind, GrantKind, ReceivedGrantKind } from './entry.js';
|
|
4
|
+
import type { ConnectionEntry, ConnectionGrantRecord, ConnectionKind, ConnectionZcap, GrantKind, ReceivedGrantKind } from './entry.js';
|
|
5
5
|
import type { ConnectionIdKey } from './resourceId.js';
|
|
6
6
|
import type { ConnectionsStore } from './store.js';
|
|
7
7
|
/**
|
|
@@ -81,6 +81,75 @@ export declare function writeConnection<Stop>({ store, hmacKey, resourceId, chan
|
|
|
81
81
|
resourceId: string;
|
|
82
82
|
outcome: 'created' | 'updated' | Stop;
|
|
83
83
|
}>;
|
|
84
|
+
/**
|
|
85
|
+
* {@link writeConnection} for the helpers here, keyed by the party's DID. A
|
|
86
|
+
* helper with nothing to write stops with `absent` (no entry at the id) or
|
|
87
|
+
* `unchanged`.
|
|
88
|
+
*
|
|
89
|
+
* @param options {object}
|
|
90
|
+
* @param options.store {ConnectionsStore}
|
|
91
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
92
|
+
* @param options.did {string} the party's DID
|
|
93
|
+
* @param options.change {Function}
|
|
94
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
95
|
+
*/
|
|
96
|
+
export declare function writePartyConnection({ store, hmacKey, did, change }: {
|
|
97
|
+
store: ConnectionsStore;
|
|
98
|
+
hmacKey: ConnectionIdKey;
|
|
99
|
+
did: string;
|
|
100
|
+
change: (current: WritableConnection | undefined) => ConnectionChange<'absent' | 'unchanged'>;
|
|
101
|
+
}): Promise<ConnectionWriteResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Refuses a stored entry of another kind than the writing flow's.
|
|
104
|
+
*
|
|
105
|
+
* @param options {object}
|
|
106
|
+
* @param options.entry {ConnectionEntry}
|
|
107
|
+
* @param options.kind {string}
|
|
108
|
+
*/
|
|
109
|
+
export declare function assertKind({ entry, kind }: {
|
|
110
|
+
entry: ConnectionEntry;
|
|
111
|
+
kind: string;
|
|
112
|
+
}): void;
|
|
113
|
+
/**
|
|
114
|
+
* A capability the wallet delegated, checked strictly: its known members
|
|
115
|
+
* well-formed, its `controller` the party's DID, its `invocationTarget`
|
|
116
|
+
* under this Space. The target check is the same one every reader applies,
|
|
117
|
+
* so a grant that is stored is a grant the revocation index will see.
|
|
118
|
+
*
|
|
119
|
+
* @param options {object}
|
|
120
|
+
* @param options.did {string}
|
|
121
|
+
* @param options.spaceUrl {string}
|
|
122
|
+
* @param options.zcap {object}
|
|
123
|
+
* @returns {ConnectionZcap}
|
|
124
|
+
*/
|
|
125
|
+
export declare function checkedDelegatedZcap({ did, spaceUrl, zcap: value }: {
|
|
126
|
+
did: string;
|
|
127
|
+
spaceUrl: string;
|
|
128
|
+
zcap: object;
|
|
129
|
+
}): ConnectionZcap;
|
|
130
|
+
/**
|
|
131
|
+
* The record a renewal appends: `zcap` renewing the recorded grant
|
|
132
|
+
* `sourceZcapId`, keeping the source's `grantKind` and `grantedAt` and
|
|
133
|
+
* carrying `renewedAt: stamp`. Refuses a source gone from the entry, or no
|
|
134
|
+
* longer the latest record of its scope (a concurrent renewal ran), or a
|
|
135
|
+
* capability not expiring strictly later than its source, with an `Error`,
|
|
136
|
+
* and a capability of another scope than its source with a `TypeError`. The
|
|
137
|
+
* one renewal rule, shared by `recordRenewedGrants` and the replica-server
|
|
138
|
+
* helpers.
|
|
139
|
+
*
|
|
140
|
+
* @param options {object}
|
|
141
|
+
* @param options.entry {ConnectionEntry}
|
|
142
|
+
* @param options.zcap {ConnectionZcap} the renewed capability
|
|
143
|
+
* @param options.sourceZcapId {string} the id of the record it renews
|
|
144
|
+
* @param options.stamp {string} `renewedAt`
|
|
145
|
+
* @returns {ConnectionGrantRecord}
|
|
146
|
+
*/
|
|
147
|
+
export declare function renewedGrantRecord({ entry, zcap, sourceZcapId, stamp }: {
|
|
148
|
+
entry: ConnectionEntry;
|
|
149
|
+
zcap: ConnectionZcap;
|
|
150
|
+
sourceZcapId: string;
|
|
151
|
+
stamp: string;
|
|
152
|
+
}): ConnectionGrantRecord;
|
|
84
153
|
/**
|
|
85
154
|
* Records a consent on the party's entry: creates the entry, or merges into
|
|
86
155
|
* it. Each new grant is added by its capability id (one already recorded is
|
|
@@ -198,6 +267,11 @@ export declare function removeGrants({ store, hmacKey, did, zcapIds }: {
|
|
|
198
267
|
* be the party's, so none counts as unhandled and the retirement empties
|
|
199
268
|
* them all.
|
|
200
269
|
*
|
|
270
|
+
* An entry whose `replicas` list is not empty is refused with an `Error`:
|
|
271
|
+
* each item is removed (`removeReplica`) once its replica Space is gone, and
|
|
272
|
+
* the entry retires only after the last one. The codec admits the list on a
|
|
273
|
+
* `replica-server` entry alone, so the guard needs no kind check.
|
|
274
|
+
*
|
|
201
275
|
* @param options {object}
|
|
202
276
|
* @param options.store {ConnectionsStore}
|
|
203
277
|
* @param options.hmacKey {ConnectionIdKey}
|