@interop/wallet-core 0.14.0 → 0.16.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 (73) hide show
  1. package/README.md +13 -4
  2. package/dist/clients/index.d.ts +32 -0
  3. package/dist/clients/index.d.ts.map +1 -0
  4. package/dist/clients/index.js +28 -0
  5. package/dist/clients/index.js.map +1 -0
  6. package/dist/clients/listing.d.ts +103 -0
  7. package/dist/clients/listing.d.ts.map +1 -0
  8. package/dist/clients/listing.js +86 -0
  9. package/dist/clients/listing.js.map +1 -0
  10. package/dist/clients/policy.d.ts +79 -0
  11. package/dist/clients/policy.d.ts.map +1 -0
  12. package/dist/clients/policy.js +55 -0
  13. package/dist/clients/policy.js.map +1 -0
  14. package/dist/clients/revocation.d.ts +156 -0
  15. package/dist/clients/revocation.d.ts.map +1 -0
  16. package/dist/clients/revocation.js +142 -0
  17. package/dist/clients/revocation.js.map +1 -0
  18. package/dist/clients/rosterPolicy.d.ts +124 -0
  19. package/dist/clients/rosterPolicy.d.ts.map +1 -0
  20. package/dist/clients/rosterPolicy.js +125 -0
  21. package/dist/clients/rosterPolicy.js.map +1 -0
  22. package/dist/enrollment/connectCode.d.ts +29 -0
  23. package/dist/enrollment/connectCode.d.ts.map +1 -0
  24. package/dist/enrollment/connectCode.js +31 -0
  25. package/dist/enrollment/connectCode.js.map +1 -0
  26. package/dist/enrollment/enrollment.d.ts.map +1 -1
  27. package/dist/enrollment/enrollment.js +1 -5
  28. package/dist/enrollment/enrollment.js.map +1 -1
  29. package/dist/enrollment/index.d.ts +3 -0
  30. package/dist/enrollment/index.d.ts.map +1 -1
  31. package/dist/enrollment/index.js +3 -0
  32. package/dist/enrollment/index.js.map +1 -1
  33. package/dist/keys/clientKeyRecord.d.ts +124 -0
  34. package/dist/keys/clientKeyRecord.d.ts.map +1 -0
  35. package/dist/keys/clientKeyRecord.js +265 -0
  36. package/dist/keys/clientKeyRecord.js.map +1 -0
  37. package/dist/keys/index.d.ts +5 -0
  38. package/dist/keys/index.d.ts.map +1 -1
  39. package/dist/keys/index.js +4 -0
  40. package/dist/keys/index.js.map +1 -1
  41. package/dist/request/index.d.ts +4 -0
  42. package/dist/request/index.d.ts.map +1 -1
  43. package/dist/request/index.js +4 -0
  44. package/dist/request/index.js.map +1 -1
  45. package/dist/request/walletInput.d.ts +93 -0
  46. package/dist/request/walletInput.d.ts.map +1 -0
  47. package/dist/request/walletInput.js +182 -0
  48. package/dist/request/walletInput.js.map +1 -0
  49. package/dist/sync/contactsConflict.d.ts +76 -0
  50. package/dist/sync/contactsConflict.d.ts.map +1 -0
  51. package/dist/sync/contactsConflict.js +95 -0
  52. package/dist/sync/contactsConflict.js.map +1 -0
  53. package/dist/sync/index.d.ts +5 -0
  54. package/dist/sync/index.d.ts.map +1 -1
  55. package/dist/sync/index.js +4 -0
  56. package/dist/sync/index.js.map +1 -1
  57. package/dist/webvh/didWebvh.d.ts +6 -0
  58. package/dist/webvh/didWebvh.d.ts.map +1 -1
  59. package/dist/webvh/didWebvh.js +16 -0
  60. package/dist/webvh/didWebvh.js.map +1 -1
  61. package/dist/webvh/index.d.ts +5 -2
  62. package/dist/webvh/index.d.ts.map +1 -1
  63. package/dist/webvh/index.js +4 -1
  64. package/dist/webvh/index.js.map +1 -1
  65. package/dist/webvh/listClients.d.ts +58 -0
  66. package/dist/webvh/listClients.d.ts.map +1 -1
  67. package/dist/webvh/listClients.js +54 -0
  68. package/dist/webvh/listClients.js.map +1 -1
  69. package/dist/webvh/revokeClient.d.ts +6 -0
  70. package/dist/webvh/revokeClient.d.ts.map +1 -1
  71. package/dist/webvh/revokeClient.js +6 -0
  72. package/dist/webvh/revokeClient.js.map +1 -1
  73. package/package.json +15 -2
package/README.md CHANGED
@@ -80,7 +80,16 @@ The subpaths:
80
80
  state alone, history escrowed -- also the completion sweep's building block),
81
81
  plus the detector that converges a roster left wrapping the current key to a
