@interop/wallet-core 0.16.0 → 0.18.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 +13 -13
- package/dist/clients/index.d.ts +4 -3
- 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/policy.d.ts +3 -3
- package/dist/clients/policy.d.ts.map +1 -1
- package/dist/clients/policy.js +1 -1
- package/dist/clients/revocation.d.ts +18 -15
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +42 -26
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +46 -24
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +106 -48
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/descriptors/refresh.d.ts +3 -1
- package/dist/descriptors/refresh.d.ts.map +1 -1
- package/dist/descriptors/refresh.js +3 -1
- package/dist/descriptors/refresh.js.map +1 -1
- package/dist/display/alignment.d.ts +8 -2
- package/dist/display/alignment.d.ts.map +1 -1
- package/dist/display/alignment.js +11 -8
- package/dist/display/alignment.js.map +1 -1
- package/dist/display/displayFields.d.ts +6 -2
- package/dist/display/displayFields.d.ts.map +1 -1
- package/dist/display/displayFields.js.map +1 -1
- package/dist/display/evidence.d.ts +9 -3
- package/dist/display/evidence.d.ts.map +1 -1
- package/dist/display/evidence.js +3 -1
- package/dist/display/evidence.js.map +1 -1
- package/dist/display/index.d.ts +1 -1
- package/dist/display/index.d.ts.map +1 -1
- package/dist/display/index.js +1 -1
- package/dist/display/index.js.map +1 -1
- package/dist/display/issuer.d.ts +12 -4
- package/dist/display/issuer.d.ts.map +1 -1
- package/dist/display/issuer.js.map +1 -1
- package/dist/display/obv3.d.ts +7 -2
- package/dist/display/obv3.d.ts.map +1 -1
- package/dist/display/obv3.js +14 -24
- package/dist/display/obv3.js.map +1 -1
- package/dist/display/parse.d.ts +6 -2
- package/dist/display/parse.d.ts.map +1 -1
- package/dist/display/parse.js +6 -2
- package/dist/display/parse.js.map +1 -1
- package/dist/display/subject.d.ts +4 -0
- package/dist/display/subject.d.ts.map +1 -1
- package/dist/display/subject.js +12 -10
- package/dist/display/subject.js.map +1 -1
- package/dist/display/text.d.ts +11 -0
- package/dist/display/text.d.ts.map +1 -1
- package/dist/display/text.js +20 -4
- package/dist/display/text.js.map +1 -1
- package/dist/display/types.js +1 -1
- package/dist/display/types.js.map +1 -1
- package/dist/display/validity.js +4 -4
- package/dist/display/validity.js.map +1 -1
- package/dist/display/verificationView.d.ts +21 -7
- package/dist/display/verificationView.d.ts.map +1 -1
- package/dist/display/verificationView.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +21 -19
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +98 -34
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/enrollment/index.d.ts +1 -1
- package/dist/enrollment/index.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/keys/clientKeyRecord.d.ts +19 -17
- package/dist/keys/clientKeyRecord.d.ts.map +1 -1
- package/dist/keys/clientKeyRecord.js +77 -41
- package/dist/keys/clientKeyRecord.js.map +1 -1
- package/dist/keys/index.d.ts +19 -17
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +16 -14
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterStore.d.ts +3 -3
- package/dist/keys/rosterStore.d.ts.map +1 -1
- package/dist/keys/rosterStore.js +13 -13
- package/dist/keys/rosterStore.js.map +1 -1
- package/dist/keys/userKey.d.ts +43 -0
- package/dist/keys/userKey.d.ts.map +1 -0
- package/dist/keys/{puk.js → userKey.js} +23 -21
- package/dist/keys/userKey.js.map +1 -0
- package/dist/keys/{pukCascade.d.ts → userKeyCascade.d.ts} +69 -69
- package/dist/keys/userKeyCascade.d.ts.map +1 -0
- package/dist/keys/{pukCascade.js → userKeyCascade.js} +77 -75
- package/dist/keys/userKeyCascade.js.map +1 -0
- package/dist/keys/{pukRoster.d.ts → userKeyRoster.d.ts} +141 -64
- package/dist/keys/userKeyRoster.d.ts.map +1 -0
- package/dist/keys/{pukRoster.js → userKeyRoster.js} +200 -72
- package/dist/keys/userKeyRoster.js.map +1 -0
- package/dist/recovery/index.d.ts +1 -1
- package/dist/recovery/index.js +1 -1
- package/dist/recovery/recoveryCode.d.ts +1 -1
- package/dist/recovery/recoveryCode.js +6 -6
- package/dist/recovery/recoveryRecord.d.ts +1 -1
- package/dist/recovery/recoveryWebvh.d.ts +1 -1
- package/dist/recovery/recoveryWebvh.js +1 -1
- package/dist/request/classify.d.ts +15 -1
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +38 -14
- package/dist/request/classify.js.map +1 -1
- package/dist/request/composeVp.d.ts.map +1 -1
- package/dist/request/composeVp.js +10 -3
- package/dist/request/composeVp.js.map +1 -1
- package/dist/request/matching.d.ts +6 -0
- package/dist/request/matching.d.ts.map +1 -1
- package/dist/request/matching.js +33 -8
- package/dist/request/matching.js.map +1 -1
- package/dist/request/parse.d.ts +5 -2
- package/dist/request/parse.d.ts.map +1 -1
- package/dist/request/parse.js +30 -5
- package/dist/request/parse.js.map +1 -1
- package/dist/request/presentationSuite.d.ts.map +1 -1
- package/dist/request/presentationSuite.js +6 -2
- package/dist/request/presentationSuite.js.map +1 -1
- package/dist/request/processRequest.js +1 -1
- package/dist/request/processRequest.js.map +1 -1
- package/dist/space/activity.d.ts +22 -8
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +19 -7
- package/dist/space/activity.js.map +1 -1
- package/dist/space/collections.d.ts +33 -21
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +34 -22
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +2 -2
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +2 -2
- package/dist/space/index.js.map +1 -1
- package/dist/space/wasLink.d.ts +6 -2
- package/dist/space/wasLink.d.ts.map +1 -1
- package/dist/space/wasLink.js +5 -2
- package/dist/space/wasLink.js.map +1 -1
- package/dist/sync/contactsConflict.d.ts +1 -1
- package/dist/sync/contactsConflict.js +1 -1
- package/dist/sync/engine.d.ts +33 -11
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +4 -3
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/pull.d.ts +5 -3
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +34 -10
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +24 -8
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +30 -6
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/webvh/didWebvh.d.ts +29 -1
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +46 -11
- package/dist/webvh/didWebvh.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 +1 -1
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/listClients.d.ts +19 -0
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +37 -1
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +11 -3
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +83 -14
- package/dist/webvh/revokeClient.js.map +1 -1
- package/package.json +3 -3
- package/dist/keys/puk.d.ts +0 -42
- package/dist/keys/puk.d.ts.map +0 -1
- package/dist/keys/puk.js.map +0 -1
- package/dist/keys/pukCascade.d.ts.map +0 -1
- package/dist/keys/pukCascade.js.map +0 -1
- package/dist/keys/pukRoster.d.ts.map +0 -1
- package/dist/keys/pukRoster.js.map +0 -1
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { addRecipient, initRecipients, ownerRecipient, removeRecipient, unwrapEpochSecret, verifyEpochsMac } from '@interop/was-client/edv';
|
|
1
|
+
import { addRecipient, epochsSigPayload, initRecipients, ownerRecipient, removeRecipient, unwrapEpochSecret, verifyEpochsMac } from '@interop/was-client/edv';
|
|
2
|
+
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key';
|
|
3
|
+
import { base64urlnopad } from '@scure/base';
|
|
4
|
+
import { clientSigningKeyMultibase } from '../webvh/zcap.js';
|
|
2
5
|
/**
|
|
3
6
|
* Thrown when a served roster fails its client-side authentication: a
|
|
4
7
|
* missing/unsupported/invalid `epochsMac`, or a descriptor whose `currentEpoch`
|
|
5
8
|
* names no epoch in its own list. The server (or whoever can write to it) has
|
|
6
9
|
* produced a configuration no enrolled client authenticated.
|
|
7
10
|
*/
|
|
8
|
-
export class
|
|
11
|
+
export class UserKeyRosterIntegrityError extends Error {
|
|
9
12
|
constructor(message) {
|
|
10
13
|
super(message);
|
|
11
|
-
this.name = '
|
|
14
|
+
this.name = 'UserKeyRosterIntegrityError';
|
|
12
15
|
}
|
|
13
16
|
}
|
|
14
17
|
/**
|
|
@@ -18,25 +21,105 @@ export class PukRosterIntegrityError extends Error {
|
|
|
18
21
|
* an older consistent configuration, which a valid `epochsMac` alone cannot
|
|
19
22
|
* catch; refused rather than followed.
|
|
20
23
|
*/
|
|
21
|
-
export class
|
|
24
|
+
export class UserKeyRosterContinuityError extends Error {
|
|
22
25
|
pinnedEpochId;
|
|
23
26
|
constructor({ pinnedEpochId }) {
|
|
24
|
-
super('The
|
|
27
|
+
super('The user key roster no longer carries the epoch this client has pinned -- ' +
|
|
25
28
|
'a rolled-back or replayed roster.');
|
|
26
|
-
this.name = '
|
|
29
|
+
this.name = 'UserKeyRosterContinuityError';
|
|
27
30
|
this.pinnedEpochId = pinnedEpochId;
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* Thrown when this client holds no usable wrap in the roster's current epoch
|
|
32
35
|
* (no recipient entry for its key-agreement key, or the entry fails to
|
|
33
|
-
* unwrap). The client cannot obtain the current
|
|
36
|
+
* unwrap). The client cannot obtain the current user key -- it may have been
|
|
34
37
|
* rotated off the roster.
|
|
35
38
|
*/
|
|
36
|
-
export class
|
|
39
|
+
export class UserKeyRosterUnwrapError extends Error {
|
|
37
40
|
constructor(message) {
|
|
38
41
|
super(message);
|
|
39
|
-
this.name = '
|
|
42
|
+
this.name = 'UserKeyRosterUnwrapError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The `epochsSig` construction this module mints and accepts: version 1,
|
|
47
|
+
* Ed25519 (`EdDSA`), `kid` the signer's public-key multibase (`z6Mk...`) --
|
|
48
|
+
* the same string that names the client's verification method in the
|
|
49
|
+
* did:webvh document.
|
|
50
|
+
*/
|
|
51
|
+
const EPOCHS_SIG_V = 1;
|
|
52
|
+
const EPOCHS_SIG_ALG = 'EdDSA';
|
|
53
|
+
/**
|
|
54
|
+
* The roster's epoch-configuration signer: signs each roster write's epoch
|
|
55
|
+
* configuration with this client's own Ed25519 signing key, under a `kid`
|
|
56
|
+
* that is the key's public multibase -- exactly the string enrolled as this
|
|
57
|
+
* client's verification method in the did:webvh document, so a reader
|
|
58
|
+
* resolves the signature against the document rather than anything the
|
|
59
|
+
* roster (or the server) supplies.
|
|
60
|
+
*
|
|
61
|
+
* @param options {object}
|
|
62
|
+
* @param options.keyAgent {ICapabilityAgent} this client's signing key
|
|
63
|
+
* agent (the `keyAgent` of `agentsFromSeed`)
|
|
64
|
+
* @returns {EpochsSigner} the `signEpochs` hook for roster writes
|
|
65
|
+
*/
|
|
66
|
+
export function userKeyRosterEpochsSigner({ keyAgent }) {
|
|
67
|
+
const kid = clientSigningKeyMultibase({ keyAgent });
|
|
68
|
+
const signer = keyAgent.getSigner();
|
|
69
|
+
return async function signEpochs({ payload }) {
|
|
70
|
+
const signature = await signer.sign({ data: payload });
|
|
71
|
+
return {
|
|
72
|
+
v: EPOCHS_SIG_V,
|
|
73
|
+
alg: EPOCHS_SIG_ALG,
|
|
74
|
+
kid,
|
|
75
|
+
sig: base64urlnopad.encode(signature)
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Verifies a served roster's `epochsSig` against the locally verified
|
|
81
|
+
* did:webvh document -- the root of trust the server cannot mint. The
|
|
82
|
+
* signature must be present and supported, its `kid` must be the public
|
|
83
|
+
* multibase of one of the document's verification methods (an enrolled
|
|
84
|
+
* client's signing key), and it must verify over the canonical
|
|
85
|
+
* epoch-configuration payload. Throws {@link UserKeyRosterIntegrityError}
|
|
86
|
+
* otherwise: a configuration no enrolled client signed.
|
|
87
|
+
*
|
|
88
|
+
* @param options {object}
|
|
89
|
+
* @param options.descriptor {CollectionEncryption} the served roster
|
|
90
|
+
* @param options.document {RosterRecipientDocument} the locally verified
|
|
91
|
+
* did:webvh document (never a server-supplied roster field)
|
|
92
|
+
* @returns {Promise<void>}
|
|
93
|
+
*/
|
|
94
|
+
export async function verifyUserKeyRosterEpochsSig({ descriptor, document }) {
|
|
95
|
+
const epochsSig = descriptor.epochsSig;
|
|
96
|
+
if (!epochsSig ||
|
|
97
|
+
epochsSig.v !== EPOCHS_SIG_V ||
|
|
98
|
+
epochsSig.alg !== EPOCHS_SIG_ALG) {
|
|
99
|
+
throw new UserKeyRosterIntegrityError('The user key roster carries no supported epoch-configuration signature.');
|
|
100
|
+
}
|
|
101
|
+
const backed = (document.verificationMethod ?? []).some(method => method.publicKeyMultibase === epochsSig.kid);
|
|
102
|
+
if (!backed) {
|
|
103
|
+
throw new UserKeyRosterIntegrityError('The user key roster epoch configuration is signed by a key the account ' +
|
|
104
|
+
'document does not back.');
|
|
105
|
+
}
|
|
106
|
+
let signature;
|
|
107
|
+
try {
|
|
108
|
+
signature = base64urlnopad.decode(epochsSig.sig);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new UserKeyRosterIntegrityError('The user key roster epoch-configuration signature is malformed.');
|
|
112
|
+
}
|
|
113
|
+
const verifier = new Ed25519VerificationKey({
|
|
114
|
+
controller: `did:key:${epochsSig.kid}`,
|
|
115
|
+
publicKeyMultibase: epochsSig.kid
|
|
116
|
+
}).verifier();
|
|
117
|
+
const verified = await verifier.verify({
|
|
118
|
+
data: epochsSigPayload(descriptor),
|
|
119
|
+
signature
|
|
120
|
+
});
|
|
121
|
+
if (!verified) {
|
|
122
|
+
throw new UserKeyRosterIntegrityError('The user key roster epoch-configuration signature failed verification.');
|
|
40
123
|
}
|
|
41
124
|
}
|
|
42
125
|
/**
|
|
@@ -84,7 +167,7 @@ function multibaseFragmentOf(id) {
|
|
|
84
167
|
* did:webvh document (never a server-supplied roster field)
|
|
85
168
|
* @returns {function} a `resolveRecipientKey` for `removeRecipient`
|
|
86
169
|
*/
|
|
87
|
-
export function
|
|
170
|
+
export function userKeyRosterRecipientResolver({ document }) {
|
|
88
171
|
// Materialize the document's keyAgreement VMs once: embedded VMs verbatim,
|
|
89
172
|
// string references resolved against `verificationMethod`.
|
|
90
173
|
const byId = new Map();
|
|
@@ -116,22 +199,25 @@ export function pukRosterRecipientResolver({ document }) {
|
|
|
116
199
|
};
|
|
117
200
|
}
|
|
118
201
|
/**
|
|
119
|
-
* Ensures the roster exists, create-if-absent: an absent roster is
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
202
|
+
* Ensures the roster exists, create-if-absent: an absent roster is initialized
|
|
203
|
+
* with the account's existing user key installed as the first epoch, wrapped to
|
|
204
|
+
* this client's key-agreement key; an existing roster is returned as-is
|
|
205
|
+
* (authentication is the read path's job, and provisioning must never clobber
|
|
206
|
+
* an established roster). Idempotent -- losing the guarded-create race to a
|
|
207
|
+
* concurrent first init converges on the winner's roster.
|
|
125
208
|
*
|
|
126
209
|
* @param options {object}
|
|
127
210
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
128
211
|
* store
|
|
129
|
-
* @param options.
|
|
212
|
+
* @param options.userKey {UserKey} the account's user key
|
|
130
213
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
131
214
|
* (identity) key-agreement key -- the roster recipient
|
|
215
|
+
* @param options.signEpochs {EpochsSigner} this client's epoch-configuration
|
|
216
|
+
* signer ({@link userKeyRosterEpochsSigner}), so the first configuration is
|
|
217
|
+
* vouched for by an enrollable key rather than only its own MAC
|
|
132
218
|
* @returns {Promise<CollectionEncryption>} the roster descriptor
|
|
133
219
|
*/
|
|
134
|
-
export async function
|
|
220
|
+
export async function ensureUserKeyRoster({ store, userKey, clientKeyAgreementKey, signEpochs }) {
|
|
135
221
|
const current = await store.read();
|
|
136
222
|
if (current !== null) {
|
|
137
223
|
return current.descriptor;
|
|
@@ -139,11 +225,12 @@ export async function ensurePukRoster({ store, puk, clientKeyAgreementKey }) {
|
|
|
139
225
|
return initRecipients({
|
|
140
226
|
store,
|
|
141
227
|
recipients: [ownerRecipient({ keyAgreementKey: clientKeyAgreementKey })],
|
|
142
|
-
epoch: { epochId:
|
|
228
|
+
epoch: { epochId: userKey.id, secret: userKey.secret },
|
|
229
|
+
signEpochs
|
|
143
230
|
});
|
|
144
231
|
}
|
|
145
232
|
/**
|
|
146
|
-
* Wraps the
|
|
233
|
+
* Wraps the user key to a client being enrolled -- the roster half of the
|
|
147
234
|
* enrollment ceremony, and deliberately its FIRST write (decryption material
|
|
148
235
|
* before authorization, the push order): the wrap lands before the did:webvh
|
|
149
236
|
* log entries, so no enrolled client is ever authorized but blind, and a tear
|
|
@@ -168,10 +255,10 @@ export async function ensurePukRoster({ store, puk, clientKeyAgreementKey }) {
|
|
|
168
255
|
* re-wrapping
|
|
169
256
|
* @returns {Promise<CollectionEncryption>} the refreshed roster descriptor
|
|
170
257
|
*/
|
|
171
|
-
export async function
|
|
258
|
+
export async function addUserKeyRosterRecipient({ store, recipient, ownerKeyAgreementKey }) {
|
|
172
259
|
const current = await store.read();
|
|
173
260
|
if (current === null) {
|
|
174
|
-
throw new Error('The
|
|
261
|
+
throw new Error('The user key roster does not exist yet; the account must finish ' +
|
|
175
262
|
'provisioning before a client can be enrolled.');
|
|
176
263
|
}
|
|
177
264
|
const descriptor = current.descriptor;
|
|
@@ -190,16 +277,16 @@ export async function addPukRosterRecipient({ store, recipient, ownerKeyAgreemen
|
|
|
190
277
|
});
|
|
191
278
|
}
|
|
192
279
|
/**
|
|
193
|
-
* Rotates the
|
|
194
|
-
* enrolled wallet client or a recovery code. A thin, deliberate composition
|
|
280
|
+
* Rotates the user key roster off one recipient -- the roster half of revoking
|
|
281
|
+
* an enrolled wallet client or a recovery code. A thin, deliberate composition
|
|
195
282
|
* of was-client's `removeRecipient` with the two roster-specific choices
|
|
196
|
-
* spelled once: the remaining recipients are resolved from the locally
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
283
|
+
* spelled once: the remaining recipients are resolved from the locally verified
|
|
284
|
+
* did:webvh document ("the roster delivers, never sources" -- an entry with no
|
|
285
|
+
* matching `keyAgreement` verification method is dropped and never receives a
|
|
286
|
+
* wrap), and the pull axis is a no-op, because for a roster recipient the pull
|
|
287
|
+
* axis IS the document edit the caller performed first -- under the
|
|
288
|
+
* current-key-set rule the removed party's server-side access died the moment
|
|
289
|
+
* its verification method left the document.
|
|
203
290
|
*
|
|
204
291
|
* @param options {object}
|
|
205
292
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
@@ -208,21 +295,25 @@ export async function addPukRosterRecipient({ store, recipient, ownerKeyAgreemen
|
|
|
208
295
|
* did:webvh document, AFTER the removal edit
|
|
209
296
|
* @param options.retireRecipientId {string} the removed recipient's roster
|
|
210
297
|
* kid
|
|
298
|
+
* @param options.signEpochs {EpochsSigner} the rotating client's
|
|
299
|
+
* epoch-configuration signer ({@link userKeyRosterEpochsSigner}), vouching for
|
|
300
|
+
* the fresh epoch so other clients' rotated reads accept it
|
|
211
301
|
* @returns {Promise<CollectionEncryption>} the rotated roster descriptor
|
|
212
302
|
*/
|
|
213
|
-
export async function
|
|
303
|
+
export async function rotateUserKeyRoster({ store, document, retireRecipientId, signEpochs }) {
|
|
214
304
|
return removeRecipient({
|
|
215
305
|
store,
|
|
216
306
|
recipientId: retireRecipientId,
|
|
217
|
-
resolveRecipientKey:
|
|
218
|
-
pull: async () => { }
|
|
307
|
+
resolveRecipientKey: userKeyRosterRecipientResolver({ document }),
|
|
308
|
+
pull: async () => { },
|
|
309
|
+
signEpochs
|
|
219
310
|
});
|
|
220
311
|
}
|
|
221
312
|
/**
|
|
222
313
|
* Converges the roster onto the account document: the standing detector for a
|
|
223
314
|
* revocation cascade torn between its two halves. The cascade edits the
|
|
224
315
|
* document first and rotates the roster second, so a client that crashes in
|
|
225
|
-
* between leaves a roster that keeps wrapping the CURRENT
|
|
316
|
+
* between leaves a roster that keeps wrapping the CURRENT user key to a
|
|
226
317
|
* recipient the document no longer keys -- durable, silent, and permanent,
|
|
227
318
|
* since the revoked client's document edit will never be re-run.
|
|
228
319
|
*
|
|
@@ -230,7 +321,7 @@ export async function rotatePukRoster({ store, document, retireRecipientId }) {
|
|
|
230
321
|
* document-backed resolver cannot answer for is exactly a recipient the
|
|
231
322
|
* document no longer keys, so a healthy account reads the descriptor and
|
|
232
323
|
* writes nothing. When any such recipient is found the roster is rotated away
|
|
233
|
-
* from ALL of them at once -- a single {@link
|
|
324
|
+
* from ALL of them at once -- a single {@link rotateUserKeyRoster} suffices,
|
|
234
325
|
* because the resolver drops every unbacked entry from the fresh epoch, not
|
|
235
326
|
* just the one named as retiring.
|
|
236
327
|
*
|
|
@@ -239,8 +330,8 @@ export async function rotatePukRoster({ store, document, retireRecipientId }) {
|
|
|
239
330
|
* account), not a cascade to finish, and completing it would lock every
|
|
240
331
|
* client out of the account.
|
|
241
332
|
*
|
|
242
|
-
* The fresh
|
|
243
|
-
* ordinary way, by re-reading the roster ({@link
|
|
333
|
+
* The fresh user key itself is not returned: the caller adopts it the
|
|
334
|
+
* ordinary way, by re-reading the roster ({@link readUserKeyRoster}) once
|
|
244
335
|
* `rotated` says there is something to adopt, and then runs the collection
|
|
245
336
|
* fan-out.
|
|
246
337
|
*
|
|
@@ -252,11 +343,14 @@ export async function rotatePukRoster({ store, document, retireRecipientId }) {
|
|
|
252
343
|
* @param [options.descriptor] {CollectionEncryption} a descriptor the caller
|
|
253
344
|
* has just read (a login-time roster read), to save a re-read; omitted, the
|
|
254
345
|
* roster is read fresh
|
|
346
|
+
* @param options.signEpochs {EpochsSigner} the converging client's
|
|
347
|
+
* epoch-configuration signer ({@link userKeyRosterEpochsSigner}), for the
|
|
348
|
+
* rotation this call may perform
|
|
255
349
|
* @returns {Promise<object>} whether the roster rotated on this call, the
|
|
256
350
|
* stale recipient kids found, and the roster descriptor as it now stands
|
|
257
351
|
* (`null` when the account has no roster yet)
|
|
258
352
|
*/
|
|
259
|
-
export async function
|
|
353
|
+
export async function convergeUserKeyRosterToDocument({ store, document, descriptor, signEpochs }) {
|
|
260
354
|
let roster = descriptor;
|
|
261
355
|
if (!roster) {
|
|
262
356
|
const read = await store.read();
|
|
@@ -268,9 +362,9 @@ export async function convergePukRosterToDocument({ store, document, descriptor
|
|
|
268
362
|
const currentEpochId = roster.currentEpoch;
|
|
269
363
|
const currentEpoch = (roster.epochs ?? []).find(epoch => epoch.id === currentEpochId);
|
|
270
364
|
if (!currentEpoch) {
|
|
271
|
-
throw new
|
|
365
|
+
throw new UserKeyRosterIntegrityError('The user key roster names no current epoch in its own epoch list.');
|
|
272
366
|
}
|
|
273
|
-
const resolveRecipientKey =
|
|
367
|
+
const resolveRecipientKey = userKeyRosterRecipientResolver({ document });
|
|
274
368
|
const staleRecipientIds = [];
|
|
275
369
|
let backed = 0;
|
|
276
370
|
for (const entry of currentEpoch.recipients) {
|
|
@@ -286,15 +380,16 @@ export async function convergePukRosterToDocument({ store, document, descriptor
|
|
|
286
380
|
return { rotated: false, staleRecipientIds, descriptor: roster };
|
|
287
381
|
}
|
|
288
382
|
if (backed === 0) {
|
|
289
|
-
throw new
|
|
383
|
+
throw new UserKeyRosterIntegrityError('No user key roster recipient is keyed by the account document; refusing ' +
|
|
290
384
|
'to rotate the roster onto no one.');
|
|
291
385
|
}
|
|
292
386
|
// One rotation retires them all: the fresh epoch is wrapped only to the
|
|
293
387
|
// recipients the resolver answers for.
|
|
294
|
-
const rotated = await
|
|
388
|
+
const rotated = await rotateUserKeyRoster({
|
|
295
389
|
store,
|
|
296
390
|
document,
|
|
297
|
-
retireRecipientId: staleRecipientIds[0]
|
|
391
|
+
retireRecipientId: staleRecipientIds[0],
|
|
392
|
+
signEpochs
|
|
298
393
|
});
|
|
299
394
|
return { rotated: true, staleRecipientIds, descriptor: rotated };
|
|
300
395
|
}
|
|
@@ -305,34 +400,51 @@ export async function convergePukRosterToDocument({ store, document, descriptor
|
|
|
305
400
|
*
|
|
306
401
|
* 1. **Continuity**: the served epochs must contain the pinned latest-seen
|
|
307
402
|
* epoch, and `currentEpoch` must not precede it in the append-only list
|
|
308
|
-
* (`
|
|
309
|
-
* 2. **Possession**: `currentEpoch ===
|
|
403
|
+
* (`UserKeyRosterContinuityError` -- the rollback/replay refusal).
|
|
404
|
+
* 2. **Possession**: `currentEpoch === userKey.id` confirms the cached user key
|
|
310
405
|
* current; otherwise the current epoch was rotated by another client and
|
|
311
406
|
* this client's wrap is unwrapped with its own key-agreement key
|
|
312
|
-
* (`
|
|
313
|
-
* 3. **
|
|
314
|
-
*
|
|
407
|
+
* (`UserKeyRosterUnwrapError` when it holds none).
|
|
408
|
+
* 3. **Provenance** (the rotated/first-read path only): the epoch
|
|
409
|
+
* configuration's `epochsSig` is verified against the locally verified
|
|
410
|
+
* did:webvh document ({@link verifyUserKeyRosterEpochsSig}) BEFORE the epoch
|
|
411
|
+
* it delivers is adopted. On this path the `epochsMac` alone proves
|
|
412
|
+
* nothing against the host -- its key is unwrapped from the served
|
|
413
|
+
* descriptor itself -- so an epoch no enrolled client signed is refused
|
|
414
|
+
* (`UserKeyRosterIntegrityError`). The cached-current path needs no signature:
|
|
415
|
+
* there the MAC is keyed by a secret this client already trusts.
|
|
416
|
+
* 4. **Authentication**: the descriptor's `epochsMac` is verified under the
|
|
417
|
+
* current epoch's secret (`UserKeyRosterIntegrityError` on any mismatch -- a
|
|
315
418
|
* fabricated configuration).
|
|
316
419
|
*
|
|
317
|
-
* A rotated read returns the fresh
|
|
420
|
+
* A rotated read returns the fresh user key; its Ed25519 signing seed does not
|
|
318
421
|
* travel through the roster (the roster wraps the key-agreement secret
|
|
319
|
-
* alone), so the returned
|
|
422
|
+
* alone), so the returned user key carries none.
|
|
320
423
|
*
|
|
321
|
-
* A caller with no cached
|
|
322
|
-
* first post-enrollment read -- omits `
|
|
323
|
-
* the result's `rotated` is then true (the
|
|
424
|
+
* A caller with no cached user key at all -- a freshly enrolled client making
|
|
425
|
+
* its first post-enrollment read -- omits `userKey` and always takes the unwrap
|
|
426
|
+
* path; the result's `rotated` is then true (the user key was adopted from the
|
|
427
|
+
* roster). Every unwrap-path caller must therefore supply the account document
|
|
428
|
+
* (or a way to resolve it): `document` when it already holds a verified copy,
|
|
429
|
+
* or `resolveDocument` to fetch-and-verify lazily, only when the read actually
|
|
430
|
+
* rotates.
|
|
324
431
|
*
|
|
325
432
|
* @param options {object}
|
|
326
433
|
* @param options.store {EncryptionDescriptorStore} the roster's descriptor
|
|
327
434
|
* store
|
|
328
|
-
* @param [options.
|
|
435
|
+
* @param [options.userKey] {UserKey} this client's cached user key, when it holds one
|
|
329
436
|
* @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
|
|
330
437
|
* (identity) key-agreement key, unwrapping a rotated epoch
|
|
331
438
|
* @param [options.pinnedEpochId] {string} the locally pinned latest-seen
|
|
332
439
|
* roster epoch, when this client has seen the roster before
|
|
333
|
-
* @
|
|
440
|
+
* @param [options.document] {RosterRecipientDocument} the locally verified
|
|
441
|
+
* did:webvh document, when the caller already holds one
|
|
442
|
+
* @param [options.resolveDocument] {function} resolves the locally verified
|
|
443
|
+
* did:webvh document on demand; called only when the read takes the
|
|
444
|
+
* rotated/first-read path
|
|
445
|
+
* @returns {Promise<UserKeyRosterReadResult | null>}
|
|
334
446
|
*/
|
|
335
|
-
export async function
|
|
447
|
+
export async function readUserKeyRoster({ store, userKey, clientKeyAgreementKey, pinnedEpochId, document, resolveDocument }) {
|
|
336
448
|
const current = await store.read();
|
|
337
449
|
if (current === null) {
|
|
338
450
|
return null;
|
|
@@ -343,50 +455,66 @@ export async function readPukRoster({ store, puk, clientKeyAgreementKey, pinnedE
|
|
|
343
455
|
? epochIds.indexOf(descriptor.currentEpoch)
|
|
344
456
|
: -1;
|
|
345
457
|
if (currentIndex === -1) {
|
|
346
|
-
throw new
|
|
458
|
+
throw new UserKeyRosterIntegrityError('The user key roster names no current epoch in its own epoch list.');
|
|
347
459
|
}
|
|
348
460
|
if (pinnedEpochId) {
|
|
349
461
|
const pinnedIndex = epochIds.indexOf(pinnedEpochId);
|
|
350
462
|
if (pinnedIndex === -1 || currentIndex < pinnedIndex) {
|
|
351
|
-
throw new
|
|
463
|
+
throw new UserKeyRosterContinuityError({ pinnedEpochId });
|
|
352
464
|
}
|
|
353
465
|
}
|
|
354
466
|
// The epochsMac construction's own version/alg are the caller's to check.
|
|
355
467
|
const epochsMac = descriptor.epochsMac;
|
|
356
468
|
if (!epochsMac || epochsMac.v !== 1 || epochsMac.alg !== 'HS256') {
|
|
357
|
-
throw new
|
|
469
|
+
throw new UserKeyRosterIntegrityError('The user key roster carries no supported epoch-configuration MAC.');
|
|
358
470
|
}
|
|
359
|
-
let
|
|
471
|
+
let currentUserKey;
|
|
360
472
|
let rotated;
|
|
361
|
-
if (
|
|
362
|
-
|
|
473
|
+
if (userKey && descriptor.currentEpoch === userKey.id) {
|
|
474
|
+
currentUserKey = userKey;
|
|
363
475
|
rotated = false;
|
|
364
476
|
}
|
|
365
477
|
else {
|
|
366
|
-
// Rotated by another client
|
|
367
|
-
// epoch
|
|
478
|
+
// Rotated by another client (or this client's first read): before
|
|
479
|
+
// adopting the delivered epoch, trace it to a root of trust the server
|
|
480
|
+
// cannot mint -- the epoch configuration must be signed by a key the
|
|
481
|
+
// locally verified account document backs. The epochsMac below cannot
|
|
482
|
+
// carry this: on this path its key comes out of the served descriptor
|
|
483
|
+
// itself.
|
|
484
|
+
const accountDocument = document ?? (resolveDocument ? await resolveDocument() : undefined);
|
|
485
|
+
if (!accountDocument) {
|
|
486
|
+
throw new Error('A user key roster read that adopts an epoch from the roster needs the ' +
|
|
487
|
+
'account document (pass `document` or `resolveDocument`) to verify ' +
|
|
488
|
+
'the epoch configuration signature.');
|
|
489
|
+
}
|
|
490
|
+
await verifyUserKeyRosterEpochsSig({
|
|
491
|
+
descriptor,
|
|
492
|
+
document: accountDocument
|
|
493
|
+
});
|
|
494
|
+
// Unwrap this client's entry in the current epoch with its own
|
|
495
|
+
// key-agreement key (rotation delivery).
|
|
368
496
|
const entry = descriptor.epochs[currentIndex].recipients.find(recipient => recipient.header.kid === clientKeyAgreementKey.id);
|
|
369
497
|
if (!entry) {
|
|
370
|
-
throw new
|
|
498
|
+
throw new UserKeyRosterUnwrapError('The user key roster current epoch carries no wrap for this client.');
|
|
371
499
|
}
|
|
372
500
|
const secret = await unwrapEpochSecret({
|
|
373
501
|
entry,
|
|
374
502
|
keyAgreementKey: clientKeyAgreementKey
|
|
375
503
|
});
|
|
376
504
|
if (!secret) {
|
|
377
|
-
throw new
|
|
505
|
+
throw new UserKeyRosterUnwrapError("This client's user key roster entry failed to unwrap.");
|
|
378
506
|
}
|
|
379
|
-
|
|
507
|
+
currentUserKey = { id: descriptor.currentEpoch, secret };
|
|
380
508
|
rotated = true;
|
|
381
509
|
}
|
|
382
|
-
if (!(await verifyEpochsMac({ descriptor, epochSecret:
|
|
383
|
-
throw new
|
|
510
|
+
if (!(await verifyEpochsMac({ descriptor, epochSecret: currentUserKey.secret }))) {
|
|
511
|
+
throw new UserKeyRosterIntegrityError('The user key roster epoch configuration failed authentication.');
|
|
384
512
|
}
|
|
385
513
|
return {
|
|
386
514
|
descriptor,
|
|
387
|
-
|
|
515
|
+
userKey: currentUserKey,
|
|
388
516
|
rotated,
|
|
389
517
|
latestEpochId: descriptor.currentEpoch
|
|
390
518
|
};
|
|
391
519
|
}
|
|
392
|
-
//# sourceMappingURL=
|
|
520
|
+
//# sourceMappingURL=userKeyRoster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userKeyRoster.js","sourceRoot":"","sources":["../../src/keys/userKeyRoster.ts"],"names":[],"mappings":"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"}
|
package/dist/recovery/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* single did:webvh update key whose hash stands pre-committed.
|
|
15
15
|
* - `wrapRecoveryRecord` / `unwrapRecoveryRecord` -- the keyring-record
|
|
16
16
|
* sibling carrying the account pointer plus the pre-minted
|
|
17
|
-
* PUT-on-`did.jsonl` delegation (never a seed, never a
|
|
17
|
+
* PUT-on-`did.jsonl` delegation (never a seed, never a user key wrap).
|
|
18
18
|
* - `publishRecoveryKey` / `removeRecoveryKey` / `recoverWebvhClient` -- the
|
|
19
19
|
* document half: issuance's split posture, revocation's removal, and the
|
|
20
20
|
* self-enrolling recovery continuation.
|
package/dist/recovery/index.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* single did:webvh update key whose hash stands pre-committed.
|
|
15
15
|
* - `wrapRecoveryRecord` / `unwrapRecoveryRecord` -- the keyring-record
|
|
16
16
|
* sibling carrying the account pointer plus the pre-minted
|
|
17
|
-
* PUT-on-`did.jsonl` delegation (never a seed, never a
|
|
17
|
+
* PUT-on-`did.jsonl` delegation (never a seed, never a user key wrap).
|
|
18
18
|
* - `publishRecoveryKey` / `removeRecoveryKey` / `recoverWebvhClient` -- the
|
|
19
19
|
* document half: issuance's split posture, revocation's removal, and the
|
|
20
20
|
* self-enrolling recovery continuation.
|
|
@@ -83,7 +83,7 @@ export interface RecoveryClient {
|
|
|
83
83
|
keyAgreementKeyMultibase: string;
|
|
84
84
|
updateKeyMultibase: string;
|
|
85
85
|
/**
|
|
86
|
-
* The kid of the code's
|
|
86
|
+
* The kid of the code's user-key-roster entry -- its key-agreement key's id
|
|
87
87
|
* exactly as `agentsFromSeed` derives it (`did:key:<ed>#<x>`), so the wrap
|
|
88
88
|
* minted at issuance is the one the recovery flow's roster read looks for.
|
|
89
89
|
*/
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* The recovery-code format layer and its deterministic derivations. A recovery
|
|
6
6
|
* code is 16 random bytes rendered as base58 (Bitcoin alphabet), shown to the
|
|
7
7
|
* user exactly once at issuance. Under the roster identity model the code is a
|
|
8
|
-
* **minimal always-enrolled wallet client**: everything the code needs to
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* **minimal always-enrolled wallet client**: everything the code needs to act
|
|
9
|
+
* -- the unlock identity that locates its keyring record, the client key set
|
|
10
|
+
* behind its `keyAgreement` verification method and user-key-roster wrap, and
|
|
11
|
+
* the did:webvh update key whose hash stands pre-committed in `nextKeyHashes`
|
|
12
|
+
* -- derives deterministically from the code's bytes, so the key material
|
|
13
|
+
* exists nowhere until the code is typed.
|
|
14
14
|
*
|
|
15
15
|
* The derivations are wire-level: two wallet apps must produce byte-identical
|
|
16
16
|
* output for the same code, or a code issued in one could not recover in the
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* is the ordinary keyring record's (controller, email, account pointer) PLUS
|
|
8
8
|
* the pre-minted PUT-on-`did.jsonl` delegation -- the narrow zcap bridge that
|
|
9
9
|
* lets the code-derived client write its self-enrolling log continuation. It
|
|
10
|
-
* carries **no key material of any kind**: never a seed, never a
|
|
10
|
+
* carries **no key material of any kind**: never a seed, never a user key wrap
|
|
11
11
|
* (wraps live doc-and-roster only), so the record stays a pure pointer.
|
|
12
12
|
*
|
|
13
13
|
* The wrap reuses the keyring cipher context verbatim, so a recovery record
|
|
@@ -64,7 +64,7 @@ export declare function publishRecoveryKey({ idStore, updateKeys, recovery }: {
|
|
|
64
64
|
* REVOCATION (run by an enrolled client, root authority): removes a recovery
|
|
65
65
|
* code's posture from the document -- its `keyAgreement` verification method
|
|
66
66
|
* and its committed update-key hash -- in one entry. Idempotent. The
|
|
67
|
-
* roster-side half (rotating the
|
|
67
|
+
* roster-side half (rotating the user key epoch off the code's wrap) is the
|
|
68
68
|
* caller's, and runs after this so the resolver's document no longer backs
|
|
69
69
|
* the removed entry.
|
|
70
70
|
*
|
|
@@ -165,7 +165,7 @@ export async function publishRecoveryKey({ idStore, updateKeys, recovery }) {
|
|
|
165
165
|
* REVOCATION (run by an enrolled client, root authority): removes a recovery
|
|
166
166
|
* code's posture from the document -- its `keyAgreement` verification method
|
|
167
167
|
* and its committed update-key hash -- in one entry. Idempotent. The
|
|
168
|
-
* roster-side half (rotating the
|
|
168
|
+
* roster-side half (rotating the user key epoch off the code's wrap) is the
|
|
169
169
|
* caller's, and runs after this so the resolver's document no longer backs
|
|
170
170
|
* the removed entry.
|
|
171
171
|
*
|
|
@@ -14,6 +14,17 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { CHAPIStoreEvent, ICapabilityQueryDetail, ICredentialQuery, IQueryByExample, IVPOffer, IVPRequest, IVPRDetails, IVPRQuery, IVerifiableCredential, IVerifiablePresentation, WalletRequestProfile } from './types.js';
|
|
16
16
|
import type { CHAPIGetEvent } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* The VC data model version a presentation carrying the given credentials must
|
|
19
|
+
* use, so its `@context` stays coherent with what it carries: `2.0` when any
|
|
20
|
+
* credential is a VC 2.0 one, else `1.0`. Shared by the bare-credential
|
|
21
|
+
* wrapping below and by the unsigned branch of `composeVp` (the signed branch
|
|
22
|
+
* takes its version from the negotiated cryptosuite instead).
|
|
23
|
+
*
|
|
24
|
+
* @param credentials {IVerifiableCredential[]}
|
|
25
|
+
* @returns {number}
|
|
26
|
+
*/
|
|
27
|
+
export declare function presentationVersionFor(credentials: IVerifiableCredential[]): number;
|
|
17
28
|
/**
|
|
18
29
|
* The Verifiable Credentials carried by a presentation, normalized to an array.
|
|
19
30
|
*
|
|
@@ -103,7 +114,10 @@ export declare function isDidAuthOnly(profile: WalletRequestProfile): boolean;
|
|
|
103
114
|
/**
|
|
104
115
|
* Returns true if the wallet can satisfy the DID method a `DIDAuthentication`
|
|
105
116
|
* query constrains to. A wallet holding only `did:key` can satisfy a request
|
|
106
|
-
* that lists `key` among `acceptedMethods` or omits the constraint entirely.
|
|
117
|
+
* that lists `key` among `acceptedMethods` or omits the constraint entirely. A
|
|
118
|
+
* malformed `acceptedMethods` (not an array, or holding non-object entries) is
|
|
119
|
+
* read for the entries it does have rather than dereferenced blindly: an
|
|
120
|
+
* `acceptedMethods` that is not a list of constraints at all imposes none.
|
|
107
121
|
*
|
|
108
122
|
* @param queries {IVPRQuery[]}
|
|
109
123
|
* @returns {boolean}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAEhB,eAAe,EACf,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,uBAAuB,EAEvB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAEhB,eAAe,EACf,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,uBAAuB,EAEvB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO/C;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,qBAAqB,EAAE,GACnC,MAAM,CAOR;AA0DD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,uBAAuB,GACpC,qBAAqB,EAAE,CAQzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAYtE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,QAAQ,CAKxE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB,GAAG,OAAO,CAQV;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,CAS3D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,GACrB,gBAAgB,EAAE,CAMpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,sBAAsB,EAAE,CAoB5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,oBAAoB,CAS1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAMpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAQpE"}
|