@civitai/blocks-react 0.43.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -216,6 +216,15 @@ const body: WorkflowBody = {
216
216
  modelVersionId,
217
217
  params: { prompt: userPrompt },
218
218
  };
219
+ // The viewer-facing copy is a string YOUR APP owns, chosen by `err.code`.
220
+ // Nothing on the error may be rendered: `err.message` is developer-facing and
221
+ // its wording is not a contract; `err.snapshot.error` is server-authored and
222
+ // unsanitised.
223
+ const estimateFailureMessage = (err: WorkflowEstimateError) =>
224
+ err.code === 'no-cost'
225
+ ? 'We could not get a price for this configuration. Try adjusting it.'
226
+ : 'Pricing is unavailable right now. Please try again shortly.';
227
+
219
228
  // 🔴 estimate() REJECTS when the reply carries no usable price. ALWAYS catch it.
220
229
  let priced = false;
221
230
  try {
@@ -223,16 +232,49 @@ try {
223
232
  priced = true;
224
233
  } catch (err) {
225
234
  if (!(err instanceof WorkflowEstimateError)) throw err;
226
- // status is now 'error'. Branch on err.code ('failed' | 'no-cost'). The
227
- // server's reason is on err.snapshot.error — server-authored and unsanitised,
228
- // so log it / show it in a dev-facing surface rather than as trusted copy.
229
- // err.message is a generic summary safe to print.
230
- logForDebugging(err.snapshot.error);
231
- showError('This configuration cannot be priced right now.');
235
+ // status is now 'error'. Log both for the developer; render neither.
236
+ logForDebugging(err.message, err.snapshot.error);
237
+ showError(estimateFailureMessage(err));
232
238
  }
233
239
  if (priced) {
234
- const snap = await submit(body); // status 'submitting' → 'polling'; returns a workflowId
235
- await poll(snap.workflowId); // you loop this on a backoff until terminal
240
+ // 🔴 submit() REJECTS when the reply carries no usable workflow outcome. A
241
+ // priced refusal is different — it RESOLVES.
242
+ try {
243
+ const snap = await submit(body); // status 'submitting' → 'polling'
244
+ if (snap.status === 'failed') {
245
+ // 🔴 A RESOLVED `failed` IS A PRICED SERVER OUTCOME — and only SOME of
246
+ // them are about the viewer's wallet. Affordability (per-call budget, the
247
+ // per-user daily Buzz cap) IS fixable by buying Buzz; the per-app velocity
248
+ // limit, the per-app aggregate daily cap, a fail-closed "temporarily
249
+ // unavailable" deny and a missing price quote are NOT. Selling Buzz for
250
+ // one of those takes money and fixes nothing, so branch before you offer.
251
+ showError(submitOutcomeMessage(snap)); // YOUR app owns this copy
252
+ } else {
253
+ await poll(snap.workflowId); // you loop this on a backoff until terminal
254
+ }
255
+ } catch (err) {
256
+ if (!(err instanceof WorkflowSubmitError)) throw err;
257
+ // Log both for the developer; render neither.
258
+ logForDebugging(err.message, err.snapshot.error);
259
+ // 🔴 TWO SEPARATE QUESTIONS — DO NOT CONJOIN THEM. `code` decides what you may
260
+ // say about MONEY; the id decides only whether there is something to POLL.
261
+ // Folding the id test into the `code` test sends a 'workflow-failed' reply
262
+ // whose id is 'whatif' into the reassuring arm — the exact blind-retry
263
+ // invitation this whole guard exists to remove.
264
+ if (err.code === 'workflow-failed') {
265
+ // 🔴 Spend MAY ALREADY BE COMMITTED. Do not tell the viewer it was free,
266
+ // and do not retry blindly — a retry mints a fresh idempotency key, i.e. a
267
+ // SECOND reservation.
268
+ showError('The generation may have started but did not complete. Check your history.');
269
+ // Only NOW ask about pollability: 'whatif' is a non-workflow sentinel.
270
+ if (err.snapshot.workflowId !== 'whatif') await poll(err.snapshot.workflowId);
271
+ } else {
272
+ // 🔴 'exception' means the host had no workflow to report — USUALLY nothing
273
+ // was queued, but a lost response or an in-progress idempotency conflict
274
+ // reaches this arm too. Retry with the SAME idempotencyKey, not a fresh one.
275
+ showError('Could not start the generation. Please try again.');
276
+ }
277
+ }
236
278
  }
237
279
  ```
238
280
 
@@ -246,10 +288,55 @@ if (priced) {
246
288
  - The hook does **not** auto-poll. After `submit` flips status to `'polling'`,
247
289
  the **caller** runs a `useEffect` that calls `poll(workflowId)` on a backoff
248
290
  until the snapshot is terminal (`succeeded | failed | canceled | expired`).
249
- - An over-budget / rejected **submit** comes back as a **resolved** snapshot with
250
- `status: 'failed'` + an `error` string — the transport resolves the reply, it
251
- doesn't throw. Check `snap.status`, not just `try/catch`.
252
- - **`estimate` is the exception to that rule** (`@civitai/blocks-react@0.43.0+`).
291
+ - A **priced** submit refusal comes back as a **resolved** snapshot with
292
+ `status: 'failed'`, an `error` string, **and a numeric `cost.total`** — the
293
+ price the server refused to charge. That is a workflow *outcome*, not an error.
294
+ Check `snap.status`, not just `try/catch`.
295
+ 🔴 **Not all of them are affordability.** Only the per-call `buzzBudget` gate
296
+ and the per-user daily Buzz cap are about the wallet. The per-app **velocity**
297
+ limit, the per-app **aggregate daily** cap, a fail-closed **"temporarily
298
+ unavailable"** deny and a **missing price quote** are priced outcomes too, and
299
+ buying Buzz fixes none of them. Branch before you offer a top-up.
300
+ - **`submit` REJECTS when the reply carries no usable workflow outcome**
301
+ (`@civitai/blocks-react@0.44.0+`). Every failure-shaped reply reports
302
+ `status: 'failed'`, so `status` cannot tell them apart — **`cost` presence
303
+ decides resolve-vs-reject, and `workflowId` decides which rejection**:
304
+ - **priced refusal** → carries `cost`. **Resolves**, as above.
305
+ - **a reply the host built itself** (`failureSnapshot(err)`, which stamps the
306
+ literal `workflowId: 'failed'` — from a `catch` or a short-circuit such as
307
+ the moderator-review nack) → no `cost`. **Rejects** with
308
+ `err.code === 'exception'`, which means *the host had no workflow to report*.
309
+ 🔴 **Not the same as "nothing happened."** Usually nothing was queued or
310
+ charged and a retry is fine, but a **lost response**, an **in-progress
311
+ idempotency conflict**, or a **transient 5xx/408/429/401** also land here,
312
+ and a workflow may have been created and charged. Prefer reusing the same
313
+ `idempotencyKey` on retry, and don't render "nothing was charged" as fact.
314
+ - **a failed, unpriced reply whose id is NOT that sentinel** (normally a
315
+ genuine orchestrator id) → no `cost`. **Rejects** with
316
+ `err.code === 'workflow-failed'`.
317
+ 🔴 **Money may already be committed.** Server-side, *any* resolved submit
318
+ keeps its Buzz reservation "regardless of snapshot status", with no refund on
319
+ a non-throwing failed snapshot. So do not tell the viewer it was free, and do
320
+ not retry blindly — `submit()` mints a fresh `idempotencyKey` per call, so an
321
+ automatic retry is a second reservation. Read `err.snapshot.workflowId` (a
322
+ usually-pollable id) and `watch`/`poll` it to learn the workflow's actual
323
+ fate — guarding with `err.snapshot.workflowId !== 'whatif'` first, since the
324
+ server treats both `'failed'` and `'whatif'` as non-workflow sentinels.
325
+
326
+ Before that version everything resolved, so a block branching on
327
+ `snap.status === 'failed'` could not tell "you can't afford this" from "the
328
+ request failed", and one gating a money control on
329
+ `typeof snap.cost?.total === 'number'` saw the same dead-control shape
330
+ civitai/civitai#4159 describes. An ordinary in-flight reply
331
+ (`{ status: 'pending' }`) is cost-less too and still resolves — and so are
332
+ cost-less `succeeded` / `canceled` / `expired` replies. Only a *failure-shaped*
333
+ reply with no price rejects. `err.message` is a generic developer-facing
334
+ constant that makes **no claim about money** (the two codes differ on that) and
335
+ the server's words stay on `err.snapshot.error`, exactly as on
336
+ `WorkflowEstimateError` below. Note this also fires in **moderator review
337
+ preview**. To exercise your `catch` locally, set the mock host's
338
+ `generation.failSubmitException: true`.
339
+ - **`estimate` follows the same rule for a different question** (`@civitai/blocks-react@0.43.0+`).
253
340
  It **rejects** with a `WorkflowEstimateError` when the reply carries no usable
254
341
  price, rather than resolving a snapshot with no `cost`. Two things produce
255
342
  that, and `err.code` tells them apart: `'failed'` (the estimate errored
@@ -263,16 +350,23 @@ if (priced) {
263
350
  `catch`, a reviewer's first click becomes an unhandled rejection.
264
351
  To exercise your `catch` locally, set the mock host's
265
352
  `generation.failEstimate: 'failed' | 'no-cost'`.
266
- - **Where to read the reason:** `err.snapshot.error` — that is the diagnostic
267
- read, and recovering it is the whole point of the fix. It is
268
- **server-authored and unsanitised** (raw upstream text, including database
269
- constraint names, can reach it), so log it or show it in a developer-facing
270
- surface; don't render it as trusted copy.
271
- `err.message` is deliberately **generic** and names the code
272
- (`estimate did not return a usable price (no-cost) — reason on .snapshot.error`)
273
- because `message` is what an uncaught rejection prints and what an error
274
- reporter ships by default. Branch on `err.code`; print `err.message`; read
275
- `err.snapshot.error` when you are debugging.
353
+ - **Three fields, three audiences — and none of them is viewer-facing copy.**
354
+ The string a viewer sees is one **your app owns**; nothing on this error may
355
+ be rendered as-is.
356
+ - `err.code` (`'failed' | 'no-cost'`) — **the branch target**, and the only
357
+ stable one. Switch on it to pick your own localised message.
358
+ - `err.snapshot.error` — **the diagnostic read**, and recovering it is the
359
+ whole point of the fix. **Server-authored and unsanitised** (raw upstream
360
+ text, including database constraint names, can reach it): log it or show it
361
+ in a developer-facing surface, and **never render it verbatim into markup**.
362
+ - `err.message` — **developer-facing**. A generic constant naming only the code
363
+ (`estimate did not return a usable price (no-cost) — reason on .snapshot.error`),
364
+ because `message` is what an uncaught rejection prints and what an error
365
+ reporter ships by default. Safe to log and to let a stack trace print;
366
+ **not intended for display to viewers** — it names an internal field path,
367
+ it is not localised, and **its exact wording is not a contract**, so a UI
368
+ built on it silently rots. Two apps migrating to `0.43.0` piped it into
369
+ rendered UI and would have shipped that sentence to end users.
276
370
  - A cost of **`0` is a real price**, not a missing one (the orchestrator whatif
277
371
  prices a cache hit at 0). `estimate` resolves it; only a non-numeric
278
372
  `cost.total` rejects.
@@ -1 +1 @@
1
- {"version":3,"file":"useAppStorage.d.ts","sourceRoot":"","sources":["../../src/hooks/useAppStorage.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjD;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC7D;;;OAGG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAClC;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAyE7C"}
1
+ {"version":3,"file":"useAppStorage.d.ts","sourceRoot":"","sources":["../../src/hooks/useAppStorage.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjD;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC7D;;;OAGG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAClC;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAsF7C"}
@@ -35,15 +35,28 @@ export function useAppStorage() {
35
35
  },
36
36
  async set(key, value) {
37
37
  const result = await sendTypedRequest(transport, { type: 'APP_STORAGE_SET', payload: { key, value } }, 'APP_STORAGE_SET_RESULT');
38
- if (!result.ok || result.error) {
39
- throw new Error(result.error ?? 'storage set failed');
38
+ // A PRESENT `error` is the reject signal, not a TRUTHY one: the reply
39
+ // validator early-accepts anything carrying an `error` key, so
40
+ // `error: ''` reaches here having skipped the success-field checks.
41
+ // `||` (not `??`) so an empty error string still yields readable copy.
42
+ if (!result.ok || result.error !== undefined) {
43
+ throw new Error(result.error || 'storage set failed');
40
44
  }
41
45
  return { ok: true, sizeBytes: result.sizeBytes };
42
46
  },
43
47
  async delete(key) {
44
48
  const result = await sendTypedRequest(transport, { type: 'APP_STORAGE_DELETE', payload: { key } }, 'APP_STORAGE_DELETE_RESULT');
45
- if (!result.ok || result.error) {
46
- throw new Error(result.error ?? 'storage delete failed');
49
+ // PRESENT, not truthy — see `set()` above.
50
+ if (!result.ok || result.error !== undefined) {
51
+ throw new Error(result.error || 'storage delete failed');
52
+ }
53
+ // `deleted` is optional on the wire type because an error reply omits
54
+ // it. On the success path the validator requires a boolean, so this is
55
+ // defence in depth rather than a reachable branch through the real
56
+ // transport — but it is what makes the `boolean` we return honest,
57
+ // instead of a cast asserting a guarantee this function cannot see.
58
+ if (typeof result.deleted !== 'boolean') {
59
+ throw new Error('storage delete failed: reply carried no `deleted` flag');
47
60
  }
48
61
  return { ok: true, deleted: result.deleted };
49
62
  },
@@ -1 +1 @@
1
- {"version":3,"file":"useAppStorage.js","sourceRoot":"","sources":["../../src/hooks/useAppStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAppStorage.js","sourceRoot":"","sources":["../../src/hooks/useAppStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA6D5D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAgB,GAAG,EAAE;QACjC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,OAAO;YACL,KAAK,CAAC,GAAG,CAAc,GAAW;gBAChC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,SAAS,EACT,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,EAC7C,wBAAwB,CACzB,CAAC;gBACF,IAAI,MAAM,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChD,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAa,CAAC;YAC5C,CAAC;YACD,KAAK,CAAC,GAAG,CAAc,GAAW,EAAE,KAAQ;gBAC1C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,SAAS,EACT,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EACpD,wBAAwB,CACzB,CAAC;gBACF,sEAAsE;gBACtE,+DAA+D;gBAC/D,oEAAoE;gBACpE,uEAAuE;gBACvE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,oBAAoB,CAAC,CAAC;gBACxD,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;YAC5D,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,GAAW;gBACtB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,SAAS,EACT,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,EAChD,2BAA2B,CAC5B,CAAC;gBACF,2CAA2C;gBAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,uBAAuB,CAAC,CAAC;gBAC3D,CAAC;gBACD,sEAAsE;gBACtE,uEAAuE;gBACvE,mEAAmE;gBACnE,mEAAmE;gBACnE,oEAAoE;gBACpE,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBACxC,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;gBAC5E,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YACxD,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI;gBACb,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,SAAS,EACT;oBACE,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE;wBACP,MAAM,EAAE,IAAI,EAAE,MAAM;wBACpB,KAAK,EAAE,IAAI,EAAE,KAAK;wBAClB,MAAM,EAAE,IAAI,EAAE,MAAM;qBACrB;iBACF,EACD,yBAAyB,CAC1B,CAAC;gBACF,IAAI,MAAM,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChD,OAAO;oBACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC5B,GAAG,EAAE,CAAC,CAAC,GAAG;wBACV,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;qBACjC,CAAC,CAAC;oBACH,UAAU,EAAE,MAAM,CAAC,UAAU;iBAC9B,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,QAAQ;gBACZ,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC,SAAS,EACT,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,EAC1C,0BAA0B,CAC3B,CAAC;gBACF,IAAI,MAAM,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChD,OAAO;oBACL,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;iBAC5B,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC"}