82
82
  recipient the account document no longer keys. Also the enrolled-client
83
- display labels (`key-map/client-labels.json`) and their WAS-backed store.
83
+ display labels (`key-map/client-labels.json`) and their WAS-backed store. Also
84
+ the client-key record codec: the contents and strict validation of the local
85
+ record each wallet client keeps its own key material in (storage and wrapping
86
+ stay app-side).
87
+
88
+ - **`@interop/wallet-core/clients`** -- the enrolled-client management surface:
89
+ the listing over the locally verified did:webvh log with display labels
90
+ merged, the disconnect-eligibility policy as pure functions, the revocation
91
+ cascade orchestrator (document edit, roster rotation, collection fan-out,
92
+ optional recovery re-mints), and the login-time roster policy.
84
93
 
85
94
  - **`@interop/wallet-core/descriptors`** -- collection encryption-descriptor
86
95
  acquisition (fetch / cache / offline fallback) and the unknown-epoch refresh
@@ -129,9 +138,9 @@ import {
129
138
 
130
139
  The `sync` and `space` subpaths are re-exported from the package root as well.
131
140
  Every other subpath (`identity`, `request`, `display`, `webvh`, `keys`,
132
- `descriptors`, `keyring`, `enrollment`, `recovery`) is import-directly-only, so
133
- consumers of the root never pull the signing / KMS / document-loader dependency
134
- graph.
141
+ `clients`, `descriptors`, `keyring`, `enrollment`, `recovery`) is
142
+ import-directly-only, so consumers of the root never pull the signing / KMS /
143
+ document-loader dependency graph.
135
144
 
136
145
  ## Contribute
137
146
 
