@interop/wallet-core 0.93.0 → 0.95.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 -20
- package/dist/clientAnnex/mend.js +4 -1
- package/dist/clientAnnex/mend.js.map +1 -1
- package/dist/clients/index.d.ts +3 -2
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +3 -2
- package/dist/clients/index.js.map +1 -1
- package/dist/clients/listing.d.ts +19 -12
- package/dist/clients/listing.d.ts.map +1 -1
- package/dist/clients/listing.js +69 -22
- package/dist/clients/listing.js.map +1 -1
- package/dist/connections/didKey.d.ts +25 -0
- package/dist/connections/didKey.d.ts.map +1 -0
- package/dist/connections/didKey.js +49 -0
- package/dist/connections/didKey.js.map +1 -0
- package/dist/connections/entry.d.ts +226 -0
- package/dist/connections/entry.d.ts.map +1 -0
- package/dist/connections/entry.js +287 -0
- package/dist/connections/entry.js.map +1 -0
- package/dist/connections/errors.d.ts +33 -0
- package/dist/connections/errors.d.ts.map +1 -0
- package/dist/connections/errors.js +36 -0
- package/dist/connections/errors.js.map +1 -0
- package/dist/connections/grants.d.ts +94 -0
- package/dist/connections/grants.d.ts.map +1 -0
- package/dist/connections/grants.js +120 -0
- package/dist/connections/grants.js.map +1 -0
- package/dist/connections/index.d.ts +47 -0
- package/dist/connections/index.d.ts.map +1 -0
- package/dist/connections/index.js +40 -0
- package/dist/connections/index.js.map +1 -0
- package/dist/connections/read.d.ts +82 -0
- package/dist/connections/read.d.ts.map +1 -0
- package/dist/connections/read.js +100 -0
- package/dist/connections/read.js.map +1 -0
- package/dist/connections/resourceId.d.ts +36 -0
- package/dist/connections/resourceId.d.ts.map +1 -0
- package/dist/connections/resourceId.js +49 -0
- package/dist/connections/resourceId.js.map +1 -0
- package/dist/connections/store.d.ts +103 -0
- package/dist/connections/store.d.ts.map +1 -0
- package/dist/connections/store.js +67 -0
- package/dist/connections/store.js.map +1 -0
- package/dist/connections/upsert.d.ts +214 -0
- package/dist/connections/upsert.d.ts.map +1 -0
- package/dist/connections/upsert.js +468 -0
- package/dist/connections/upsert.js.map +1 -0
- package/dist/connections/writers.d.ts +217 -0
- package/dist/connections/writers.d.ts.map +1 -0
- package/dist/connections/writers.js +485 -0
- package/dist/connections/writers.js.map +1 -0
- package/dist/enrollment/onboardingResponse.d.ts +3 -3
- package/dist/enrollment/onboardingResponse.d.ts.map +1 -1
- package/dist/enrollment/onboardingResponse.js +17 -13
- package/dist/enrollment/onboardingResponse.js.map +1 -1
- package/dist/keys/index.d.ts +0 -7
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +0 -6
- package/dist/keys/index.js.map +1 -1
- package/dist/labelText.d.ts +30 -3
- package/dist/labelText.d.ts.map +1 -1
- package/dist/labelText.js +35 -3
- package/dist/labelText.js.map +1 -1
- package/dist/menders/ids.d.ts +1 -1
- package/dist/menders/ids.d.ts.map +1 -1
- package/dist/menders/ids.js +7 -2
- package/dist/menders/ids.js.map +1 -1
- package/dist/space/collections.d.ts +28 -25
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +46 -40
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +4 -3
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +4 -3
- package/dist/space/index.js.map +1 -1
- package/package.json +8 -8
- package/dist/keys/clientLabels.d.ts +0 -85
- package/dist/keys/clientLabels.d.ts.map +0 -1
- package/dist/keys/clientLabels.js +0 -96
- package/dist/keys/clientLabels.js.map +0 -1
- package/dist/keys/wasLabelsStore.d.ts +0 -33
- package/dist/keys/wasLabelsStore.d.ts.map +0 -1
- package/dist/keys/wasLabelsStore.js +0 -35
- package/dist/keys/wasLabelsStore.js.map +0 -1
- package/dist/writers/entry.d.ts +0 -95
- package/dist/writers/entry.d.ts.map +0 -1
- package/dist/writers/entry.js +0 -90
- package/dist/writers/entry.js.map +0 -1
- package/dist/writers/index.d.ts +0 -17
- package/dist/writers/index.d.ts.map +0 -1
- package/dist/writers/index.js +0 -14
- package/dist/writers/index.js.map +0 -1
- package/dist/writers/roster.d.ts +0 -152
- package/dist/writers/roster.d.ts.map +0 -1
- package/dist/writers/roster.js +0 -365
- package/dist/writers/roster.js.map +0 -1
- package/dist/writers/store.d.ts +0 -71
- package/dist/writers/store.d.ts.map +0 -1
- package/dist/writers/store.js +0 -55
- package/dist/writers/store.js.map +0 -1
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The upsert helpers every flow writes a party's entry through:
|
|
6
|
+
* `recordGrants` at consent, `removeGrants` at an unshare or a torn
|
|
7
|
+
* consent's rollback, `retireConnection` when a relationship ends, and
|
|
8
|
+
* `setConnectionLabel` for the user's rename and the enrollment-time name.
|
|
9
|
+
*
|
|
10
|
+
* Each runs `writeConnection`, the one bounded compare-and-swap loop at a
|
|
11
|
+
* party's resource id, which the writer arm (`writers.ts`) runs too. It reads
|
|
12
|
+
* the entry, applies its change to the stored body, and writes under
|
|
13
|
+
* `ifMatch` (or creates under `ifNoneMatch`). A lost race re-reads and
|
|
14
|
+
* re-applies, up to three attempts, after which the last
|
|
15
|
+
* `PreconditionFailedError` is thrown. A helper changes only the members it
|
|
16
|
+
* owns, so a member a newer build added, on the entry or on a grant wrapper,
|
|
17
|
+
* is written back verbatim. A helper that finds a body it cannot parse, one
|
|
18
|
+
* whose `version` is above this build's, or one that does not belong at the
|
|
19
|
+
* id refuses to write, rather than treating the body as absent: overwriting
|
|
20
|
+
* it would wipe a newer build's grants.
|
|
21
|
+
*/
|
|
22
|
+
import { NotSupportedError } from '@interop/was-client';
|
|
23
|
+
import { errorNameOf } from '../errorName.js';
|
|
24
|
+
import { normalizeDisplayName } from '../labelText.js';
|
|
25
|
+
import { signingKeyMultibaseOfDid } from './didKey.js';
|
|
26
|
+
import { CONNECTION_ENTRY_VERSION, GRANT_KINDS, isWritableConnectionEntry, newConnectionEntry, parseConnectionEntry, parseConnectionZcap } from './entry.js';
|
|
27
|
+
import { ConnectionKindMismatchError } from './errors.js';
|
|
28
|
+
import { connectionGrants, isTargetInSpace } from './grants.js';
|
|
29
|
+
import { claimedResourceId } from './read.js';
|
|
30
|
+
import { connectionResourceId } from './resourceId.js';
|
|
31
|
+
const PRECONDITION_FAILED_ERROR_NAME = 'PreconditionFailedError';
|
|
32
|
+
const WRITE_ATTEMPTS = 3;
|
|
33
|
+
/**
|
|
34
|
+
* Whether a store write lost a race. Matched by name, since the store is an
|
|
35
|
+
* injected seam that may raise from a second copy of was-client.
|
|
36
|
+
*
|
|
37
|
+
* @param err {unknown}
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
export function isLostConnectionRace(err) {
|
|
41
|
+
return errorNameOf(err) === PRECONDITION_FAILED_ERROR_NAME;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The ETag a write over an existing resource pins to. A read that carried
|
|
45
|
+
* none would send the write unconditionally, so it is refused instead.
|
|
46
|
+
*
|
|
47
|
+
* @param options {object}
|
|
48
|
+
* @param options.resourceId {string}
|
|
49
|
+
* @param [options.etag] {string}
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
function requireConnectionEtag({ resourceId, etag }) {
|
|
53
|
+
if (etag === undefined) {
|
|
54
|
+
throw new NotSupportedError(`Cannot update connections entry "${resourceId}": its read returned ` +
|
|
55
|
+
'no ETag, so the write would go out unconditionally. A browser ' +
|
|
56
|
+
"client needs `ETag` in the server's `Access-Control-Expose-Headers`.");
|
|
57
|
+
}
|
|
58
|
+
return etag;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reads a stored body as an entry this build may write over, or throws. The
|
|
62
|
+
* body must sit at the id its own members derive to, parse, and carry this
|
|
63
|
+
* build's `version`.
|
|
64
|
+
*
|
|
65
|
+
* @param options {object}
|
|
66
|
+
* @param options.resourceId {string}
|
|
67
|
+
* @param options.stored {object} the store's `get` result
|
|
68
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
69
|
+
* @returns {Promise<WritableConnection>}
|
|
70
|
+
*/
|
|
71
|
+
async function writableConnection({ resourceId, stored, hmacKey }) {
|
|
72
|
+
const claimed = await claimedResourceId({ body: stored.body, hmacKey });
|
|
73
|
+
const entry = parseConnectionEntry(stored.body);
|
|
74
|
+
if (claimed !== resourceId || entry === undefined) {
|
|
75
|
+
throw new Error(`The connections entry at "${resourceId}" cannot be parsed as the ` +
|
|
76
|
+
'entry for this id; this build refuses to write over it.');
|
|
77
|
+
}
|
|
78
|
+
if (!isWritableConnectionEntry(entry)) {
|
|
79
|
+
throw new Error(`The connections entry at "${resourceId}" carries version ` +
|
|
80
|
+
`${entry.version}, newer than this build's ` +
|
|
81
|
+
`${CONNECTION_ENTRY_VERSION}; this build refuses to write over it.`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
entry,
|
|
85
|
+
body: stored.body,
|
|
86
|
+
...(stored.etag !== undefined && { etag: stored.etag })
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The bounded compare-and-swap loop every directory write runs at one
|
|
91
|
+
* resource id: the upsert helpers here and the writer arm in `writers.ts`.
|
|
92
|
+
* Each attempt reads the resource, hands `change` the writable entry (or
|
|
93
|
+
* `undefined` when none stands), and writes the body it returns under
|
|
94
|
+
* `ifMatch` (or creates it under `ifNoneMatch`). A `stop` ends the loop with
|
|
95
|
+
* that outcome and no write. A lost race re-reads and re-applies, and after
|
|
96
|
+
* the last attempt the last `PreconditionFailedError` is thrown. `change`
|
|
97
|
+
* may throw a refusal, which ends the loop the same way.
|
|
98
|
+
*
|
|
99
|
+
* A stored body this build cannot write over (unparseable, misplaced, or
|
|
100
|
+
* from a newer build) throws, unless `unwritable` names the outcome to
|
|
101
|
+
* resolve with instead.
|
|
102
|
+
*
|
|
103
|
+
* @param options {object}
|
|
104
|
+
* @param options.store {ConnectionsStore}
|
|
105
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
106
|
+
* @param options.resourceId {string}
|
|
107
|
+
* @param options.change {Function}
|
|
108
|
+
* @param [options.unwritable] {Stop} the outcome for a body this build
|
|
109
|
+
* cannot write over; omitted, such a body throws
|
|
110
|
+
* @returns {Promise<object>} the id and the outcome: `created`, `updated`,
|
|
111
|
+
* or the `stop` the callback returned
|
|
112
|
+
*/
|
|
113
|
+
export async function writeConnection({ store, hmacKey, resourceId, change, unwritable }) {
|
|
114
|
+
let lastRace;
|
|
115
|
+
for (let attempt = 0; attempt < WRITE_ATTEMPTS; attempt++) {
|
|
116
|
+
const stored = await store.get({ resourceId });
|
|
117
|
+
let current;
|
|
118
|
+
if (stored !== undefined) {
|
|
119
|
+
try {
|
|
120
|
+
current = await writableConnection({ resourceId, stored, hmacKey });
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
if (unwritable === undefined) {
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
return { resourceId, outcome: unwritable };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const next = change(current);
|
|
130
|
+
if ('stop' in next) {
|
|
131
|
+
return { resourceId, outcome: next.stop };
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
if (current === undefined) {
|
|
135
|
+
await store.put({ resourceId, body: next.body, ifNoneMatch: true });
|
|
136
|
+
return { resourceId, outcome: 'created' };
|
|
137
|
+
}
|
|
138
|
+
await store.put({
|
|
139
|
+
resourceId,
|
|
140
|
+
body: next.body,
|
|
141
|
+
ifMatch: requireConnectionEtag({ resourceId, etag: current.etag })
|
|
142
|
+
});
|
|
143
|
+
return { resourceId, outcome: 'updated' };
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (!isLostConnectionRace(err)) {
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
lastRace = err;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
throw lastRace;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* {@link writeConnection} for the helpers here, keyed by the party's DID. A
|
|
156
|
+
* helper with nothing to write stops with `absent` (no entry at the id) or
|
|
157
|
+
* `unchanged`.
|
|
158
|
+
*
|
|
159
|
+
* @param options {object}
|
|
160
|
+
* @param options.store {ConnectionsStore}
|
|
161
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
162
|
+
* @param options.did {string} the party's DID
|
|
163
|
+
* @param options.change {Function}
|
|
164
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
165
|
+
*/
|
|
166
|
+
async function writePartyConnection({ store, hmacKey, did, change }) {
|
|
167
|
+
return writeConnection({
|
|
168
|
+
store,
|
|
169
|
+
hmacKey,
|
|
170
|
+
resourceId: await connectionResourceId({ hmacKey, did }),
|
|
171
|
+
change
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Refuses a stored entry of another kind than the writing flow's.
|
|
176
|
+
*
|
|
177
|
+
* @param options {object}
|
|
178
|
+
* @param options.entry {ConnectionEntry}
|
|
179
|
+
* @param options.kind {string}
|
|
180
|
+
*/
|
|
181
|
+
function assertKind({ entry, kind }) {
|
|
182
|
+
if (entry.kind !== kind) {
|
|
183
|
+
throw new ConnectionKindMismatchError({
|
|
184
|
+
expectedKind: kind,
|
|
185
|
+
foundKind: entry.kind
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The capability of one grant to record, checked strictly: its known members
|
|
191
|
+
* well-formed, its `controller` the party's DID, its `invocationTarget` under
|
|
192
|
+
* this Space, its kind one this build writes. The target check is the same
|
|
193
|
+
* one every reader applies, so a grant that is stored is a grant the
|
|
194
|
+
* revocation index will see.
|
|
195
|
+
*
|
|
196
|
+
* @param options {object}
|
|
197
|
+
* @param options.did {string}
|
|
198
|
+
* @param options.spaceUrl {string}
|
|
199
|
+
* @param options.grant {object}
|
|
200
|
+
* @returns {ConnectionZcap}
|
|
201
|
+
*/
|
|
202
|
+
function checkedGrant({ did, spaceUrl, grant }) {
|
|
203
|
+
const zcap = parseConnectionZcap(grant.zcap);
|
|
204
|
+
if (zcap === undefined) {
|
|
205
|
+
throw new TypeError('A grant to record must carry a capability with an id, a controller, ' +
|
|
206
|
+
'and an invocation target.');
|
|
207
|
+
}
|
|
208
|
+
if (zcap.controller !== did) {
|
|
209
|
+
throw new TypeError(`A grant to record must be delegated to the party "${did}"; its ` +
|
|
210
|
+
`controller is "${zcap.controller}".`);
|
|
211
|
+
}
|
|
212
|
+
if (!isTargetInSpace({ target: zcap.invocationTarget, spaceUrl })) {
|
|
213
|
+
throw new TypeError('A grant to record must target this Space; its invocation target is ' +
|
|
214
|
+
`"${zcap.invocationTarget}".`);
|
|
215
|
+
}
|
|
216
|
+
if (!GRANT_KINDS.includes(grant.grantKind)) {
|
|
217
|
+
throw new TypeError(`Unknown grant kind "${grant.grantKind}".`);
|
|
218
|
+
}
|
|
219
|
+
return zcap;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Records a consent on the party's entry: creates the entry, or merges into
|
|
223
|
+
* it. Each new grant is added by its capability id (one already recorded is
|
|
224
|
+
* left as stored), `name` is set when it passes the display-name rule (left
|
|
225
|
+
* as it was otherwise), `origin`, `url`, and `appKey` are set when given,
|
|
226
|
+
* `retired` is cleared, and `lastSeen` moves to `now`. `firstSeen` is set
|
|
227
|
+
* only on create, and `label` is never touched. A zero-grant consent writes
|
|
228
|
+
* too, so an App Connect app with no grants is indexed by its key.
|
|
229
|
+
*
|
|
230
|
+
* Refuses an entry of another kind with {@link ConnectionKindMismatchError},
|
|
231
|
+
* and a grant delegated to another party or targeting another Space with a
|
|
232
|
+
* `TypeError`, before anything is written.
|
|
233
|
+
*
|
|
234
|
+
* @param options {object}
|
|
235
|
+
* @param options.store {ConnectionsStore}
|
|
236
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
237
|
+
* @param options.did {string} the party's DID, every grant's controller
|
|
238
|
+
* @param options.kind {ConnectionKind} the kind this flow writes
|
|
239
|
+
* @param options.spaceUrl {string} this Space's container URL, every
|
|
240
|
+
* grant's target prefix
|
|
241
|
+
* @param options.grants {Array<object>} `{ zcap, grantKind }` per grant
|
|
242
|
+
* @param [options.name] {string} the party's self-declared name
|
|
243
|
+
* @param [options.origin] {string} the attested Web origin (App Connect)
|
|
244
|
+
* @param [options.url] {string} the canonical app URL (App Connect)
|
|
245
|
+
* @param [options.appKey] {string} the app-key Resource id (App Connect)
|
|
246
|
+
* @param [options.now] {Date}
|
|
247
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
248
|
+
*/
|
|
249
|
+
export async function recordGrants({ store, hmacKey, did, kind, spaceUrl, grants, name, origin, url, appKey, now = new Date() }) {
|
|
250
|
+
const stamp = now.toISOString();
|
|
251
|
+
const recorded = [];
|
|
252
|
+
const seen = new Set();
|
|
253
|
+
for (const grant of grants) {
|
|
254
|
+
const zcap = checkedGrant({ did, spaceUrl, grant });
|
|
255
|
+
if (!seen.has(zcap.id)) {
|
|
256
|
+
seen.add(zcap.id);
|
|
257
|
+
recorded.push({ zcap, grantKind: grant.grantKind, grantedAt: stamp });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const normalizedName = name === undefined ? undefined : normalizeDisplayName({ value: name });
|
|
261
|
+
const declared = {
|
|
262
|
+
...(normalizedName !== undefined && { name: normalizedName }),
|
|
263
|
+
...(origin !== undefined && { origin }),
|
|
264
|
+
...(url !== undefined && { url }),
|
|
265
|
+
...(appKey !== undefined && { appKey })
|
|
266
|
+
};
|
|
267
|
+
return writePartyConnection({
|
|
268
|
+
store,
|
|
269
|
+
hmacKey,
|
|
270
|
+
did,
|
|
271
|
+
change(current) {
|
|
272
|
+
if (current === undefined) {
|
|
273
|
+
return {
|
|
274
|
+
body: {
|
|
275
|
+
...newConnectionEntry({ kind, did, now }),
|
|
276
|
+
...declared,
|
|
277
|
+
grants: recorded
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
assertKind({ entry: current.entry, kind });
|
|
282
|
+
const held = new Set(current.entry.grants.map(grant => grant.zcap.id));
|
|
283
|
+
const body = {
|
|
284
|
+
...current.body,
|
|
285
|
+
...declared,
|
|
286
|
+
lastSeen: stamp,
|
|
287
|
+
grants: [
|
|
288
|
+
...current.entry.grants,
|
|
289
|
+
...recorded.filter(grant => !held.has(grant.zcap.id))
|
|
290
|
+
]
|
|
291
|
+
};
|
|
292
|
+
delete body.retired;
|
|
293
|
+
return { body };
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Removes grants from the party's entry by capability id, whatever the
|
|
299
|
+
* entry's kind. Used by an unshare after its revocation, and by a torn
|
|
300
|
+
* consent's rollback. An absent entry, or one holding none of the ids,
|
|
301
|
+
* writes nothing.
|
|
302
|
+
*
|
|
303
|
+
* @param options {object}
|
|
304
|
+
* @param options.store {ConnectionsStore}
|
|
305
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
306
|
+
* @param options.did {string} the party's DID
|
|
307
|
+
* @param options.zcapIds {Iterable<string>} the capability ids to remove
|
|
308
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
309
|
+
*/
|
|
310
|
+
export async function removeGrants({ store, hmacKey, did, zcapIds }) {
|
|
311
|
+
const removing = new Set(zcapIds);
|
|
312
|
+
return writePartyConnection({
|
|
313
|
+
store,
|
|
314
|
+
hmacKey,
|
|
315
|
+
did,
|
|
316
|
+
change(current) {
|
|
317
|
+
if (current === undefined) {
|
|
318
|
+
return { stop: 'absent' };
|
|
319
|
+
}
|
|
320
|
+
const kept = current.entry.grants.filter(grant => !removing.has(grant.zcap.id));
|
|
321
|
+
if (kept.length === current.entry.grants.length) {
|
|
322
|
+
return { stop: 'unchanged' };
|
|
323
|
+
}
|
|
324
|
+
return { body: { ...current.body, grants: kept } };
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Retires the party's entry, of any kind, once a revocation has handled its
|
|
330
|
+
* grants: empties `grants`, drops `appKey`, and stamps `retired`. `name`,
|
|
331
|
+
* `label`, `origin`, `url`, `firstSeen`, `lastSeen`, and `writers` stay, so a
|
|
332
|
+
* departed party keeps resolving. An entry already retired with nothing left
|
|
333
|
+
* to empty writes nothing, and an absent entry writes nothing.
|
|
334
|
+
*
|
|
335
|
+
* Throws when a read finds a grant that passes the reader checks and is not
|
|
336
|
+
* among `handledZcapIds`: a concurrent consent merged it, and the revocation
|
|
337
|
+
* must run again before the entry may retire. A grant that fails the reader
|
|
338
|
+
* checks (another party's controller, a target outside this Space) is not
|
|
339
|
+
* the party's, and the retirement empties it with the rest.
|
|
340
|
+
*
|
|
341
|
+
* @param options {object}
|
|
342
|
+
* @param options.store {ConnectionsStore}
|
|
343
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
344
|
+
* @param options.did {string} the party's DID
|
|
345
|
+
* @param options.handledZcapIds {Iterable<string>} the capability ids the
|
|
346
|
+
* revocation POSTed
|
|
347
|
+
* @param options.spaceUrl {string} this Space's container URL
|
|
348
|
+
* @param [options.now] {Date}
|
|
349
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
350
|
+
*/
|
|
351
|
+
export async function retireConnection({ store, hmacKey, did, handledZcapIds, spaceUrl, now = new Date() }) {
|
|
352
|
+
const handled = new Set(handledZcapIds);
|
|
353
|
+
return writePartyConnection({
|
|
354
|
+
store,
|
|
355
|
+
hmacKey,
|
|
356
|
+
did,
|
|
357
|
+
change(current) {
|
|
358
|
+
if (current === undefined) {
|
|
359
|
+
return { stop: 'absent' };
|
|
360
|
+
}
|
|
361
|
+
const unhandled = connectionGrants({
|
|
362
|
+
entry: current.entry,
|
|
363
|
+
spaceUrl
|
|
364
|
+
}).filter(grant => !handled.has(grant.zcapId));
|
|
365
|
+
if (unhandled.length > 0) {
|
|
366
|
+
throw new Error(`The connections entry carries ${unhandled.length} grant(s) this ` +
|
|
367
|
+
'revocation did not handle (a consent merged them since); the ' +
|
|
368
|
+
'revocation must run again before the entry retires.');
|
|
369
|
+
}
|
|
370
|
+
const { entry } = current;
|
|
371
|
+
if (entry.retired !== undefined &&
|
|
372
|
+
entry.grants.length === 0 &&
|
|
373
|
+
entry.appKey === undefined) {
|
|
374
|
+
return { stop: 'unchanged' };
|
|
375
|
+
}
|
|
376
|
+
const body = {
|
|
377
|
+
...current.body,
|
|
378
|
+
grants: [],
|
|
379
|
+
retired: entry.retired ?? now.toISOString()
|
|
380
|
+
};
|
|
381
|
+
delete body.appKey;
|
|
382
|
+
return { body };
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Sets the user's `label` on the party's entry, and its `name` when given.
|
|
388
|
+
* A blank `label` removes the member; an omitted one leaves it, and one
|
|
389
|
+
* outside the display-name rule is refused with a `TypeError`, since the
|
|
390
|
+
* user typed it and can shorten it. A `name` outside the rule is ignored. The enrollment approval writes
|
|
391
|
+
* the code's suggested label as `name` and passes `label` only when the
|
|
392
|
+
* approver edited it.
|
|
393
|
+
*
|
|
394
|
+
* Creates an absent entry only for a wallet client the verified account
|
|
395
|
+
* document lists (`kind: 'wallet-client'`, its did:key's signing-key
|
|
396
|
+
* multibase in `enrolledSigningKeys`), and throws for any other absent
|
|
397
|
+
* party. Refuses an entry of another kind with
|
|
398
|
+
* {@link ConnectionKindMismatchError}.
|
|
399
|
+
*
|
|
400
|
+
* @param options {object}
|
|
401
|
+
* @param options.store {ConnectionsStore}
|
|
402
|
+
* @param options.hmacKey {ConnectionIdKey}
|
|
403
|
+
* @param options.did {string} the party's DID
|
|
404
|
+
* @param options.kind {ConnectionKind} the kind the calling surface lists
|
|
405
|
+
* the party as
|
|
406
|
+
* @param [options.label] {string} the user's name for the party
|
|
407
|
+
* @param [options.name] {string} the party's name (a client's default
|
|
408
|
+
* platform label, or an enrollee's suggested label)
|
|
409
|
+
* @param [options.enrolledSigningKeys] {ReadonlySet<string>} the enrolled
|
|
410
|
+
* clients' signing-key multibases in the verified account document; needed
|
|
411
|
+
* to create a wallet client's entry
|
|
412
|
+
* @param [options.now] {Date}
|
|
413
|
+
* @returns {Promise<ConnectionWriteResult>}
|
|
414
|
+
*/
|
|
415
|
+
export async function setConnectionLabel({ store, hmacKey, did, kind, label, name, enrolledSigningKeys, now = new Date() }) {
|
|
416
|
+
const trimmedLabel = label?.trim();
|
|
417
|
+
const normalizedLabel = trimmedLabel
|
|
418
|
+
? normalizeDisplayName({ value: trimmedLabel })
|
|
419
|
+
: undefined;
|
|
420
|
+
if (trimmedLabel && normalizedLabel === undefined) {
|
|
421
|
+
throw new TypeError('A label is 1 to 64 code points once control and bidi characters are ' +
|
|
422
|
+
'stripped.');
|
|
423
|
+
}
|
|
424
|
+
const normalizedName = name === undefined ? undefined : normalizeDisplayName({ value: name });
|
|
425
|
+
return writePartyConnection({
|
|
426
|
+
store,
|
|
427
|
+
hmacKey,
|
|
428
|
+
did,
|
|
429
|
+
change(current) {
|
|
430
|
+
if (current === undefined) {
|
|
431
|
+
const multibase = signingKeyMultibaseOfDid({ did });
|
|
432
|
+
if (kind !== 'wallet-client' ||
|
|
433
|
+
multibase === undefined ||
|
|
434
|
+
enrolledSigningKeys?.has(multibase) !== true) {
|
|
435
|
+
throw new Error('No connections entry stands for this party, and one is created ' +
|
|
436
|
+
'here only for a wallet client the verified account document ' +
|
|
437
|
+
'lists.');
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
body: {
|
|
441
|
+
...newConnectionEntry({ kind, did, now }),
|
|
442
|
+
...(normalizedName !== undefined && { name: normalizedName }),
|
|
443
|
+
...(normalizedLabel !== undefined && { label: normalizedLabel })
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
assertKind({ entry: current.entry, kind });
|
|
448
|
+
const body = { ...current.body };
|
|
449
|
+
if (trimmedLabel !== undefined) {
|
|
450
|
+
if (normalizedLabel !== undefined) {
|
|
451
|
+
body.label = normalizedLabel;
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
delete body.label;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (normalizedName !== undefined) {
|
|
458
|
+
body.name = normalizedName;
|
|
459
|
+
}
|
|
460
|
+
if (body.label === current.body.label &&
|
|
461
|
+
body.name === current.body.name) {
|
|
462
|
+
return { stop: 'unchanged' };
|
|
463
|
+
}
|
|
464
|
+
return { body };
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
//# sourceMappingURL=upsert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert.js","sourceRoot":"","sources":["../../src/connections/upsert.ts"],"names":[],"mappings":"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"}
|