@agora-sdk/secure-chat-core 0.7.0 → 0.8.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 (53) hide show
  1. package/dist/cjs/content/builders.d.ts +40 -0
  2. package/dist/cjs/content/builders.js +85 -0
  3. package/dist/cjs/content/builders.js.map +1 -0
  4. package/dist/cjs/content/cbor.d.ts +48 -0
  5. package/dist/cjs/content/cbor.js +298 -0
  6. package/dist/cjs/content/cbor.js.map +1 -0
  7. package/dist/cjs/content/frame.d.ts +24 -0
  8. package/dist/cjs/content/frame.js +39 -0
  9. package/dist/cjs/content/frame.js.map +1 -0
  10. package/dist/cjs/content/mimi-content.d.ts +194 -0
  11. package/dist/cjs/content/mimi-content.js +289 -0
  12. package/dist/cjs/content/mimi-content.js.map +1 -0
  13. package/dist/cjs/hooks/message-fold.d.ts +91 -0
  14. package/dist/cjs/hooks/message-fold.js +218 -0
  15. package/dist/cjs/hooks/message-fold.js.map +1 -0
  16. package/dist/cjs/hooks/useSecureMessages.d.ts +30 -18
  17. package/dist/cjs/hooks/useSecureMessages.js +190 -238
  18. package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
  19. package/dist/cjs/index.d.ts +7 -0
  20. package/dist/cjs/index.js +27 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/persistence/repository.d.ts +11 -11
  23. package/dist/cjs/persistence/repository.js +19 -19
  24. package/dist/cjs/persistence/repository.js.map +1 -1
  25. package/dist/cjs/version.d.ts +1 -1
  26. package/dist/cjs/version.js +1 -1
  27. package/dist/esm/content/builders.d.ts +40 -0
  28. package/dist/esm/content/builders.js +77 -0
  29. package/dist/esm/content/builders.js.map +1 -0
  30. package/dist/esm/content/cbor.d.ts +48 -0
  31. package/dist/esm/content/cbor.js +292 -0
  32. package/dist/esm/content/cbor.js.map +1 -0
  33. package/dist/esm/content/frame.d.ts +24 -0
  34. package/dist/esm/content/frame.js +34 -0
  35. package/dist/esm/content/frame.js.map +1 -0
  36. package/dist/esm/content/mimi-content.d.ts +194 -0
  37. package/dist/esm/content/mimi-content.js +283 -0
  38. package/dist/esm/content/mimi-content.js.map +1 -0
  39. package/dist/esm/hooks/message-fold.d.ts +91 -0
  40. package/dist/esm/hooks/message-fold.js +214 -0
  41. package/dist/esm/hooks/message-fold.js.map +1 -0
  42. package/dist/esm/hooks/useSecureMessages.d.ts +30 -18
  43. package/dist/esm/hooks/useSecureMessages.js +192 -240
  44. package/dist/esm/hooks/useSecureMessages.js.map +1 -1
  45. package/dist/esm/index.d.ts +7 -0
  46. package/dist/esm/index.js +6 -0
  47. package/dist/esm/index.js.map +1 -1
  48. package/dist/esm/persistence/repository.d.ts +11 -11
  49. package/dist/esm/persistence/repository.js +19 -19
  50. package/dist/esm/persistence/repository.js.map +1 -1
  51. package/dist/esm/version.d.ts +1 -1
  52. package/dist/esm/version.js +1 -1
  53. package/package.json +3 -2
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
- // useSecureMessages — load, decrypt, send, and live-receive messages in a secure conversation.
2
+ // useSecureMessages — load, decrypt, send, and live-receive MIMI-content messages in a secure conversation.
3
3
  //
4
- // Self-sufficient once a store is wired: the MLS GroupHandle is auto-resolved from persistence via
5
- // resolveGroup, and senderDeviceId is read from the persisted device. Both stay overridable through
6
- // options for advanced use. Without a resolvable handle, ciphertext is still listed/received
7
- // (plaintext: null) and sending is disabled.
4
+ // Content is the IETF MimiContent format (CBOR) inside a [kind][payload] routing frame inside the
5
+ // size-bucket padding frame all ABOVE the unchanged SecureChatCrypto seam (which still exchanges
6
+ // Uint8Array). The hook owns message-list STATE (dedup, ordering, decrypt-once, write-through) keyed by
7
+ // server messageId; a MessageFold collapses reaction/edit/delete/un-react messages onto their target by
8
+ // MIMI content-hash. The durable source of truth stays REST; realtime is a notification optimization.
8
9
  Object.defineProperty(exports, "__esModule", { value: true });
9
10
  exports.useSecureMessages = useSecureMessages;
10
11
  const react_1 = require("react");
@@ -13,36 +14,48 @@ const base64_js_1 = require("../util/base64.js");
13
14
  const padding_js_1 = require("../util/padding.js");
14
15
  const debug_js_1 = require("../util/debug.js");
15
16
  const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
17
+ const frame_js_1 = require("../content/frame.js");
18
+ const mimi_content_js_1 = require("../content/mimi-content.js");
19
+ const builders_js_1 = require("../content/builders.js");
20
+ const message_fold_js_1 = require("./message-fold.js");
16
21
  const log = (0, debug_js_1.createDebugLogger)("messages");