@@ -0,0 +1,32 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/clients` subpath: the enrolled-client management
6
+ * surface -- the place "disconnect this wallet" lives -- and the cascades
7
+ * behind it.
8
+ *
9
+ * - `listAccountClients` / `currentAccountSigningKeys` -- the listing over the
10
+ * locally verified did:webvh log, with display labels merged, and the same
11
+ * read reduced to the key set an app grant's delegation signer is checked
12
+ * against. Both take an already-verified log in place of fetching one.
13
+ * - `disconnectEligibility` / `revokedClientKeysFor` / `cascadeCompletion` --
14
+ * the disconnect-eligibility policy as data and pure functions, so both
15
+ * surfaces refuse the same rows for the same reasons and report a partial
16
+ * fan-out as the resumable success it is.
17
+ * - `revokeAccountClient` -- the revocation cascade in dependency order
18
+ * (document edit, roster rotation, collection fan-out, optional recovery
19
+ * re-mints), with the app-specific stages injected.
20
+ * - `checkPukRosterAtLogin` / `convergePukRosterToAccount` -- the login-time
21
+ * roster policy: which roster failures refuse a session, and the standing
22
+ * convergence of the roster onto the account document.
23
+ */
24
+ export { currentAccountSigningKeys, listAccountClients } from './listing.js';
25
+ export type { AccountClientView, AccountLogPointer, VerifiedAccountLog } from './listing.js';
26
+ export { cascadeCompletion, disconnectEligibility, revokedClientKeysFor } from './policy.js';
27
+ export type { DisconnectRefusal } from './policy.js';
28
+ export { revokeAccountClient } from './revocation.js';
29
+ export type { CascadeCollections, ClientRevocationResult } from './revocation.js';
30
+ export { checkPukRosterAtLogin, convergePukRosterToAccount } from './rosterPolicy.js';
31
+ export type { AdoptedPuk } from './rosterPolicy.js';
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clients/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC5E,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,28 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The `@interop/wallet-core/clients` subpath: the enrolled-client management
6
+ * surface -- the place "disconnect this wallet" lives -- and the cascades
7
+ * behind it.
8
+ *
9
+ * - `listAccountClients` / `currentAccountSigningKeys` -- the listing over the
10
+ * locally verified did:webvh log, with display labels merged, and the same
11
+ * read reduced to the key set an app grant's delegation signer is checked
12
+ * against. Both take an already-verified log in place of fetching one.
13
+ * - `disconnectEligibility` / `revokedClientKeysFor` / `cascadeCompletion` --
14
+ * the disconnect-eligibility policy as data and pure functions, so both
15
+ * surfaces refuse the same rows for the same reasons and report a partial
16
+ * fan-out as the resumable success it is.
17
+ * - `revokeAccountClient` -- the revocation cascade in dependency order
18
+ * (document edit, roster rotation, collection fan-out, optional recovery
19
+ * re-mints), with the app-specific stages injected.
20
+ * - `checkPukRosterAtLogin` / `convergePukRosterToAccount` -- the login-time
21
+ * roster policy: which roster failures refuse a session, and the standing
22
+ * convergence of the roster onto the account document.
23
+ */
24
+ export { currentAccountSigningKeys, listAccountClients } from './listing.js';
25
+ export { cascadeCompletion, disconnectEligibility, revokedClientKeysFor } from './policy.js';
26
+ export { revokeAccountClient } from './revocation.js';
27
+ export { checkPukRosterAtLogin, convergePukRosterToAccount } from './rosterPolicy.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/clients/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAO5E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAMrD,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,103 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The enrolled-client listing behind a "wallets connected to this account"
6
+ * surface: fetch and locally verify the account's world-readable did:webvh log
7
+ * (the same verification step every ceremony runs), enumerate the clients it
8
+ * enrolls, merge their display labels, and mark the row belonging to the
9
+ * caller's own client.
10
+ *
11
+ * The listing IS the revocation surface, so the enumeration rule matters as
12
+ * much as the display: `listEnrolledWebvhClients` keys on
13
+ * `capabilityInvocation`, which is what structurally excludes a recovery
14
+ * code's key (published under `keyAgreement` only, deliberately unmarked) and
15
+ * the server-side conveniences (published under `authentication` /
16
+ * `assertionMethod`) -- neither can appear, by construction rather than by a
17
+ * filter someone must remember.
18
+ *
19
+ * Labels are display metadata with no authority, so a label-read failure
20
+ * degrades to unlabeled rows; the listing itself fails only when the log
21
+ * cannot be fetched or verified.
22
+ *
23
+ * The two reads are independent, so they run together, and either entry point
24
+ * takes an already-verified log (`verifiedLog`) in place of fetching one --
25
+ * the seam a caller needs to keep one verified log for a session instead of
26
+ * re-verifying `did.jsonl` per surface. Whether such a cache is safe to hold,
27
+ * and what invalidates it, is the caller's call.
28
+ */
29
+ import { verifyAccountLog, type EnrolledWebvhClient } from '../webvh/index.js';
30
+ import { type ClientLabelsStore } from '../keys/index.js';
31
+ /**
32
+ * Where an account's did:webvh log is published: the account DID plus the
33
+ * Space and host its `id` collection is served from.
34
+ */
35
+ export interface AccountLogPointer {
36
+ did: string;
37
+ spaceId: string;
38
+ host: string;
39
+ }
40
+ /**
41
+ * A log that has already been fetched and locally verified -- exactly what
42
+ * `verifyAccountLog` resolves to. Both entry points below accept one so a
43
+ * caller holding a still-valid result (a session-lifetime cache, or two
44
+ * surfaces mounting together) reads the account's clients without re-fetching
45
+ * and re-verifying `did.jsonl`. The cache itself is the caller's: only the
46
+ * caller knows which ceremonies invalidate it.
47
+ */
48
+ export type VerifiedAccountLog = Awaited<ReturnType<typeof verifyAccountLog>>;
49
+ /**
50
+ * One row of the listing: the log-stated client plus its display state.
51
+ * `updateKeyMultibase` is absent when the log attribution could not isolate
52
+ * the client's active update key, which is exactly when it cannot be
53
+ * disconnected.
54
+ */
55
+ export interface AccountClientView extends EnrolledWebvhClient {
56
+ label?: string;
57
+ isCurrent: boolean;
58
+ }
59
+ /**
60
+ * Lists the wallet clients enrolled on an account, from the locally verified
61
+ * did:webvh log, with labels merged and the caller's own client marked.
62
+ *
63
+ * @param options {object}
64
+ * @param options.pointer {AccountLogPointer} where the account log lives
65
+ * @param [options.labelsStore] {ClientLabelsStore} the
66
+ * `key-map/client-labels.json` store; omitted, every row is unlabeled
67
+ * @param [options.ownSigningKeyMultibase] {string} this client's own signing
68
+ * key, which marks its row `isCurrent`
69
+ * @param [options.verifiedLog] {VerifiedAccountLog} an already-verified log
70
+ * to read instead of fetching and verifying one
71
+ * @returns {Promise<AccountClientView[]>}
72
+ */
73
+ export declare function listAccountClients({ pointer, labelsStore, ownSigningKeyMultibase, verifiedLog }: {
74
+ pointer: AccountLogPointer;
75
+ labelsStore?: ClientLabelsStore;
76
+ ownSigningKeyMultibase?: string;
77
+ verifiedLog?: VerifiedAccountLog;
78
+ }): Promise<AccountClientView[]>;
79
+ /**
80
+ * The signing-key multibases of the account's currently enrolled wallet
81
+ * clients, from the locally verified did:webvh log -- the key set a recorded
82
+ * app grant's delegation proof must name to still verify under the
83
+ * current-key-set rule (a grant signed by a since-disconnected client no
84
+ * longer verifies).
85
+ *
86
+ * This is the connected-applications surface's half of the same read: the
87
+ * gating on whether a session HAS a promoted account to check against stays
88
+ * app-side, since only the app knows what a guest or a storage-less session
89
+ * looks like. Throws when the log cannot be fetched or verified; a caller
90
+ * treating the check as best-effort catches and degrades to "unknown" rather
91
+ * than failing its page.
92
+ *
93
+ * @param options {object}
94
+ * @param options.pointer {AccountLogPointer}
95
+ * @param [options.verifiedLog] {VerifiedAccountLog} an already-verified log
96
+ * to read instead of fetching and verifying one
97
+ * @returns {Promise<Set<string>>}
98
+ */
99
+ export declare function currentAccountSigningKeys({ pointer, verifiedLog }: {
100
+ pointer: AccountLogPointer;
101
+ verifiedLog?: VerifiedAccountLog;
102
+ }): Promise<Set<string>>;
103
+ //# sourceMappingURL=listing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../../src/clients/listing.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAEL,gBAAgB,EAChB,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAE3E;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAA;AAE7E;;;;;GAKG;AACH,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,WAAW,EACX,sBAAsB,EACtB,WAAW,EACZ,EAAE;IACD,OAAO,EAAE,iBAAiB,CAAA;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,WAAW,CAAC,EAAE,kBAAkB,CAAA;CACjC,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAgB/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,OAAO,EACP,WAAW,EACZ,EAAE;IACD,OAAO,EAAE,iBAAiB,CAAA;IAC1B,WAAW,CAAC,EAAE,kBAAkB,CAAA;CACjC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAKvB"}
@@ -0,0 +1,86 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The enrolled-client listing behind a "wallets connected to this account"
6
+ * surface: fetch and locally verify the account's world-readable did:webvh log
7
+ * (the same verification step every ceremony runs), enumerate the clients it
8
+ * enrolls, merge their display labels, and mark the row belonging to the
9
+ * caller's own client.
10
+ *
11
+ * The listing IS the revocation surface, so the enumeration rule matters as
12
+ * much as the display: `listEnrolledWebvhClients` keys on
13
+ * `capabilityInvocation`, which is what structurally excludes a recovery
14
+ * code's key (published under `keyAgreement` only, deliberately unmarked) and
15
+ * the server-side conveniences (published under `authentication` /
16
+ * `assertionMethod`) -- neither can appear, by construction rather than by a
17
+ * filter someone must remember.
18
+ *
19
+ * Labels are display metadata with no authority, so a label-read failure
20
+ * degrades to unlabeled rows; the listing itself fails only when the log
21
+ * cannot be fetched or verified.
22
+ *
23
+ * The two reads are independent, so they run together, and either entry point
24
+ * takes an already-verified log (`verifiedLog`) in place of fetching one --
25
+ * the seam a caller needs to keep one verified log for a session instead of
26
+ * re-verifying `did.jsonl` per surface. Whether such a cache is safe to hold,
27
+ * and what invalidates it, is the caller's call.
28
+ */
29
+ import { listEnrolledWebvhClients, verifyAccountLog } from '../webvh/index.js';
30
+ import { readClientLabels } from '../keys/index.js';
31
+ /**
32
+ * Lists the wallet clients enrolled on an account, from the locally verified
33
+ * did:webvh log, with labels merged and the caller's own client marked.
34
+ *
35
+ * @param options {object}
36
+ * @param options.pointer {AccountLogPointer} where the account log lives
37
+ * @param [options.labelsStore] {ClientLabelsStore} the
38
+ * `key-map/client-labels.json` store; omitted, every row is unlabeled
39
+ * @param [options.ownSigningKeyMultibase] {string} this client's own signing
40
+ * key, which marks its row `isCurrent`
41
+ * @param [options.verifiedLog] {VerifiedAccountLog} an already-verified log
42
+ * to read instead of fetching and verifying one
43
+ * @returns {Promise<AccountClientView[]>}
44
+ */
45
+ export async function listAccountClients({ pointer, labelsStore, ownSigningKeyMultibase, verifiedLog }) {
46
+ // The log read and the label read are independent, so they run together.
47
+ const [{ log }, labels] = await Promise.all([
48
+ verifiedLog ?? verifyAccountLog(pointer),
49
+ labelsStore
50
+ ? readClientLabels({ store: labelsStore }).then(read => read.labels)
51
+ : Promise.resolve({})
52
+ ]);
53
+ const clients = listEnrolledWebvhClients({ log });
54
+ return clients.map(client => ({
55
+ ...client,
56
+ ...(labels[client.signingKeyMultibase] !== undefined
57
+ ? { label: labels[client.signingKeyMultibase] }
58
+ : {}),
59
+ isCurrent: client.signingKeyMultibase === ownSigningKeyMultibase
60
+ }));
61
+ }
62
+ /**
63
+ * The signing-key multibases of the account's currently enrolled wallet
64
+ * clients, from the locally verified did:webvh log -- the key set a recorded
65
+ * app grant's delegation proof must name to still verify under the
66
+ * current-key-set rule (a grant signed by a since-disconnected client no
67
+ * longer verifies).
68
+ *
69
+ * This is the connected-applications surface's half of the same read: the
70
+ * gating on whether a session HAS a promoted account to check against stays
71
+ * app-side, since only the app knows what a guest or a storage-less session
72
+ * looks like. Throws when the log cannot be fetched or verified; a caller
73
+ * treating the check as best-effort catches and degrades to "unknown" rather
74
+ * than failing its page.
75
+ *
76
+ * @param options {object}
77
+ * @param options.pointer {AccountLogPointer}
78
+ * @param [options.verifiedLog] {VerifiedAccountLog} an already-verified log
79
+ * to read instead of fetching and verifying one
80
+ * @returns {Promise<Set<string>>}
81
+ */
82
+ export async function currentAccountSigningKeys({ pointer, verifiedLog }) {
83
+ const { log } = verifiedLog ?? (await verifyAccountLog(pointer));
84
+ return new Set(listEnrolledWebvhClients({ log }).map(client => client.signingKeyMultibase));
85
+ }
86
+ //# sourceMappingURL=listing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listing.js","sourceRoot":"","sources":["../../src/clients/listing.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAEjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,gBAAgB,EAA0B,MAAM,kBAAkB,CAAA;AAiC3E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,OAAO,EACP,WAAW,EACX,sBAAsB,EACtB,WAAW,EAMZ;IACC,yEAAyE;IACzE,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,WAAW,IAAI,gBAAgB,CAAC,OAAO,CAAC;QACxC,WAAW;YACT,CAAC,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;YACpE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAyB,EAAE,CAAC;KAChD,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,wBAAwB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IACjD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5B,GAAG,MAAM;QACT,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,SAAS;YAClD,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE;YAC/C,CAAC,CAAC,EAAE,CAAC;QACP,SAAS,EAAE,MAAM,CAAC,mBAAmB,KAAK,sBAAsB;KACjE,CAAC,CAAC,CAAA;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,EAC9C,OAAO,EACP,WAAW,EAIZ;IACC,MAAM,EAAE,GAAG,EAAE,GAAG,WAAW,IAAI,CAAC,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;IAChE,OAAO,IAAI,GAAG,CACZ,wBAAwB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAC5E,CAAA;AACH,CAAC"}
@@ -0,0 +1,79 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The disconnect-eligibility policy both "connected wallets" surfaces encode
6
+ * as UI state, as data and pure functions -- so the rule that decides whether
7
+ * a row can be disconnected is one rule, and each app supplies only its own
8
+ * wording.
9
+ *
10
+ * Three refusals, each for a different reason:
11
+ *
12
+ * - **`self`** -- a client cannot disconnect itself. The document edit would
13
+ * also refuse (on the update key), but the surface should name the real rule
14
+ * and point at another connected wallet, or a recovery code.
15
+ * - **`last-client`** -- the account's only enrolled client cannot be
16
+ * disconnected: that would abandon the account's update authority, leaving a
17
+ * log nobody can ever extend. Recovery-code issuance is the answer, not this
18
+ * button.
19
+ * - **`unattributed-update-key`** -- the log attribution could not isolate the
20
+ * row's ACTIVE update key. Disconnecting with a guessed key could revoke a
21
+ * different client's authority, so the row is disabled rather than guessed
22
+ * at.
23
+ *
24
+ * And one non-failure: a cascade whose collection fan-out left failures
25
+ * behind is a **resumable success**. The wallet IS disconnected -- the
26
+ * document edit landed first and is the pull axis everywhere -- and the
27
+ * remaining re-keying is detected from durable state alone, so the next run
28
+ * (or the login-time completion sweep) finishes it. A surface that reported
29
+ * that as an error would contradict its own refreshed listing.
30
+ */
31
+ import type { RevokedClientKeys } from '../webvh/index.js';
32
+ import type { PukCascadeResult } from '../keys/index.js';
33
+ import type { AccountClientView } from './listing.js';
34
+ /**
35
+ * Why a listed row cannot be disconnected. See the module doc.
36
+ */
37
+ export type DisconnectRefusal = 'self' | 'last-client' | 'unattributed-update-key';
38
+ /**
39
+ * Whether one listed row can be disconnected, and -- when it cannot -- which
40
+ * rule refuses it.
41
+ *
42
+ * @param options {object}
43
+ * @param options.client {AccountClientView} the row in question
44
+ * @param options.clients {AccountClientView[]} the whole listing (the
45
+ * last-client rule is a property of the account, not of the row)
46
+ * @returns {{ allowed: boolean, refusal?: DisconnectRefusal }}
47
+ */
48
+ export declare function disconnectEligibility({ client, clients }: {
49
+ client: AccountClientView;
50
+ clients: AccountClientView[];
51
+ }): {
52
+ allowed: boolean;
53
+ refusal?: DisconnectRefusal;
54
+ };
55
+ /**
56
+ * Narrows a listed row to the key set a revocation needs, throwing when the
57
+ * row's active update key could not be attributed. A row with all three key
58
+ * members present is exactly a `RevokedClientKeys`.
59
+ *
60
+ * @param options {object}
61
+ * @param options.client {AccountClientView}
62
+ * @returns {RevokedClientKeys}
63
+ */
64
+ export declare function revokedClientKeysFor({ client }: {
65
+ client: AccountClientView;
66
+ }): RevokedClientKeys;
67
+ /**
68
+ * How a completed cascade should be reported: `complete` when every encrypted
69
+ * collection took the fresh key, `partial` when some did not -- a resumable
70
+ * success, never an error (see the module doc).
71
+ *
72
+ * @param options {object}
73
+ * @param options.collections {PukCascadeResult} the collection fan-out result
74
+ * @returns {'complete' | 'partial'}
75
+ */
76
+ export declare function cascadeCompletion({ collections }: {
77
+ collections: PukCascadeResult;
78
+ }): 'complete' | 'partial';
79
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/clients/policy.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAC3B,MAAM,GAAG,aAAa,GAAG,yBAAyB,CAAA;AAEpD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EACR,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAA;IACzB,OAAO,EAAE,iBAAiB,EAAE,CAAA;CAC7B,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAAE,CAWpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACP,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAA;CAC1B,GAAG,iBAAiB,CAYpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACZ,EAAE;IACD,WAAW,EAAE,gBAAgB,CAAA;CAC9B,GAAG,UAAU,GAAG,SAAS,CAEzB"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Whether one listed row can be disconnected, and -- when it cannot -- which
3
+ * rule refuses it.
4
+ *
5
+ * @param options {object}
6
+ * @param options.client {AccountClientView} the row in question
7
+ * @param options.clients {AccountClientView[]} the whole listing (the
8
+ * last-client rule is a property of the account, not of the row)
9
+ * @returns {{ allowed: boolean, refusal?: DisconnectRefusal }}
10
+ */
11
+ export function disconnectEligibility({ client, clients }) {
12
+ if (client.isCurrent) {
13
+ return { allowed: false, refusal: 'self' };
14
+ }
15
+ if (clients.length <= 1) {
16
+ return { allowed: false, refusal: 'last-client' };
17
+ }
18
+ if (!client.updateKeyMultibase) {
19
+ return { allowed: false, refusal: 'unattributed-update-key' };
20
+ }
21
+ return { allowed: true };
22
+ }
23
+ /**
24
+ * Narrows a listed row to the key set a revocation needs, throwing when the
25
+ * row's active update key could not be attributed. A row with all three key
26
+ * members present is exactly a `RevokedClientKeys`.
27
+ *
28
+ * @param options {object}
29
+ * @param options.client {AccountClientView}
30
+ * @returns {RevokedClientKeys}
31
+ */
32
+ export function revokedClientKeysFor({ client }) {
33
+ if (!client.updateKeyMultibase) {
34
+ throw new Error("This wallet's update key could not be attributed from the account " +
35
+ 'log, so it cannot be disconnected from here.');
36
+ }
37
+ return {
38
+ signingKeyMultibase: client.signingKeyMultibase,
39
+ keyAgreementKeyMultibase: client.keyAgreementKeyMultibase,
40
+ updateKeyMultibase: client.updateKeyMultibase
41
+ };
42
+ }
43
+ /**
44
+ * How a completed cascade should be reported: `complete` when every encrypted
45
+ * collection took the fresh key, `partial` when some did not -- a resumable
46
+ * success, never an error (see the module doc).
47
+ *
48
+ * @param options {object}
49
+ * @param options.collections {PukCascadeResult} the collection fan-out result
50
+ * @returns {'complete' | 'partial'}
51
+ */
52
+ export function cascadeCompletion({ collections }) {
53
+ return collections.failed.length > 0 ? 'partial' : 'complete';
54
+ }
55
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/clients/policy.ts"],"names":[],"mappings":"AAwCA;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EAIR;IACC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IAC5C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,CAAA;IACnD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAA;IAC/D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,MAAM,EAGP;IACC,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,oEAAoE;YAClE,8CAA8C,CACjD,CAAA;IACH,CAAC;IACD,OAAO;QACL,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,wBAAwB,EAAE,MAAM,CAAC,wBAAwB;QACzD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;KAC9C,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,WAAW,EAGZ;IACC,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAA;AAC/D,CAAC"}
@@ -0,0 +1,156 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The client-revocation cascade: disconnecting an enrolled wallet client from
6
+ * an account, run synchronously in the revoking client, in dependency order.
7
+ * One orchestrator for every wallet, with the two app-specific stages injected
8
+ * rather than forked.
9
+ *
10
+ * 1. **The document edit** (`revokeWebvhClient`): the revoked client's two
11
+ * verification methods, its update key, and both its standing prerotation
12
+ * commitments leave the account's did:webvh document in one log entry.
13
+ * Under the current-key-set rule that single edit is the revoked client's
14
+ * pull axis EVERYWHERE -- its invocations, and every delegation and app
15
+ * grant it ever signed, stop verifying the moment its verification method
16
+ * leaves the document. There is no per-collection revoke anywhere in the
17
+ * cascade; apps a revoked client had connected reconnect through the
18
+ * ordinary connect flow.
19
+ * 2. **The per-user key rotation** in the wrap-set roster, recipients resolved
20
+ * from the document the edit itself just resolved to (no re-fetch of the
21
+ * log this call just extended). The roster delivers, never sources, so the
22
+ * revoked client's entry is dropped even before the retire filter. An
23
+ * account with no roster yet stops here: the client IS disconnected, with
24
+ * nothing to rotate.
25
+ * 3. **The collection fan-out**: every encrypted collection is re-epoch'd onto
26
+ * the fresh key in parallel, so writes stop landing under epochs the
27
+ * revoked client can still decrypt. Failures are collected per collection
28
+ * and never abort the fan-out.
29
+ * 4. **The recovery re-mints** (optional): delegations the revoked client had
30
+ * signed stopped chaining at stage 1, so a wallet that issues recovery
31
+ * codes re-mints them here -- while the registry is still readable under
32
+ * the session's pre-adoption vault keys.
33
+ *
34
+ * The revoking session then adopts the fresh key in place (`onRotationAdopted`
35
+ * -- profile vault keys, storage ciphers, engine restarts: whatever "in place"
36
+ * means for the app), so it keeps operating without a re-login.
37
+ *
38
+ * Convergence is the design: every stage detects its own completion from
39
+ * durable state alone -- the log entry is idempotent, the roster no-ops once
40
+ * the revoked entry is off the current epoch, and a collection is stale
41
+ * exactly when its current epoch names a non-current key generation -- so a
42
+ * mid-cascade crash strands nothing permanently and a naive full re-run
43
+ * finishes it (the login-time completion sweep is the standing backstop). The
44
+ * honest ceiling is unchanged: ciphertext the revoked client already fetched
45
+ * stays readable to it, and old epochs open to keys it already held.
46
+ */
47
+ import type { IKeyAgreementKey } from '@interop/data-integrity-core';
48
+ import type { CollectionEncryption } from '@interop/was-client';
49
+ import type { EncryptionDescriptorStore } from '@interop/was-client/edv';
50
+ import { type ClientWebvhUpdateKeys, type RevokedClientKeys, type WebvhIdStore } from '../webvh/index.js';
51
+ import { type Puk, type PukCascadeResult } from '../keys/index.js';
52
+ /**
53
+ * Where the cascade's collection fan-out gets its work: which encrypted
54
+ * collections exist (only the app knows -- a mobile replica names the
55
+ * collections it replicates, a web wallet also lists the app-provisioned ones
56
+ * remotely) and how each one's descriptor store and encryption declaration are
57
+ * reached.
58
+ */
59
+ export interface CascadeCollections {
60
+ collectionIds: string[] | (() => Promise<string[]>);
61
+ storeFor: (collectionId: string) => EncryptionDescriptorStore;
62
+ isEncrypted?: (collectionId: string) => Promise<boolean>;
63
+ }
64
+ /**
65
+ * What a completed cascade reports: whether the roster actually rotated on
66
+ * this run (a re-run of an already-complete revocation reports `false`), the
67
+ * per-collection fan-out result, the document as the edit left it, and the
68
+ * recovery re-mint counts when that stage ran.
69
+ */
70
+ export interface ClientRevocationResult {
71
+ rotated: boolean;
72
+ collections: PukCascadeResult;
73
+ document: object;
74
+ puk?: Puk;
75
+ rosterDescriptor?: CollectionEncryption;
76
+ recovery?: {
77
+ reminted: number;
78
+ skipped: number;
79
+ };
80
+ }
81
+ /**
82
+ * Runs the whole revocation cascade for one enrolled wallet client. See the
83
+ * module doc for the order and the convergence story. Throws before touching
84
+ * anything on a call that must not proceed (revoking this client itself, a
85
+ * client whose active update key was not attributed); once the document edit
86
+ * lands, a thrown later stage leaves durable state a naive re-run -- or the
87
+ * login-time sweep -- converges from.
88
+ *
89
+ * The document edit's `StagedCommitmentAmbiguousError` passes through
90
+ * unwrapped, so a surface can re-word it ("disconnect this wallet from the
91
+ * other one instead"). Match it on `err.name ===
92
+ * 'StagedCommitmentAmbiguousError'` -- a stable contract on that class --
93
+ * rather than on `instanceof`, which does not survive a linked or duplicated
94
+ * copy of this package.
95
+ *
96
+ * @param options {object}
97
+ * @param options.idStore {WebvhIdStore} the account's `id` collection store
98
+ * @param options.updateKeys {ClientWebvhUpdateKeys} THIS client's did:webvh
99
+ * update-key seeds, which sign the document edit
100
+ * @param options.revokedClient {RevokedClientKeys} the revoked client's
101
+ * public halves (its two verification-method multibases and its active
102
+ * update key)
103
+ * @param [options.knownLatentHashes] {string[]} the standing recovery codes'
104
+ * update-key hashes, so the document edit can tell the revoked client's
105
+ * staged commitment apart from a latent recovery commitment (the one
106
+ * ambiguous log shape). Best-effort on the caller's side: an unreadable
107
+ * registry simply omits them
108
+ * @param [options.ownSigningKeyMultibase] {string} this client's own signing
109
+ * key; supplied, self-revocation is refused up front by the rule the surface
110
+ * should name, rather than by the update-key check inside the edit
111
+ * @param options.rosterStore {EncryptionDescriptorStore} the
112
+ * `key-map/puk.json` roster store
113
+ * @param [options.puk] {Puk} this client's cached per-user key
114
+ * @param options.clientKeyAgreementKey {IKeyAgreementKey} this client's own
115
+ * (identity) key-agreement key -- its roster entry
116
+ * @param [options.pinnedEpochId] {string} the locally pinned latest-seen
117
+ * roster epoch
118
+ * @param [options.onPukAdopted] {Function} persists a rotated key: called
119
+ * with `{ puk, latestEpochId, descriptor }` after the roster read and BEFORE
120
+ * the fan-out. The key and the epoch pin must persist atomically
121
+ * @param options.collections {CascadeCollections} the fan-out's work
122
+ * @param [options.remintRecoveryDelegations] {Function} `({ document }) =>
123
+ * Promise<{ reminted, skipped }>` -- the recovery-delegation re-mint stage,
124
+ * for a wallet that issues recovery codes
125
+ * @param [options.onRotationAdopted] {Function} `({ puk }) => Promise<void>`
126
+ * -- the live-session adoption of a rotated key, run last so the session
127
+ * keeps operating without a re-login
128
+ * @returns {Promise<ClientRevocationResult>}
129
+ */
130
+ export declare function revokeAccountClient({ idStore, updateKeys, revokedClient, knownLatentHashes, ownSigningKeyMultibase, rosterStore, puk, clientKeyAgreementKey, pinnedEpochId, onPukAdopted, collections, remintRecoveryDelegations, onRotationAdopted }: {
131
+ idStore: WebvhIdStore;
132
+ updateKeys: ClientWebvhUpdateKeys;
133
+ revokedClient: RevokedClientKeys;
134
+ knownLatentHashes?: string[];
135
+ ownSigningKeyMultibase?: string;
136
+ rosterStore: EncryptionDescriptorStore;
137
+ puk?: Puk;
138
+ clientKeyAgreementKey: IKeyAgreementKey;
139
+ pinnedEpochId?: string | null;
140
+ onPukAdopted?: (adopted: {
141
+ puk: Puk;
142
+ latestEpochId: string;
143
+ descriptor: CollectionEncryption;
144
+ }) => Promise<void>;
145
+ collections: CascadeCollections;
146
+ remintRecoveryDelegations?: (options: {
147
+ document: object;
148
+ }) => Promise<{
149
+ reminted: number;
150
+ skipped: number;
151
+ }>;
152
+ onRotationAdopted?: (rotation: {
153
+ puk: Puk;
154
+ }) => Promise<void>;
155
+ }): Promise<ClientRevocationResult>;
156
+ //# sourceMappingURL=revocation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revocation.d.ts","sourceRoot":"","sources":["../../src/clients/revocation.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AACxE,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAA;AAEzB;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACnD,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,yBAAyB,CAAA;IAC7D,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,gBAAgB,CAAA;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,gBAAgB,CAAC,EAAE,oBAAoB,CAAA;IACvC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CACjD;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,OAAO,EACP,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,EACX,GAAG,EACH,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,yBAAyB,EACzB,iBAAiB,EAClB,EAAE;IACD,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,qBAAqB,CAAA;IACjC,aAAa,EAAE,iBAAiB,CAAA;IAChC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,WAAW,EAAE,yBAAyB,CAAA;IACtC,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,qBAAqB,EAAE,gBAAgB,CAAA;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QACvB,GAAG,EAAE,GAAG,CAAA;QACR,aAAa,EAAE,MAAM,CAAA;QACrB,UAAU,EAAE,oBAAoB,CAAA;KACjC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB,WAAW,EAAE,kBAAkB,CAAA;IAC/B,yBAAyB,CAAC,EAAE,CAAC,OAAO,EAAE;QACpC,QAAQ,EAAE,MAAM,CAAA;KACjB,KAAK,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpD,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,GAAG,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC9D,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAuFlC"}