@cef-ai/vault-sdk 3.3.0 → 4.0.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 (43) hide show
  1. package/dist/client.d.ts +26 -2
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +40 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/core/canonical.d.ts +17 -1
  6. package/dist/core/canonical.d.ts.map +1 -1
  7. package/dist/core/canonical.js +26 -1
  8. package/dist/core/canonical.js.map +1 -1
  9. package/dist/core/endpoints.d.ts +5 -4
  10. package/dist/core/endpoints.d.ts.map +1 -1
  11. package/dist/core/endpoints.js +13 -4
  12. package/dist/core/endpoints.js.map +1 -1
  13. package/dist/core/grant-doc.d.ts +345 -0
  14. package/dist/core/grant-doc.d.ts.map +1 -0
  15. package/dist/core/grant-doc.js +603 -0
  16. package/dist/core/grant-doc.js.map +1 -0
  17. package/dist/core/types.d.ts +181 -49
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/fluent/vault.d.ts +6 -0
  20. package/dist/fluent/vault.d.ts.map +1 -1
  21. package/dist/fluent/vault.js +7 -0
  22. package/dist/fluent/vault.js.map +1 -1
  23. package/dist/index.d.ts +4 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal/memberships.d.ts +360 -0
  28. package/dist/internal/memberships.d.ts.map +1 -0
  29. package/dist/internal/memberships.js +403 -0
  30. package/dist/internal/memberships.js.map +1 -0
  31. package/dist/internal/vaults.d.ts +22 -0
  32. package/dist/internal/vaults.d.ts.map +1 -1
  33. package/dist/internal/vaults.js +11 -0
  34. package/dist/internal/vaults.js.map +1 -1
  35. package/dist/internal-exports.d.ts +2 -1
  36. package/dist/internal-exports.d.ts.map +1 -1
  37. package/dist/internal-exports.js +1 -1
  38. package/dist/internal-exports.js.map +1 -1
  39. package/package.json +3 -3
  40. package/dist/internal/orgs.d.ts +0 -59
  41. package/dist/internal/orgs.d.ts.map +0 -1
  42. package/dist/internal/orgs.js +0 -80
  43. package/dist/internal/orgs.js.map +0 -1
