@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.
Files changed (175) hide show
  1. package/README.md +13 -13
  2. package/dist/clients/index.d.ts +4 -3
  3. package/dist/clients/index.d.ts.map +1 -1
  4. package/dist/clients/index.js +3 -2
  5. package/dist/clients/index.js.map +1 -1
  6. package/dist/clients/policy.d.ts +3 -3
  7. package/dist/clients/policy.d.ts.map +1 -1
  8. package/dist/clients/policy.js +1 -1
  9. package/dist/clients/revocation.d.ts +18 -15
  10. package/dist/clients/revocation.d.ts.map +1 -1
  11. package/dist/clients/revocation.js +42 -26
  12. package/dist/clients/revocation.js.map +1 -1
  13. package/dist/clients/rosterPolicy.d.ts +46 -24
  14. package/dist/clients/rosterPolicy.d.ts.map +1 -1
  15. package/dist/clients/rosterPolicy.js +106 -48
  16. package/dist/clients/rosterPolicy.js.map +1 -1
  17. package/dist/descriptors/refresh.d.ts +3 -1
  18. package/dist/descriptors/refresh.d.ts.map +1 -1
  19. package/dist/descriptors/refresh.js +3 -1
  20. package/dist/descriptors/refresh.js.map +1 -1
  21. package/dist/display/alignment.d.ts +8 -2
  22. package/dist/display/alignment.d.ts.map +1 -1
  23. package/dist/display/alignment.js +11 -8
  24. package/dist/display/alignment.js.map +1 -1
  25. package/dist/display/displayFields.d.ts +6 -2
  26. package/dist/display/displayFields.d.ts.map +1 -1
  27. package/dist/display/displayFields.js.map +1 -1
  28. package/dist/display/evidence.d.ts +9 -3
  29. package/dist/display/evidence.d.ts.map +1 -1
  30. package/dist/display/evidence.js +3 -1
  31. package/dist/display/evidence.js.map +1 -1
  32. package/dist/display/index.d.ts +1 -1
  33. package/dist/display/index.d.ts.map +1 -1
  34. package/dist/display/index.js +1 -1
  35. package/dist/display/index.js.map +1 -1
  36. package/dist/display/issuer.d.ts +12 -4
  37. package/dist/display/issuer.d.ts.map +1 -1
  38. package/dist/display/issuer.js.map +1 -1
  39. package/dist/display/obv3.d.ts +7 -2
  40. package/dist/display/obv3.d.ts.map +1 -1
  41. package/dist/display/obv3.js +14 -24
  42. package/dist/display/obv3.js.map +1 -1
  43. package/dist/display/parse.d.ts +6 -2
  44. package/dist/display/parse.d.ts.map +1 -1
  45. package/dist/display/parse.js +6 -2
  46. package/dist/display/parse.js.map +1 -1
  47. package/dist/display/subject.d.ts +4 -0
  48. package/dist/display/subject.d.ts.map +1 -1
  49. package/dist/display/subject.js +12 -10
  50. package/dist/display/subject.js.map +1 -1
  51. package/dist/display/text.d.ts +11 -0
  52. package/dist/display/text.d.ts.map +1 -1
  53. package/dist/display/text.js +20 -4
  54. package/dist/display/text.js.map +1 -1
  55. package/dist/display/types.js +1 -1
  56. package/dist/display/types.js.map +1 -1
  57. package/dist/display/validity.js +4 -4
  58. package/dist/display/validity.js.map +1 -1
  59. package/dist/display/verificationView.d.ts +21 -7
  60. package/dist/display/verificationView.d.ts.map +1 -1
  61. package/dist/display/verificationView.js.map +1 -1
  62. package/dist/enrollment/enrollment.d.ts +21 -19
  63. package/dist/enrollment/enrollment.d.ts.map +1 -1
  64. package/dist/enrollment/enrollment.js +98 -34
  65. package/dist/enrollment/enrollment.js.map +1 -1
  66. package/dist/enrollment/index.d.ts +1 -1
  67. package/dist/enrollment/index.js +1 -1
  68. package/dist/index.d.ts +2 -2
  69. package/dist/index.js +2 -2
  70. package/dist/keys/clientKeyRecord.d.ts +19 -17
  71. package/dist/keys/clientKeyRecord.d.ts.map +1 -1
  72. package/dist/keys/clientKeyRecord.js +77 -41
  73. package/dist/keys/clientKeyRecord.js.map +1 -1
  74. package/dist/keys/index.d.ts +19 -17
  75. package/dist/keys/index.d.ts.map +1 -1
  76. package/dist/keys/index.js +16 -14
  77. package/dist/keys/index.js.map +1 -1
  78. package/dist/keys/rosterStore.d.ts +3 -3
  79. package/dist/keys/rosterStore.d.ts.map +1 -1
  80. package/dist/keys/rosterStore.js +13 -13
  81. package/dist/keys/rosterStore.js.map +1 -1
  82. package/dist/keys/userKey.d.ts +43 -0
  83. package/dist/keys/userKey.d.ts.map +1 -0
  84. package/dist/keys/{puk.js → userKey.js} +23 -21
  85. package/dist/keys/userKey.js.map +1 -0
  86. package/dist/keys/{pukCascade.d.ts → userKeyCascade.d.ts} +69 -69
  87. package/dist/keys/userKeyCascade.d.ts.map +1 -0
  88. package/dist/keys/{pukCascade.js → userKeyCascade.js} +77 -75
  89. package/dist/keys/userKeyCascade.js.map +1 -0
  90. package/dist/keys/{pukRoster.d.ts → userKeyRoster.d.ts} +141 -64
  91. package/dist/keys/userKeyRoster.d.ts.map +1 -0
  92. package/dist/keys/{pukRoster.js → userKeyRoster.js} +200 -72
  93. package/dist/keys/userKeyRoster.js.map +1 -0
  94. package/dist/recovery/index.d.ts +1 -1
  95. package/dist/recovery/index.js +1 -1
  96. package/dist/recovery/recoveryCode.d.ts +1 -1
  97. package/dist/recovery/recoveryCode.js +6 -6
  98. package/dist/recovery/recoveryRecord.d.ts +1 -1
  99. package/dist/recovery/recoveryWebvh.d.ts +1 -1
  100. package/dist/recovery/recoveryWebvh.js +1 -1
  101. package/dist/request/classify.d.ts +15 -1
  102. package/dist/request/classify.d.ts.map +1 -1
  103. package/dist/request/classify.js +38 -14
  104. package/dist/request/classify.js.map +1 -1
  105. package/dist/request/composeVp.d.ts.map +1 -1
  106. package/dist/request/composeVp.js +10 -3
  107. package/dist/request/composeVp.js.map +1 -1
  108. package/dist/request/matching.d.ts +6 -0
  109. package/dist/request/matching.d.ts.map +1 -1
  110. package/dist/request/matching.js +33 -8
  111. package/dist/request/matching.js.map +1 -1
  112. package/dist/request/parse.d.ts +5 -2
  113. package/dist/request/parse.d.ts.map +1 -1
  114. package/dist/request/parse.js +30 -5
  115. package/dist/request/parse.js.map +1 -1
  116. package/dist/request/presentationSuite.d.ts.map +1 -1
  117. package/dist/request/presentationSuite.js +6 -2
  118. package/dist/request/presentationSuite.js.map +1 -1
  119. package/dist/request/processRequest.js +1 -1
  120. package/dist/request/processRequest.js.map +1 -1
  121. package/dist/space/activity.d.ts +22 -8
  122. package/dist/space/activity.d.ts.map +1 -1
  123. package/dist/space/activity.js +19 -7
  124. package/dist/space/activity.js.map +1 -1
  125. package/dist/space/collections.d.ts +33 -21
  126. package/dist/space/collections.d.ts.map +1 -1
  127. package/dist/space/collections.js +34 -22
  128. package/dist/space/collections.js.map +1 -1
  129. package/dist/space/index.d.ts +2 -2
  130. package/dist/space/index.d.ts.map +1 -1
  131. package/dist/space/index.js +2 -2
  132. package/dist/space/index.js.map +1 -1
  133. package/dist/space/wasLink.d.ts +6 -2
  134. package/dist/space/wasLink.d.ts.map +1 -1
  135. package/dist/space/wasLink.js +5 -2
  136. package/dist/space/wasLink.js.map +1 -1
  137. package/dist/sync/contactsConflict.d.ts +1 -1
  138. package/dist/sync/contactsConflict.js +1 -1
  139. package/dist/sync/engine.d.ts +33 -11
  140. package/dist/sync/engine.d.ts.map +1 -1
  141. package/dist/sync/engine.js +4 -3
  142. package/dist/sync/engine.js.map +1 -1
  143. package/dist/sync/pull.d.ts +5 -3
  144. package/dist/sync/pull.d.ts.map +1 -1
  145. package/dist/sync/pull.js +34 -10
  146. package/dist/sync/pull.js.map +1 -1
  147. package/dist/sync/push.d.ts.map +1 -1
  148. package/dist/sync/push.js +24 -8
  149. package/dist/sync/push.js.map +1 -1
  150. package/dist/sync/types.d.ts +30 -6
  151. package/dist/sync/types.d.ts.map +1 -1
  152. package/dist/webvh/didWebvh.d.ts +29 -1
  153. package/dist/webvh/didWebvh.d.ts.map +1 -1
  154. package/dist/webvh/didWebvh.js +46 -11
  155. package/dist/webvh/didWebvh.js.map +1 -1
  156. package/dist/webvh/index.d.ts +1 -1
  157. package/dist/webvh/index.d.ts.map +1 -1
  158. package/dist/webvh/index.js +1 -1
  159. package/dist/webvh/index.js.map +1 -1
  160. package/dist/webvh/listClients.d.ts +19 -0
  161. package/dist/webvh/listClients.d.ts.map +1 -1
  162. package/dist/webvh/listClients.js +37 -1
  163. package/dist/webvh/listClients.js.map +1 -1
  164. package/dist/webvh/revokeClient.d.ts +11 -3
  165. package/dist/webvh/revokeClient.d.ts.map +1 -1
  166. package/dist/webvh/revokeClient.js +83 -14
  167. package/dist/webvh/revokeClient.js.map +1 -1
  168. package/package.json +3 -3
  169. package/dist/keys/puk.d.ts +0 -42
  170. package/dist/keys/puk.d.ts.map +0 -1
  171. package/dist/keys/puk.js.map +0 -1
  172. package/dist/keys/pukCascade.d.ts.map +0 -1
  173. package/dist/keys/pukCascade.js.map +0 -1
  174. package/dist/keys/pukRoster.d.ts.map +0 -1
  175. 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 PukRosterIntegrityError extends Error {
11
+ export class UserKeyRosterIntegrityError extends Error {
9
12
  constructor(message) {
10
13
  super(message);
11
- this.name = 'PukRosterIntegrityError';
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 PukRosterContinuityError extends Error {
24
+ export class UserKeyRosterContinuityError extends Error {
22
25
  pinnedEpochId;
23
26
  constructor({ pinnedEpochId }) {
24
- super('The PUK roster no longer carries the epoch this client has pinned -- ' +
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 = 'PukRosterContinuityError';
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 PUK -- it may have been
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 PukRosterUnwrapError extends Error {
39
+ export class UserKeyRosterUnwrapError extends Error {
37
40
  constructor(message) {
38
41
  super(message);
39
- this.name = 'PukRosterUnwrapError';
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 pukRosterRecipientResolver({ document }) {
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
- * initialized with the account's existing PUK installed as the first epoch,
121
- * wrapped to this client's key-agreement key; an existing roster is returned
122
- * as-is (authentication is the read path's job, and provisioning must never
123
- * clobber an established roster). Idempotent -- losing the guarded-create
124
- * race to a concurrent first init converges on the winner's roster.
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.puk {Puk} the account's per-user key
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 ensurePukRoster({ store, puk, clientKeyAgreementKey }) {
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: puk.id, secret: puk.secret }
228
+ epoch: { epochId: userKey.id, secret: userKey.secret },
229
+ signEpochs
143
230
  });
144
231
  }
145
232
  /**
146
- * Wraps the PUK to a client being enrolled -- the roster half of 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 addPukRosterRecipient({ store, recipient, ownerKeyAgreementKey }) {
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 PUK roster does not exist yet; the account must finish ' +
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 PUK roster off one recipient -- the roster half of revoking an
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
- * verified did:webvh document ("the roster delivers, never sources" -- an
198
- * entry with no matching `keyAgreement` verification method is dropped and
199
- * never receives a wrap), and the pull axis is a no-op, because for a roster
200
- * recipient the pull axis IS the document edit the caller performed first --
201
- * under the current-key-set rule the removed party's server-side access died
202
- * the moment its verification method left the document.
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 rotatePukRoster({ store, document, retireRecipientId }) {
303
+ export async function rotateUserKeyRoster({ store, document, retireRecipientId, signEpochs }) {
214
304
  return removeRecipient({
215
305
  store,
216
306
  recipientId: retireRecipientId,
217
- resolveRecipientKey: pukRosterRecipientResolver({ document }),
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 per-user key to a
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 rotatePukRoster} suffices,
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 per-user key itself is not returned: the caller adopts it the
243
- * ordinary way, by re-reading the roster ({@link readPukRoster}) once
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 convergePukRosterToDocument({ store, document, descriptor }) {
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 PukRosterIntegrityError('The PUK roster names no current epoch in its own epoch list.');
365
+ throw new UserKeyRosterIntegrityError('The user key roster names no current epoch in its own epoch list.');
272
366
  }
273
- const resolveRecipientKey = pukRosterRecipientResolver({ document });
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 PukRosterIntegrityError('No PUK roster recipient is keyed by the account document; refusing ' +
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 rotatePukRoster({
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
- * (`PukRosterContinuityError` -- the rollback/replay refusal).
309
- * 2. **Possession**: `currentEpoch === puk.id` confirms the cached PUK
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
- * (`PukRosterUnwrapError` when it holds none).
313
- * 3. **Authentication**: the descriptor's `epochsMac` is verified under the
314
- * current epoch's secret (`PukRosterIntegrityError` on any mismatch -- a
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 PUK; its Ed25519 signing seed does not
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 PUK carries none.
422
+ * alone), so the returned user key carries none.
320
423
  *
321
- * A caller with no cached PUK at all -- a freshly enrolled client making its
322
- * first post-enrollment read -- omits `puk` and always takes the unwrap path;
323
- * the result's `rotated` is then true (the PUK was adopted from the roster).
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.puk] {Puk} this client's cached PUK, when it holds one
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
- * @returns {Promise<PukRosterReadResult | null>}
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 readPukRoster({ store, puk, clientKeyAgreementKey, pinnedEpochId }) {
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 PukRosterIntegrityError('The PUK roster names no current epoch in its own epoch list.');
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 PukRosterContinuityError({ pinnedEpochId });
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 PukRosterIntegrityError('The PUK roster carries no supported epoch-configuration MAC.');
469
+ throw new UserKeyRosterIntegrityError('The user key roster carries no supported epoch-configuration MAC.');
358
470
  }
359
- let currentPuk;
471
+ let currentUserKey;
360
472
  let rotated;
361
- if (puk && descriptor.currentEpoch === puk.id) {
362
- currentPuk = puk;
473
+ if (userKey && descriptor.currentEpoch === userKey.id) {
474
+ currentUserKey = userKey;
363
475
  rotated = false;
364
476
  }
365
477
  else {
366
- // Rotated by another client: unwrap this client's entry in the current
367
- // epoch with its own key-agreement key (rotation delivery).
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 PukRosterUnwrapError('The PUK roster current epoch carries no wrap for this client.');
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 PukRosterUnwrapError("This client's PUK roster entry failed to unwrap.");
505
+ throw new UserKeyRosterUnwrapError("This client's user key roster entry failed to unwrap.");
378
506
  }
379
- currentPuk = { id: descriptor.currentEpoch, secret };
507
+ currentUserKey = { id: descriptor.currentEpoch, secret };
380
508
  rotated = true;
381
509
  }
382
- if (!(await verifyEpochsMac({ descriptor, epochSecret: currentPuk.secret }))) {
383
- throw new PukRosterIntegrityError('The PUK roster epoch configuration failed authentication.');
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
- puk: currentPuk,
515
+ userKey: currentUserKey,
388
516
  rotated,
389
517
  latestEpochId: descriptor.currentEpoch
390
518
  };
391
519
  }
392
- //# sourceMappingURL=pukRoster.js.map
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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"}
@@ -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 PUK wrap).
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.
@@ -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 PUK wrap).
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 PUK-roster entry -- its key-agreement key's id
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
- * act -- the unlock identity that locates its keyring record, the client
10
- * key set behind its `keyAgreement` verification method and PUK-roster wrap,
11
- * and the did:webvh update key whose hash stands pre-committed in
12
- * `nextKeyHashes` -- derives deterministically from the code's bytes, so the
13
- * key material exists nowhere until the code is typed.
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 PUK wrap
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 PUK epoch off the code's wrap) is 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 PUK epoch off the code's wrap) is 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;AA4D/C;;;;;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,CAMV;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;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAQpE"}
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"}