17
- /**
18
- * Merge two copies of the SAME message (same id) seen via different paths (REST load, retry, live
19
- * echo), keeping the more-resolved one. A row's status may only ever IMPROVE.
20
- *
21
- * This is load-bearing for E2EE correctness, not just de-dup hygiene: MLS application-message keys are
22
- * single-use (forward secrecy), so the ONE decrypt attempt that succeeds is the only one that ever
23
- * will — that attempt also *consumes* the key, so a later re-attempt necessarily fails. If a message
24
- * is loaded as `pending` (group not resolved yet) and then the live echo decrypts it `ok`, naively
25
- * "keep the first-seen row" would discard the only successful decryption and strand the message on
26
- * "waiting for key update" forever. So `ok` always wins; a failed re-attempt (`pending`/`rejected`)
27
- * must never overwrite an `ok`; otherwise keep the existing row (the retry effect handles `pending`).
28
- *
29
- * @param existing - The row already in state.
30
- * @param incoming - A freshly-produced row for the same message id.
31
- * @returns Whichever row is more resolved (`ok` \> anything; else `existing`).
32
- */
33
- function preferResolved(existing, incoming) {
34
- if (existing.status === "ok")
35
- return existing; // never downgrade a successful decrypt
36
- if (incoming.status === "ok")
37
- return incoming; // upgrade pending/rejected → ok
38
- return existing; // both unresolved: keep existing (a `pending` row is retried by the group effect)
22
+ const REJECT_MALFORMED = { status: "rejected", rejectedReason: "malformed" };
23
+ /** Decode a content-frame to a typed outcome. Pure; fails closed on any framing/schema error. */
24
+ function decodeFrame(frameBytes, model, senderDeviceId) {
25
+ let unf;
26
+ try {
27
+ unf = (0, frame_js_1.unframe)(frameBytes);
28
+ }
29
+ catch {
30
+ return REJECT_MALFORMED;
31
+ }
32
+ // kind 1 = IUC control (reserved; out of scope here): authenticate + hide, never render, never error.
33
+ if (unf.kind === frame_js_1.ContentKind.IucControl)
34
+ return { status: "ok", control: true };
35
+ if (unf.kind !== frame_js_1.ContentKind.Mimi)
36
+ return REJECT_MALFORMED;
37
+ let mimi;
38
+ try {
39
+ mimi = (0, mimi_content_js_1.decodeMimiContent)(unf.payload);
40
+ }
41
+ catch {
42
+ return REJECT_MALFORMED;
43
+ }
44
+ return {
45
+ status: "ok",
46
+ control: false,
47
+ decoded: {
48
+ messageId: model.id,
49
+ createdAt: model.createdAt,
50
+ senderDeviceId,
51
+ contentHash: (0, mimi_content_js_1.contentHash)(mimi),
52
+ mimi,
53
+ },
54
+ };
39
55
  }
56
+ const cmpStr = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
40
57
  /**
41
- * Load, decrypt, send, and live-receive messages in one secure conversation.
42
- *
43
- * Auto-resolves the MLS group handle (via `resolveGroup`) and the sender device id (from the
44
- * persisted device) unless overridden in `options`. Joins the conversation socket room for live
45
- * `secure:message` events.
58
+ * Load, decrypt, send, and live-receive MIMI-content messages in one secure conversation.
46
59
  *
47
60
  * @param conversationId - The conversation to read and send within.
48
61
  * @param options - {@link UseSecureMessagesOptions}.
@@ -50,82 +63,54 @@ function preferResolved(existing, incoming) {
50
63
  *
51
64
  * @example
52
65
  * ```tsx
53
- * const { messages, sendMessage } = useSecureMessages(conversationId);
66
+ * const { messages, sendMessage, react } = useSecureMessages(conversationId);
54
67
  * await sendMessage("hello 💜");
68
+ * await react(messages[0].contentHash!, "👍");
55
69
  * ```
56
70
  */
57
71
  function useSecureMessages(conversationId, options = {}) {
58
72
  const { rest, crypto, socket, repo, resolveGroup, persistGroupState, getGroupVersion, subscribeGroupChange, padding, } = (0, secure_chat_context_js_1.useSecureChat)();
59
- const [messages, setMessages] = (0, react_1.useState)([]);
60
73
  const [before, setBefore] = (0, react_1.useState)(undefined);
61
74
  const [hasMore, setHasMore] = (0, react_1.useState)(true);
62
75
  const [loading, setLoading] = (0, react_1.useState)(false);
63
76
  const [error, setError] = (0, react_1.useState)(null);
64
77
  const [group, setGroup] = (0, react_1.useState)(options.group ?? null);
65
78
  const [senderDeviceId, setSenderDeviceId] = (0, react_1.useState)(options.senderDeviceId);
66
- // Bumps when THIS conversation's group handle advances (a join or a processed Commit, driven by
67
- // useSecureHandshakes calling rememberGroup). Feeds the group-resolve effect's deps so we re-resolve
68
- // the now-current handle and flush buffered (plaintext:null) rows.
69
79
  const [groupVersion, setGroupVersion] = (0, react_1.useState)(0);
70
- // Latest messages, read by the "decrypt history once the group resolves" effect below without
71
- // making `messages` one of its deps (which would loop).
72
- const messagesRef = (0, react_1.useRef)(messages);
73
- messagesRef.current = messages;
74
- // `decrypt` reads the LIVE group through this ref, not its closure. A message page that finishes
75
- // loading AFTER the group resolves must decrypt with the now-current handle instead of stranding as
76
- // `pending` the load's closure may have captured `group` while it was still null.
80
+ // Rendered state lives in refs (the fold mutates target rows in place); `bump` forces a re-derive.
81
+ const byIdRef = (0, react_1.useRef)(new Map());
82
+ const foldRef = (0, react_1.useRef)(new message_fold_js_1.MessageFold());
83
+ // Decrypt-once cache by id: MLS application keys are single-use, so the one decrypt that succeeds is
84
+ // the only one that ever will. Survives StrictMode double-invokes and multi-effect decrypts.
85
+ const okCache = (0, react_1.useRef)(new Map());
86
+ const [version, bump] = (0, react_1.useReducer)((x) => x + 1, 0);
77
87
  const groupRef = (0, react_1.useRef)(group);
78
88
  groupRef.current = group;
79
- // Decrypt-once cache, by message id — the in-memory tier of a TWO-tier store. MLS application keys
80
- // are SINGLE-USE (forward secrecy): the one decrypt that succeeds consumes the key, so any later
81
- // attempt fails (`"Desired gen in the past"`). The hook decrypts the same message from several
82
- // effects (load, retry, live echo) and React StrictMode double-invokes them — so without this cache
83
- // the key could be consumed on a run whose `ok` result is then discarded, leaving the message
84
- // permanently un-decryptable. This cache covers within-session repeats; `decrypt` ALSO write-throughs
85
- // each `ok` to the durable plaintext store (repo.saveMessagePlaintext) so history survives reload
86
- // without ever replaying the consumed ratchet. Only `ok` is cached (terminal); `pending`/`rejected`
87
- // stay retryable. Ids are globally-unique server uuids, so this never needs clearing per-conversation.
88
- const okCache = (0, react_1.useRef)(new Map());
89
- // Subscribe to provider group-change signals; only a change to OUR conversation's version updates
90
- // state (React bails on an unchanged primitive), so unrelated conversations don't re-resolve us.
91
89
  (0, react_1.useEffect)(() => {
92
90
  return subscribeGroupChange(() => setGroupVersion(getGroupVersion(conversationId)));
93
91
  }, [subscribeGroupChange, getGroupVersion, conversationId]);
94
- // Resolve the group handle: explicit override, else persisted state.
92
+ // Resolve the group handle: explicit override, else persisted state. (Same as before.)
95
93
  (0, react_1.useEffect)(() => {
96
94
  if (options.group) {
97
95
  setGroup(options.group);
98
96
  return;
99
97
  }
100
- // Clear any stale handle from the previous conversation before re-resolving, so live messages
101
- // for the new conversation never decrypt against the old group during the async window.
102
98
  setGroup(null);
103
99
  let alive = true;
104
100
  resolveGroup(conversationId)
105
101
  .then((g) => {
106
- if (alive) {
102
+ if (alive)
107
103
  setGroup(g);
108
- log.debug("group handle set in messages hook", {
109
- conversationId,
110
- resolved: !!g,
111
- epoch: g?.epoch?.toString(),
112
- });
113
- }
114
104
  })
115
- .catch((err) => {
105
+ .catch(() => {
116
106
  if (alive)
117
107
  setGroup(null);
118
- log.debug("group resolve failed in messages hook", {
119
- conversationId,
120
- error: err instanceof Error ? err.message : String(err),
121
- });
122
108
  });
123
109
  return () => {
124
110
  alive = false;
125
111
  };
126
- // `groupVersion` re-runs this when a Commit/join advances the handle → flushes buffered rows.
127
112
  }, [options.group, conversationId, resolveGroup, groupVersion]);
128
- // Resolve the sender device id: explicit override, else persisted device row.
113
+ // Resolve the sender device id: explicit override, else persisted device row. (Same as before.)
129
114
  (0, react_1.useEffect)(() => {
130
115
  if (options.senderDeviceId) {
131
116
  setSenderDeviceId(options.senderDeviceId);
@@ -146,132 +131,127 @@ function useSecureMessages(conversationId, options = {}) {
146
131
  alive = false;
147
132
  };
148
133
  }, [options.senderDeviceId, repo]);
134
+ // Decrypt one message to a typed outcome. Two short-circuits BEFORE the single-use ratchet: the
135
+ // in-memory okCache and the durable content-frame store. A store/cache hit re-decodes locally and
136
+ // NEVER touches the ratchet (re-decrypting a consumed key throws "Desired gen in the past").
149
137
  const decrypt = (0, react_1.useCallback)(async (model) => {
150
- // Decrypt-once (in-memory tier): a message decoded earlier this session is returned from cache —
151
- // never re-run the MLS decrypt (its single-use key is already consumed; a second attempt fails).
152
138
  const cached = okCache.current.get(model.id);
153
139
  if (cached)
154
140
  return cached;
155
- // Decrypt-once (durable tier): a message decoded in a PRIOR session is served from the local
156
- // plaintext store. This is what makes history survive reload — the re-imported ratchet can't
157
- // reproduce a consumed key, so re-decrypting would throw "Desired gen in the past". A store hit
158
- // therefore must NOT touch the ratchet. (The blind server never sees this plaintext.)
159
- const stored = await repo.loadMessagePlaintext(conversationId, model.id);
160
- if (stored !== null) {
161
- const restored = { model, plaintext: stored, status: "ok" };
162
- okCache.current.set(model.id, restored);
163
- return restored;
164
- }
165
- // Read the LIVE group via the ref (not a stale closure): a load that finishes after the group
166
- // resolved must decrypt with the now-current handle, not the null it captured when it started.
167
- const group = groupRef.current;
168
- // No handle yet (still resolving) → retryable once it arrives.
169
- if (!group) {
170
- log.trace("decrypt deferred — no group handle yet", { messageId: model.id, epoch: model.epoch });
171
- return { model, plaintext: null, status: "pending" };
141
+ const storedFrame = await repo.loadMessageContent(conversationId, model.id);
142
+ if (storedFrame !== null) {
143
+ // The frame was already authenticated when first decrypted (and write-through only happens on an
144
+ // `ok` decrypt). The server-reported senderDeviceId is just a render label here; coalesce its
145
+ // possible null to "" so the fold's DecodedContentMessage stays a plain string.
146
+ const outcome = decodeFrame(storedFrame, model, model.senderDeviceId ?? "");
147
+ if (outcome.status === "ok")
148
+ okCache.current.set(model.id, outcome);
149
+ return outcome;
172
150
  }
151
+ const grp = groupRef.current;
152
+ if (!grp)
153
+ return { status: "pending" };
173
154
  let plaintext;
155
+ let sender;
174
156
  try {
175
- ({ plaintext } = await crypto.decryptMessage(group, (0, base64_js_1.fromBase64)(model.ciphertext)));
157
+ ({ plaintext, senderDeviceId: sender } = await crypto.decryptMessage(grp, (0, base64_js_1.fromBase64)(model.ciphertext)));
176
158
  }
177
159
  catch (err) {
178
- // Classify, don't conflate. A message from an epoch we HAVEN'T reached yet is legitimately
179
- // buffered (a future Commit will advance us, then this re-decrypts). Anything else that fails
180
- // at an epoch we HAVE reached is a terminal rejection — the MLS core refused it (replay,
181
- // over-window gap, bad auth, malformed, too-old epoch). Fail closed: never show it as text and
182
- // never silently retry it forever (the old behavior masked replays/forgeries as "pending").
183
- if (BigInt(model.epoch) > group.epoch) {
184
- log.debug("decrypt buffered — message epoch ahead of ours", {
185
- messageId: model.id,
186
- messageEpoch: model.epoch,
187
- groupEpoch: group.epoch.toString(),
188
- });
189
- return { model, plaintext: null, status: "pending" };
190
- }
160
+ if (BigInt(model.epoch) > grp.epoch)
161
+ return { status: "pending" }; // epoch ahead buffer
191
162
  const rejectedReason = err instanceof secure_chat_crypto_1.SecureChatDecryptError ? err.reason : "unknown";
192
- log.debug("decrypt rejected (fail closed)", {
193
- messageId: model.id,
194
- messageEpoch: model.epoch,
195
- groupEpoch: group.epoch.toString(),
196
- rejectedReason,
197
- });
198
- return { model, plaintext: null, status: "rejected", rejectedReason };
163
+ return { status: "rejected", rejectedReason };
199
164
  }
200
- // Decrypt + MLS authentication succeeded, so the bytes are from a real group member. Strip the
201
- // size-bucket padding frame (see util/padding). A bad frame here is NOT a decrypt failure — it's a
202
- // framing/version mismatch from an authenticated sender — so fail closed as "malformed" rather
203
- // than rendering raw padded bytes as text.
204
- let text;
165
+ let frameBytes;
205
166
  try {
206
- text = (0, base64_js_1.bytesToUtf8)((0, padding_js_1.unpadPlaintext)(plaintext));
167
+ frameBytes = (0, padding_js_1.unpadPlaintext)(plaintext); // authenticated sender, bad padding ⇒ malformed (fail closed)
207
168
  }
208
169
  catch {
209
- return { model, plaintext: null, status: "rejected", rejectedReason: "malformed" };
170
+ return REJECT_MALFORMED;
210
171
  }
211
- const ok = { model, plaintext: text, status: "ok" };
212
- okCache.current.set(model.id, ok); // cache the (single) successful decode for all later callers
213
- // Write-through to the durable store so this decode survives reload, and persist the now-advanced
214
- // RECEIVE ratchet: decrypt moved the group's generation in memory, so if we don't persist it a
215
- // reload rewinds the ratchet and the next send/receive desyncs. Persist plaintext FIRST if the
216
- // group-state write somehow fails, the message is still recoverable from the plaintext store.
217
- await repo.saveMessagePlaintext(conversationId, model.id, text);
218
- await persistGroupState(conversationId, group);
219
- return ok;
172
+ const outcome = decodeFrame(frameBytes, model, sender);
173
+ if (outcome.status === "ok") {
174
+ okCache.current.set(model.id, outcome);
175
+ // Write-through the raw content-frame bytes (re-decoded + re-folded on reload), then persist the
176
+ // advanced RECEIVE ratchet (decrypt moved the generation in memory; a reload must not rewind it).
177
+ await repo.saveMessageContent(conversationId, model.id, frameBytes);
178
+ await persistGroupState(conversationId, grp);
179
+ }
180
+ return outcome;
220
181
  }, [crypto, repo, conversationId, persistGroupState]);
182
+ // Fold one outcome into rendered state. `ok` is terminal (never downgraded — forward secrecy).
183
+ const ingest = (0, react_1.useCallback)((model, outcome) => {
184
+ const entries = byIdRef.current;
185
+ const prev = entries.get(model.id);
186
+ if (prev?.status === "ok")
187
+ return;
188
+ if (outcome.status === "ok") {
189
+ if (outcome.control) {
190
+ entries.set(model.id, { model, status: "ok", renderable: false });
191
+ }
192
+ else {
193
+ const { renderable } = foldRef.current.apply(outcome.decoded);
194
+ entries.set(model.id, { model, status: "ok", renderable, decoded: outcome.decoded });
195
+ }
196
+ }
197
+ else if (outcome.status === "pending") {
198
+ if (!prev)
199
+ entries.set(model.id, { model, status: "pending", renderable: false });
200
+ }
201
+ else {
202
+ if (!prev || prev.status === "pending")
203
+ entries.set(model.id, { model, status: "rejected", renderable: false, rejectedReason: outcome.rejectedReason });
204
+ }
205
+ bump();
206
+ }, []);
207
+ // Derive the rendered list: only renderable (post/reply) rows + non-ok rows, newest-first. Mutation
208
+ // and control rows are folded/hidden. Recomputed on every `bump` (fold mutates rows in place).
209
+ const messages = (0, react_1.useMemo)(() => {
210
+ const rows = [];
211
+ for (const e of byIdRef.current.values()) {
212
+ if (e.status === "ok") {
213
+ if (!e.renderable)
214
+ continue;
215
+ rows.push({
216
+ model: e.model,
217
+ content: foldRef.current.getContent(e.model.id),
218
+ mimi: e.decoded?.mimi ?? null,
219
+ contentHash: e.decoded?.contentHash ?? null,
220
+ status: "ok",
221
+ });
222
+ }
223
+ else {
224
+ rows.push({ model: e.model, content: null, mimi: null, contentHash: null, status: e.status, rejectedReason: e.rejectedReason });
225
+ }
226
+ }
227
+ rows.sort((a, b) => cmpStr(b.model.createdAt, a.model.createdAt) || cmpStr(b.model.id, a.model.id));
228
+ return rows;
229
+ // eslint-disable-next-line react-hooks/exhaustive-deps
230
+ }, [version]);
221
231
  const load = (0, react_1.useCallback)(async (reset) => {
222
232
  setLoading(true);
223
233
  setError(null);
224
234
  try {
225
- const page = await rest.listMessages(conversationId, {
226
- before: reset ? undefined : before,
227
- limit: 40,
228
- });
229
- const decrypted = await Promise.all(page.messages.map(decrypt));
235
+ const page = await rest.listMessages(conversationId, { before: reset ? undefined : before, limit: 40 });
236
+ if (reset) {
237
+ byIdRef.current.clear();
238
+ foldRef.current.reset();
239
+ }
230
240
  const oldest = page.messages[page.messages.length - 1];
231
241
  setBefore(oldest ? oldest.createdAt : before);
232
242
  setHasMore(page.hasMore);
233
- // Server returns created_at DESC; keep newest-first in state. Merge by id when appending an
234
- // older page: a row already in state (one that arrived live, or an overlap at the page
235
- // boundary) must not be appended twice (duplicate React key) — but if this page decrypted a row
236
- // we're still holding as `pending`, UPGRADE it in place rather than dropping the decode (same
237
- // forward-secrecy reasoning as the live path). `reset` replaces wholesale.
238
- setMessages((prev) => {
239
- if (reset)
240
- return decrypted;
241
- const indexById = new Map(prev.map((p, idx) => [p.model.id, idx]));
242
- const next = prev.slice();
243
- const appended = [];
244
- for (const m of decrypted) {
245
- const idx = indexById.get(m.model.id);
246
- if (idx === undefined)
247
- appended.push(m);
248
- else
249
- next[idx] = preferResolved(next[idx], m);
250
- }
251
- return [...next, ...appended];
252
- });
253
- log.debug("loaded message page", {
254
- conversationId,
255
- reset,
256
- before: reset ? undefined : before,
257
- count: decrypted.length,
258
- hasMore: page.hasMore,
259
- ok: decrypted.filter((m) => m.status === "ok").length,
260
- pending: decrypted.filter((m) => m.status === "pending").length,
261
- rejected: decrypted.filter((m) => m.status === "rejected").length,
262
- });
243
+ for (const model of page.messages)
244
+ ingest(model, await decrypt(model));
245
+ bump();
246
+ log.debug("loaded message page", { conversationId, reset, count: page.messages.length, hasMore: page.hasMore });
263
247
  }
264
248
  catch (err) {
265
- log.debug("load message page failed", {
266
- conversationId,
267
- error: err instanceof Error ? err.message : String(err),
268
- });
269
249
  setError(err);
270
250
  }
271
251
  finally {
272
252
  setLoading(false);
273
253
  }
274
- }, [rest, conversationId, before, decrypt]);
254
+ }, [rest, conversationId, before, decrypt, ingest]);
275
255
  const refresh = (0, react_1.useCallback)(async () => {
276
256
  setBefore(undefined);
277
257
  await load(true);
@@ -281,103 +261,75 @@ function useSecureMessages(conversationId, options = {}) {
281
261
  return;
282
262
  await load(false);
283
263
  }, [hasMore, loading, load]);
284
- const sendMessage = (0, react_1.useCallback)(async (text) => {
285
- // Assumes the crypto identity is already hydrated (mount `useSecureDevice` under the same
286
- // provider): the crypto layer tags the sender from the restored device identity, so after a
287
- // reload the first send must wait for useSecureDevice's importDeviceState to complete.
264
+ // Shared send: encode frame pad → encrypt → persist ratchet → POST → persist content → optimistic.
265
+ const sendContent = (0, react_1.useCallback)(async (mimi) => {
288
266
  if (!group)
289
267
  throw new Error("Cannot send: no MLS group handle for this conversation.");
290
268
  if (!senderDeviceId)
291
269
  throw new Error("Cannot send: senderDeviceId is required.");
292
- // Pad the plaintext to a size bucket BEFORE encryption so the ciphertext length leaks less
293
- // (the receiver strips the frame in `decrypt`). See util/padding for the framing.
294
- const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, padding_js_1.padPlaintext)((0, base64_js_1.utf8ToBytes)(text), padding));
295
- // The send ratchet just advanced in memory. Persist NOW — BEFORE the network send — because the
296
- // ratchet moved regardless of whether the send succeeds. If we skipped this, a reload would
297
- // re-import the last-committed state, rewind the send ratchet to a consumed generation, and the
298
- // peer would reject our next message as a replay (the exact bug this fixes). A failed network
299
- // send instead leaves at most a one-generation forward gap, which the peer tolerates within its
300
- // key-retention window — fail-safe-forward, never a replay.
270
+ const frame = (0, frame_js_1.frameContent)(frame_js_1.ContentKind.Mimi, (0, mimi_content_js_1.encodeMimiContent)(mimi));
271
+ const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, padding_js_1.padPlaintext)(frame, padding));
272
+ // Persist the advanced SEND ratchet BEFORE the network send (it moved regardless of success).
301
273
  await persistGroupState(conversationId, group);
302
274
  const sent = await rest.sendMessage(conversationId, {
303
275
  ciphertext: (0, base64_js_1.toBase64)(ciphertext),
304
276
  epoch: epoch.toString(),
305
277
  senderDeviceId,
306
278
  });
307
- // Persist our own plaintext: we can't re-decrypt our own single-use MLS message after reload (and
308
- // the server's echo of it self-rejects), so without this our own history would blank on reload.
309
- await repo.saveMessagePlaintext(conversationId, sent.id, text);
310
- log.debug("sent message", {
311
- conversationId,
312
- messageId: sent.id,
313
- epoch: epoch.toString(),
314
- senderDeviceId,
315
- });
316
- // Optimistic: we know our own plaintext without a round-trip through decrypt. Dedup by id while
317
- // prepending: the server echoes this same row back over `secure:message`, and a sender can't
318
- // decrypt their own MLS message, so that echo decrypts as `rejected`. If the echo wins the race
319
- // against this HTTP response it's already in `prev` drop it and keep this authoritative `ok`
320
- // copy, so the list never holds two rows with the same id (React duplicate-key) and the user
321
- // never sees their own message as `rejected`. (The live-receive path dedups the other ordering.)
322
- setMessages((prev) => [
323
- { model: sent, plaintext: text, status: "ok" },
324
- ...prev.filter((p) => p.model.id !== sent.id),
325
- ]);
326
- }, [crypto, rest, repo, conversationId, group, senderDeviceId, padding, persistGroupState]);
279
+ await repo.saveMessageContent(conversationId, sent.id, frame);
280
+ // Optimistic: we can't decrypt our own MLS message, so seed the decoded content directly and cache
281
+ // it so the server echo short-circuits (no rejected flicker).
282
+ const decoded = {
283
+ messageId: sent.id, createdAt: sent.createdAt, senderDeviceId, contentHash: (0, mimi_content_js_1.contentHash)(mimi), mimi,
284
+ };
285
+ const outcome = { status: "ok", control: false, decoded };
286
+ okCache.current.set(sent.id, outcome);
287
+ ingest(sent, outcome);
288
+ log.debug("sent content", { conversationId, messageId: sent.id, epoch: epoch.toString() });
289
+ }, [crypto, rest, repo, conversationId, group, senderDeviceId, padding, persistGroupState, ingest]);
290
+ const sendMessage = (0, react_1.useCallback)((text) => sendContent((0, builders_js_1.buildPost)(text)), [sendContent]);
291
+ const reply = (0, react_1.useCallback)((t, text) => sendContent((0, builders_js_1.buildReply)(text, t)), [sendContent]);
292
+ const react = (0, react_1.useCallback)((t, token) => sendContent((0, builders_js_1.buildReaction)(t, token)), [sendContent]);
293
+ const editMessage = (0, react_1.useCallback)((t, text) => sendContent((0, builders_js_1.buildEdit)(t, text)), [sendContent]);
294
+ const deleteMessage = (0, react_1.useCallback)((t) => sendContent((0, builders_js_1.buildDelete)(t)), [sendContent]);
295
+ const unreact = (0, react_1.useCallback)((reactionHash) => sendContent((0, builders_js_1.buildUnreact)(reactionHash)), [sendContent]);
327
296
  (0, react_1.useEffect)(() => {
328
297
  refresh();
329
298
  // eslint-disable-next-line react-hooks/exhaustive-deps
330
299
  }, [conversationId]);
331
- // Re-decrypt buffered rows when the group handle advances. On reload the first page loads while
332
- // resolveGroup is still in flight (those rows come back `pending`); a Commit/join also advances the
333
- // epoch, letting previously-ahead rows decrypt. Retry ONLY `pending` rows — never `rejected` ones, so
334
- // a replay/forgery the core already refused isn't retried on every epoch bump. `ok` rows are kept.
300
+ // Retry buffered (pending) rows when the group handle advances.
335
301
  (0, react_1.useEffect)(() => {
336
302
  if (!group)
337
303
  return;
338
- if (!messagesRef.current.some((m) => m.status === "pending"))
304
+ const pendingModels = [...byIdRef.current.values()].filter((e) => e.status === "pending").map((e) => e.model);
305
+ if (pendingModels.length === 0)
339
306
  return;
340
307
  let alive = true;
341
- Promise.all(messagesRef.current.map((m) => (m.status === "pending" ? decrypt(m.model) : Promise.resolve(m)))).then((next) => {
342
- if (alive)
343
- setMessages(next);
344
- });
308
+ (async () => {
309
+ for (const m of pendingModels) {
310
+ const outcome = await decrypt(m);
311
+ if (!alive)
312
+ return;
313
+ ingest(m, outcome);
314
+ }
315
+ })();
345
316
  return () => {
346
317
  alive = false;
347
318
  };
348
- }, [group, decrypt]);
349
- // Live receive: join the conversation room and decrypt inbound ciphertext.
319
+ }, [group, decrypt, ingest]);
320
+ // Live receive: join the conversation room and decrypt+ingest inbound ciphertext.
350
321
  (0, react_1.useEffect)(() => {
351
322
  socket.joinConversation(conversationId);
352
323
  const off = socket.on("secure:message", (model) => {
353
324
  if (model.conversationId !== conversationId)
354
325
  return;
355
- decrypt(model).then((m) => setMessages((prev) => {
356
- const i = prev.findIndex((p) => p.model.id === m.model.id);
357
- if (i === -1) {
358
- log.debug("live message received", {
359
- conversationId,
360
- messageId: m.model.id,
361
- status: m.status,
362
- });
363
- return [m, ...prev];
364
- }
365
- // Already present (e.g. loaded as `pending` before the group resolved): keep the more-resolved
366
- // copy in place — NEVER drop this `ok` for a stale `pending`. The decrypt above consumed the
367
- // single-use MLS key, so this may be the only successful decode the message ever gets.
368
- const merged = preferResolved(prev[i], m);
369
- if (merged === prev[i]) {
370
- log.trace("live message deduped (kept existing)", { messageId: m.model.id, status: prev[i].status });
371
- return prev;
372
- }
373
- log.debug("live message upgraded", { conversationId, messageId: m.model.id, status: merged.status });
374
- const next = prev.slice();
375
- next[i] = merged;
376
- return next;
377
- }));
326
+ decrypt(model).then((outcome) => ingest(model, outcome));
378
327
  });
379
328
  return off;
380
- }, [socket, conversationId, decrypt]);
381
- return { messages, loading, hasMore, error, loadMore, refresh, sendMessage };
329
+ }, [socket, conversationId, decrypt, ingest]);
330
+ return {
331
+ messages, loading, hasMore, error, loadMore, refresh,
332
+ sendMessage, reply, react, editMessage, deleteMessage, unreact,
333
+ };
382
334
  }