@@ -0,0 +1,360 @@
1
+ import type { Signer } from "@cef-ai/signer";
2
+ import type { VaultHttpClient } from "../core/http.js";
3
+ import type { Member, MemberRole, MembershipSummary, ScopeGrants, SignedRoster } from "../core/types.js";
4
+ /**
5
+ * What the caller already knows about the membership's OTHER half, so the
6
+ * grant document can be built without reading it back.
7
+ *
8
+ * The document always describes the membership as it will read AFTER the
9
+ * write, and each write route sets only one of its two components (see
10
+ * `Memberships`' doc comment). Absent, the SDK reads the other half from the
11
+ * server; supplied, it is signed as given — which saves the round trip for a
12
+ * console that already holds the roster, and is refused with a 400 naming the
13
+ * document the server derived if it is wrong.
14
+ */
15
+ export interface PutMemberOptions {
16
+ /** The scope grants this member ALREADY holds. Default: read back. */
17
+ scopes?: ScopeGrants;
18
+ }
19
+ /** @see PutMemberOptions */
20
+ export interface PutScopesOptions {
21
+ /**
22
+ * The standing this member ALREADY has — BOTH halves this route does not
23
+ * set. Default: read both back off the roster in one GET.
24
+ *
25
+ * ONE OPTION CARRYING TWO FIELDS, replacing the former `role?`. The grant
26
+ * document covers the role AND the expiry, and this route changes neither,
27
+ * so a caller who knew only the role would have had the SDK sign
28
+ * "never expires" for a membership that does expire — a document vault-api
29
+ * refuses, and would have honoured as a widening if it did not. Knowing
30
+ * half the standing is not knowing the standing.
31
+ *
32
+ * `expiresAt` absent inside this object means the membership has no expiry.
33
+ * Pass the spelling you read off `list()`; any spelling of the right
34
+ * instant is accepted, because the server compares instants (it cannot
35
+ * render the signer's original string back out of a timestamp column).
36
+ */
37
+ standing?: {
38
+ role: MemberRole;
39
+ expiresAt?: string;
40
+ };
41
+ }
42
+ /**
43
+ * Who belongs to a vault, in what role, holding which scope grants — and,
44
+ * from the other direction, which vaults the caller belongs to.
45
+ *
46
+ * ## THERE IS NO ORG ENTITY (D1)
47
+ *
48
+ * This class replaces `sdk.orgs`, which addressed an `orgId`. The `orgs`
49
+ * table and every `/api/v1/orgs…` route were removed, not aliased: a vault
50
+ * IS the organization, and **a vault BECOMES one by acquiring a second
51
+ * member**, which is `put()` below. There is deliberately no `create` — the
52
+ * removed `POST /api/v1/orgs` needed only half a replacement, the naming
53
+ * half, and that is `sdk.vault.rename()` (`PATCH /api/v1/vaults/:vaultId`),
54
+ * because a name is a property of the vault and a single-member vault must
55
+ * be nameable too.
56
+ *
57
+ * ## The one thing a consumer porting from `sdk.orgs` gets wrong
58
+ *
59
+ * `mine()` does NOT include the caller's own vault. `sdk.orgs.list()` folded
60
+ * the two together by synthesising an owner entry; the owner is never a
61
+ * membership row under D1, and `sdk.vault.current()` already answers "my own
62
+ * vault" keyed by wallet. **A switcher shows both by calling both** — and
63
+ * folding them here would double-count for anyone who did:
64
+ *
65
+ * ```ts
66
+ * const [own, joined] = await Promise.all([
67
+ * sdk.vault.current(), // the vault this wallet owns
68
+ * sdk.memberships.mine(), // the vaults this wallet was invited into
69
+ * ]);
70
+ * ```
71
+ *
72
+ * ## THE TWO WRITES CARRY A SECOND SIGNATURE, AND IT IS THE OWNER'S
73
+ *
74
+ * `put()` and `putScopes()` send `X-Grant-Signature`: the VAULT OWNER's
75
+ * ed25519 signature over the grant's canonical document
76
+ * (`canonicalGrantBytes`). ddc-node #1136 made it mandatory on both, so
77
+ * without it neither method can succeed at all — a 400 `grant sig: missing
78
+ * X-Grant-Signature`. They send `X-Grant-Issued-At` alongside it, carrying the
79
+ * moment the document was minted: it is inside the signed bytes, and the
80
+ * server rebuilds those bytes rather than receiving them, so it has no way to
81
+ * supply that field itself. It is a header of its own rather than the wallet auth's
82
+ * `X-Signature` because the two cover different bytes: `X-Signature` covers
83
+ * the request BODY and authenticates the caller, while this covers a document
84
+ * that names the vault, the member, the role and the scopes, so one signature
85
+ * cannot be replayed onto another member or another vault.
86
+ *
87
+ * `remove()` sends NO grant signature, and that is not an omission —
88
+ * `DeleteMember` has no such check. Read the handler before assuming
89
+ * symmetry: revocation deletes the row (and, by FK, its grants), so there is
90
+ * no post-write standing left for a document to describe.
91
+ *
92
+ * ### The document describes the membership AFTER the write, and each route
93
+ * ### knows only half of it
94
+ *
95
+ * `PutMember` builds its document from the role in the body and the scopes
96
+ * ALREADY IN THE STORE; `PutScopes` builds its own from the scopes in the
97
+ * body and the role already in the store. So each method reads the other half
98
+ * back before signing — one extra GET — unless the caller supplies it
99
+ * (`PutMemberOptions.scopes` / `PutScopesOptions.role`). Signing the same
100
+ * bytes for both calls is refused by the second.
101
+ *
102
+ * ### AN ADMIN WHO IS NOT THE OWNER CANNOT SIGN
103
+ *
104
+ * The route's gate admits the vault owner OR a live `role: "admin"` member,
105
+ * but `verifyGrantDocument` checks the signature against the VAULT's wallet
106
+ * key and nothing else. So an admin can be authorised to make this request
107
+ * and unable to produce the document it must carry. The SDK signs with the
108
+ * configured `signer`, which is the owner in the ordinary case of an owner
109
+ * administering their own vault; a non-owner admin gets a 400 naming the
110
+ * document, and needs one their owner signed out of band — pass it by calling
111
+ * the route through `VaultHttpClient` directly with the header set. There is
112
+ * no in-band way to obtain it today.
113
+ *
114
+ * ## Every mutation body carries a `timestamp`
115
+ *
116
+ * The wallet-signature middleware (`pkg/shared/auth/signature.go`) rejects
117
+ * ANY mutation body with no top-level RFC3339 `timestamp` as 401
118
+ * `INVALID_SIGNATURE "body missing timestamp"`, before the request reaches
119
+ * a handler. `WalletAuthProvider` supplies one during canonicalisation;
120
+ * `DelegationAuthProvider` (which never passes through that middleware)
121
+ * supplies nothing — so each method below sends its own, keeping the body
122
+ * correct on both paths. It is NOT a replay guard: ddc-node parses the field
123
+ * and no membership handler reads it.
124
+ */
125
+ export declare class Memberships {
126
+ private readonly http;
127
+ private readonly signer?;
128
+ /**
129
+ * `signer` is the VAULT OWNER's key, and it is required by `put` and
130
+ * `putScopes` only — every read here, and `remove`, work without one.
131
+ * Optional so that constructing this class from
132
+ * `@cef-ai/vault-sdk/internal` for reads alone keeps working unchanged;
133
+ * a write without it throws `VaultSignerRequiredError` rather than
134
+ * sending a request the server will refuse.
135
+ */
136
+ constructor(http: VaultHttpClient, signer?: Signer | undefined);
137
+ /**
138
+ * The vaults the caller is a MEMBER of, with their own grants on each —
139
+ * the employee's vault switcher. `GET /api/v1/memberships`.
140
+ *
141
+ * Excludes the caller's own vault; see this class's doc comment, which is
142
+ * the single most likely thing to get wrong when porting from
143
+ * `sdk.orgs.list()`.
144
+ *
145
+ * LIVE memberships only: a membership that is suspended or past its
146
+ * `expiresAt` is absent, not present-with-a-state. `scopes` is always
147
+ * present on every entry (these are the caller's OWN grants, so there is
148
+ * no disclosure question) and is `{}` — never `null` — when they hold
149
+ * none.
150
+ */
151
+ mine(): Promise<MembershipSummary[]>;
152
+ /**
153
+ * The vault's roster. `GET /api/v1/vaults/:vaultId/members`.
154
+ *
155
+ * Readable by the vault owner or any of its own LIVE members, whatever
156
+ * their role; 403 (uniformly, so an outsider cannot enumerate) otherwise,
157
+ * and 404 if the vault was never claimed.
158
+ *
159
+ * THE OWNER ROW IS FIRST, is synthesised (`isOwner: true`, `role:
160
+ * "admin"`, `state: "active"`), and carries NO `scopes` — see `Member`.
161
+ * Every other row's `scopes` is present only when disclosed to the caller.
162
+ * `Member.scopes` being absent is NOT the same as `{}`; do not default it.
163
+ */
164
+ list(vaultId: string): Promise<Member[]>;
165
+ /**
166
+ * The same roster as SIGNED EVIDENCE.
167
+ * `GET /api/v1/vaults/:vaultId/roster/signed`.
168
+ *
169
+ * Each entry carries the canonical grant document the vault owner signed
170
+ * and that signature, so a party that does NOT trust this vault-api can
171
+ * decide what a member may do. That is the entire point of the route, and
172
+ * it only holds if the consumer checks the documents AGAINST SOMETHING
173
+ * THIS RESPONSE DID NOT SUPPLY:
174
+ *
175
+ * ```ts
176
+ * import { verifySignedRoster } from "@cef-ai/vault-sdk";
177
+ *
178
+ * const roster = await sdk.memberships.signedRoster(vaultId);
179
+ * const grants = await verifySignedRoster(roster, vaultId); // throws on any entry
180
+ * // act on `grants` — never on roster.grants[i].role / .scopes
181
+ * ```
182
+ *
183
+ * **Pass the SAME `vaultId` you asked for.** `verifySignedRoster` requires
184
+ * it and will not verify without it, because the alternative is not a
185
+ * weaker check but a meaningless one: `orgWalletPubkey` arrives inside the
186
+ * response, so a roster checked only against itself proves that whoever
187
+ * answered can sign — never that they are the vault's owner. The id is the
188
+ * one value the responder does not get to choose; `vaultIdFor` makes the
189
+ * owner key answer to it. A caller holding the owner key instead of the id
190
+ * gets the id from `vaultIdFor(ownerKey)`.
191
+ *
192
+ * What this does NOT establish: that the vault id is the one you meant. It
193
+ * anchors the roster to a vault, so anchor the vault to something you knew
194
+ * beforehand rather than to a value the same untrusted party handed you.
195
+ *
196
+ * The raw shape is returned rather than the verified one so evidence can be
197
+ * forwarded to a third party intact; `verifySignedRoster` is the step that
198
+ * turns it into values worth acting on. `SignedGrant.role` and
199
+ * `.scopes` are vault-api's own decoding of `doc`, provided for display —
200
+ * enforcing on them verifies one thing and enforces another.
201
+ *
202
+ * Same gate and same disclosure rule as `list()`: readable by the owner or
203
+ * any LIVE member (404 for an unclaimed vault, a uniform 403 otherwise),
204
+ * owner and live admin see every grant, a plain member only their own. Two
205
+ * differences from `list()`, both deliberate: the owner is NOT an entry
206
+ * here (they hold no signed document — `orgWalletPubkey` is where they
207
+ * appear), and only LIVE memberships are served, so there is no `state`
208
+ * field to check.
209
+ */
210
+ signedRoster(vaultId: string): Promise<SignedRoster>;
211
+ /**
212
+ * Adds or updates a member. `PUT /api/v1/vaults/:vaultId/members/:memberPubkey`.
213
+ *
214
+ * **This is how a vault becomes an organization** — there is no
215
+ * registration step; the first successful call is the whole ceremony.
216
+ *
217
+ * Requires the vault owner or a live `role: "admin"` member. 400 if
218
+ * `memberPubkey` is the vault's own owner — the owner is never a
219
+ * membership row (D1) — and 404 if the vault is unclaimed.
220
+ *
221
+ * `memberPubkey` should already be in the server's canonical
222
+ * 0x-lowercase-hex spelling (`auth.CanonicalPubKeyHex`), which is the one
223
+ * spelling every authorization read looks members up by.
224
+ *
225
+ * `expiresAt` MUST BE RFC 3339 — vault-api parses it for the timestamptz
226
+ * column and 400s anything else, naming the field. It is also INSIDE THE
227
+ * SIGNED DOCUMENT now, and the server rebuilds the document from the string
228
+ * this method sends: the exact spelling passed here is what is signed and
229
+ * what is sent, never re-derived from a `Date` on either side. Formatting it
230
+ * twice is how the two copies drift by a trimmed fractional zero and the
231
+ * signature fails as though the key were wrong.
232
+ *
233
+ * The returned `Member` carries neither `scopes` nor `isOwner`: it is the
234
+ * row just written, and grants are a separate call (`putScopes`).
235
+ *
236
+ * CARRIES THE OWNER'S `X-Grant-Signature` over
237
+ * `{vaultId, memberPubkey, role, scopes, issuedAt, expiresAt}` — see the
238
+ * class doc comment. The scopes in that document are the ones the member
239
+ * ALREADY HOLDS, because this route sets the role only, so re-roling a
240
+ * member with grants signs those grants too. They are read back with `scopes()` (a 404 — the new
241
+ * member case — is `{}`); pass `{ scopes }` to skip that GET when they are
242
+ * already in hand.
243
+ */
244
+ put(vaultId: string, memberPubkey: string, role: MemberRole, expiresAt?: string, opts?: PutMemberOptions): Promise<Member>;
245
+ /**
246
+ * Removes a member row. `DELETE /api/v1/vaults/:vaultId/members/:memberPubkey`.
247
+ *
248
+ * 409 — not 404 — for the vault's own owner: they cannot be removed at
249
+ * all, and 404 would read as "already gone, nothing left to do" to an
250
+ * admin who believed they had locked the founder out.
251
+ *
252
+ * ddc-node's handler never reads the body, but the wallet-signature
253
+ * middleware still requires a top-level `timestamp` on every mutation
254
+ * regardless of what the handler does with it — so this body is
255
+ * `{timestamp}` and nothing else.
256
+ *
257
+ * NO `X-Grant-Signature`, deliberately and after reading `DeleteMember`:
258
+ * the grant check lives in `verifyGrantDocument`, which only `PutMember`
259
+ * and `PutScopes` call. Adding one here on the assumption that the three
260
+ * writes are symmetrical would send a header the server ignores and would
261
+ * make this method need a signer it has no use for.
262
+ */
263
+ remove(vaultId: string, memberPubkey: string): Promise<void>;
264
+ /**
265
+ * A member's scope grants.
266
+ * `GET /api/v1/vaults/:vaultId/members/:memberPubkey/scopes`.
267
+ *
268
+ * Readable by the vault owner, a live admin, or the member themselves.
269
+ * 404 when the membership does not exist — INCLUDING when the vault OWNER
270
+ * asks for their own grants, which is the read-side face of "the owner is
271
+ * never a row": their authority is key math and there is no grant row.
272
+ *
273
+ * `list()` already carries `scopes` inline on every disclosed row, so a
274
+ * console rendering a roster should NOT call this per member — that is an
275
+ * N+1. This is for reading one membership's grants directly.
276
+ */
277
+ scopes(vaultId: string, memberPubkey: string): Promise<{
278
+ scopes: ScopeGrants;
279
+ }>;
280
+ /**
281
+ * Replaces a member's FULL scope-grant set.
282
+ * `PUT /api/v1/vaults/:vaultId/members/:memberPubkey/scopes`.
283
+ *
284
+ * The server deletes then reinserts, so this is never a merge or a diff
285
+ * against the existing grants — send the complete intended set. 404 if the
286
+ * membership row does not exist, INCLUDING for an empty `scopes` map: the
287
+ * check is EXISTENCE, not liveness, so an admin may prepare the grants of
288
+ * a currently-suspended membership.
289
+ *
290
+ * CARRIES THE OWNER'S `X-Grant-Signature` over
291
+ * `{vaultId, memberPubkey, role, scopes, issuedAt, expiresAt}` — see the
292
+ * class doc comment. The role AND the expiry in that document are the ones
293
+ * the member ALREADY HOLDS, because this route sets the scopes only; both
294
+ * are read off the roster (`list()`) in one GET, which is why a
295
+ * `memberPubkey` with no row fails here rather than as the server's 404.
296
+ * Pass `{ standing: { role, expiresAt } }` to skip it.
297
+ *
298
+ * THE EXPIRY IS ALSO SENT IN THE BODY, and that is the one place this route
299
+ * differs from `put`. vault-api holds the expiry as a timestamp and the
300
+ * document carries the signer's STRING, which a timestamp cannot be
301
+ * rendered back into — so the server cannot supply this field the way it
302
+ * supplies the role. It checks what is sent against the stored instant, so
303
+ * stating it cannot widen the membership: a different moment is a 400.
304
+ */
305
+ putScopes(vaultId: string, memberPubkey: string, scopes: ScopeGrants, opts?: PutScopesOptions): Promise<void>;
306
+ /**
307
+ * The vault owner's signature over this grant's canonical document, as the
308
+ * `X-Grant-Signature` header — see the class doc comment for why a write
309
+ * cannot land without it.
310
+ *
311
+ * `memberPubkey` is canonicalised FIRST. The server canonicalises the URL
312
+ * parameter before it derives the bytes (`memberPubkeyParam`), so signing
313
+ * the caller's own spelling of a bare or upper-case key produces a valid
314
+ * signature over a document the server never builds — a 400 that reads as
315
+ * a key problem. `vaultId` is NOT canonicalised, because the server does
316
+ * not touch it either.
317
+ *
318
+ * ED25519 ONLY, and checked here. `authz.VerifyGrantSig` hard-codes
319
+ * `SchemeEd25519` (unlike the request-auth middleware, which also takes
320
+ * sr25519), so an sr25519 owner can authenticate the request and still
321
+ * never produce a document the server will accept. Named up front rather
322
+ * than left to surface as an opaque signature refusal.
323
+ */
324
+ private grantHeader;
325
+ /**
326
+ * The scope grants this member holds RIGHT NOW — the half of `put`'s
327
+ * document that route reads from the store rather than from its body.
328
+ *
329
+ * A 404 is `{}`, not a failure: it is what `GET .../scopes` answers for a
330
+ * membership row that does not exist yet, which is the ordinary case of
331
+ * adding a NEW member, and it is exactly what the server's own
332
+ * `ListScopeGrantsForMember` yields there (it tolerates `ErrNotFound`).
333
+ * Every other error propagates — a 403 means this caller may not administer
334
+ * the vault at all, and guessing `{}` would turn it into a puzzling 400
335
+ * from the write instead.
336
+ */
337
+ private heldScopes;
338
+ /**
339
+ * The role AND expiry this member holds RIGHT NOW — the two halves of
340
+ * `putScopes`'s document that route reads from the store rather than from
341
+ * its body.
342
+ *
343
+ * BOTH OUT OF ONE ROW, deliberately. They used to be one value read here
344
+ * and one value the document did not carry at all; now that the expiry is
345
+ * signed, fetching them separately would be two chances for them to
346
+ * describe different moments of the same membership.
347
+ *
348
+ * From the roster rather than from a route of its own, because there is no
349
+ * single-membership read that carries a role: `GET .../scopes` returns only
350
+ * grants. The synthesised OWNER row is skipped explicitly — the owner is
351
+ * never a membership row (D1), so a `memberPubkey` matching it is the
352
+ * server's 400, not a standing to sign.
353
+ *
354
+ * `expiresAt` absent on the row means the membership does not expire; the
355
+ * roster omits the key rather than sending null (Go `omitempty`), which is
356
+ * the same three-state distinction `Member.scopes` documents.
357
+ */
358
+ private heldStanding;
359
+ }
360
+ //# sourceMappingURL=memberships.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memberships.d.ts","sourceRoot":"","sources":["../../src/internal/memberships.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAavD,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACb,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,4BAA4B;AAC5B,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,qBAAa,WAAW;IAUpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAV1B;;;;;;;OAOG;gBAEgB,IAAI,EAAE,eAAe,EACrB,MAAM,CAAC,EAAE,MAAM,YAAA;IAGlC;;;;;;;;;;;;;OAaG;IACH,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAIpC;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,GAAG,CACP,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAalB;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC;IAI/E;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAUhB;;;;;;;;;;;;;;;;;OAiBG;YACW,WAAW;IAiDzB;;;;;;;;;;;OAWG;YACW,UAAU;IASxB;;;;;;;;;;;;;;;;;;;OAmBG;YACW,YAAY;CAkB3B"}