383
335
  //# sourceMappingURL=useSecureMessages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":";AAAA,4GAA4G;AAC5G,EAAE;AACF,kGAAkG;AAClG,mGAAmG;AACnG,wGAAwG;AACxG,wGAAwG;AACxG,sGAAsG;;AA2JtG,8CA8QC;AAvaD,iCAAsF;AAEtF,sEAIuC;AACvC,iDAAyD;AACzD,mDAAkE;AAClE,+CAAqD;AACrD,8EAAkE;AAClE,kDAAyE;AACzE,gEAEoC;AACpC,wDAEgC;AAChC,uDAE2B;AAE3B,MAAM,GAAG,GAAG,IAAA,4BAAiB,EAAC,UAAU,CAAC,CAAC;AAsE1C,MAAM,gBAAgB,GAAmB,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;AAE7F,iGAAiG;AACjG,SAAS,WAAW,CAClB,UAAsB,EACtB,KAAyB,EACzB,cAAsB;IAEtB,IAAI,GAA0C,CAAC;IAC/C,IAAI,CAAC;QACH,GAAG,GAAG,IAAA,kBAAO,EAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,sGAAsG;IACtG,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAW,CAAC,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAChF,IAAI,GAAG,CAAC,IAAI,KAAK,sBAAW,CAAC,IAAI;QAAE,OAAO,gBAAgB,CAAC;IAC3D,IAAI,IAAiB,CAAC;IACtB,IAAI,CAAC;QACH,IAAI,GAAG,IAAA,mCAAiB,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,KAAK;QACd,OAAO,EAAE;YACP,SAAS,EAAE,KAAK,CAAC,EAAE;YACnB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,cAAc;YACd,WAAW,EAAE,IAAA,6BAAW,EAAC,IAAI,CAAC;YAC9B,IAAI;SACL;KACF,CAAC;AACJ,CAAC;AAWD,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtE;;;;;;;;;;;;;GAaG;AACH,SAAgB,iBAAiB,CAC/B,cAAsB,EACtB,UAAoC,EAAE;IAEtC,MAAM,EACJ,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAC3D,eAAe,EAAE,oBAAoB,EAAE,OAAO,GAC/C,GAAG,IAAA,sCAAa,GAAE,CAAC;IAEpB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAqB,SAAS,CAAC,CAAC;IACpE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAU,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAqB,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,IAAA,gBAAQ,EAAqB,OAAO,CAAC,cAAc,CAAC,CAAC;IACjG,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IAEpD,mGAAmG;IACnG,MAAM,OAAO,GAAG,IAAA,cAAM,EAAC,IAAI,GAAG,EAAiB,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,IAAA,cAAM,EAAC,IAAI,6BAAW,EAAE,CAAC,CAAC;IAC1C,qGAAqG;IACrG,6FAA6F;IAC7F,MAAM,OAAO,GAAG,IAAA,cAAM,EAAC,IAAI,GAAG,EAA0B,CAAC,CAAC;IAC1D,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,IAAA,kBAAU,EAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,IAAA,cAAM,EAAqB,KAAK,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;IAEzB,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,oBAAoB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC,EAAE,CAAC,oBAAoB,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5D,uFAAuF;IACvF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,YAAY,CAAC,cAAc,CAAC;aACzB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,KAAK;gBAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,KAAK;gBAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAEhE,gGAAgG;IAChG,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI;aACD,UAAU,EAAE;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,KAAK;gBAAE,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,SAAS,CAAC,CAAC;QAC3D,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,KAAK;gBAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;IAEnC,gGAAgG;IAChG,kGAAkG;IAClG,6FAA6F;IAC7F,MAAM,OAAO,GAAG,IAAA,mBAAW,EACzB,KAAK,EAAE,KAAyB,EAA2B,EAAE;QAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5E,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,iGAAiG;YACjG,8FAA8F;YAC9F,gFAAgF;YAChF,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;YAC5E,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI;gBAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACpE,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACvC,IAAI,SAAqB,CAAC;QAC1B,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACH,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAA,sBAAU,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3G,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK;gBAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,uBAAuB;YAC1F,MAAM,cAAc,GAClB,GAAG,YAAY,2CAAsB,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACjE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;QAChD,CAAC;QACD,IAAI,UAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,UAAU,GAAG,IAAA,2BAAc,EAAC,SAAS,CAAC,CAAC,CAAC,8DAA8D;QACxG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACvD,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC5B,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACvC,iGAAiG;YACjG,kGAAkG;YAClG,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACpE,MAAM,iBAAiB,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,EACD,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAClD,CAAC;IAEF,+FAA+F;IAC/F,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,CAAC,KAAyB,EAAE,OAAuB,EAAE,EAAE;QAChF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,IAAI,EAAE,MAAM,KAAK,IAAI;YAAE,OAAO;QAClC,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,oGAAoG;IACpG,+FAA+F;IAC/F,MAAM,QAAQ,GAAG,IAAA,eAAO,EAA2B,GAAG,EAAE;QACtD,MAAM,IAAI,GAA6B,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACtB,IAAI,CAAC,CAAC,CAAC,UAAU;oBAAE,SAAS;gBAC5B,IAAI,CAAC,IAAI,CAAC;oBACR,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/C,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI;oBAC7B,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI;oBAC3C,MAAM,EAAE,IAAI;iBACb,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;YAClI,CAAC;QACH,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACpG,OAAO,IAAI,CAAC;QACZ,uDAAuD;IACzD,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,IAAI,GAAG,IAAA,mBAAW,EACtB,KAAK,EAAE,KAAc,EAAE,EAAE;QACvB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YACxG,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACxB,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1B,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvD,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9C,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ;gBAAE,MAAM,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YACvE,IAAI,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAClH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EACD,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAChD,CAAC;IAEF,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QACrC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,QAAQ,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,OAAO,IAAI,OAAO;YAAE,OAAO;QAChC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAE7B,uGAAuG;IACvG,MAAM,WAAW,GAAG,IAAA,mBAAW,EAC7B,KAAK,EAAE,IAAiB,EAAiB,EAAE;QACzC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACvF,IAAI,CAAC,cAAc;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,IAAA,uBAAY,EAAC,sBAAW,CAAC,IAAI,EAAE,IAAA,mCAAiB,EAAC,IAAI,CAAC,CAAC,CAAC;QACtE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,IAAA,yBAAY,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/F,8FAA8F;QAC9F,MAAM,iBAAiB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;YAClD,UAAU,EAAE,IAAA,oBAAQ,EAAC,UAAU,CAAC;YAChC,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;YACvB,cAAc;SACf,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9D,mGAAmG;QACnG,8DAA8D;QAC9D,MAAM,OAAO,GAA0B;YACrC,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,IAAA,6BAAW,EAAC,IAAI,CAAC,EAAE,IAAI;SACpG,CAAC;QACF,MAAM,OAAO,GAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC1E,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtB,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC,EACD,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAChG,CAAC;IAEF,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,uBAAS,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/F,MAAM,KAAK,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAa,EAAE,IAAY,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,wBAAU,EAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5G,MAAM,KAAK,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAa,EAAE,KAAa,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,2BAAa,EAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACjH,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAa,EAAE,IAAY,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,uBAAS,EAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACjH,MAAM,aAAa,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAa,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,yBAAW,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACjG,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,CAAC,YAAwB,EAAE,EAAE,CAAC,WAAW,CAAC,IAAA,0BAAY,EAAC,YAAY,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElH,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,EAAE,CAAC;QACV,uDAAuD;IACzD,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAErB,gEAAgE;IAChE,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,aAAa,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9G,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACvC,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,CAAC,KAAK,IAAI,EAAE;YACV,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;gBAC9B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;gBACjC,IAAI,CAAC,KAAK;oBAAE,OAAO;gBACnB,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7B,kFAAkF;IAClF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChD,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc;gBAAE,OAAO;YACpD,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE9C,OAAO;QACL,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO;QACpD,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO;KAC/D,CAAC;AACJ,CAAC"}