@agora-sdk/secure-chat-core 0.1.0 → 0.3.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 (64) hide show
  1. package/dist/cjs/context/secure-chat-context.d.ts +34 -18
  2. package/dist/cjs/context/secure-chat-context.js +78 -23
  3. package/dist/cjs/context/secure-chat-context.js.map +1 -1
  4. package/dist/cjs/contract/index.js +2 -2
  5. package/dist/cjs/contract/index.js.map +1 -1
  6. package/dist/cjs/hooks/useSecureConversations.d.ts +1 -1
  7. package/dist/cjs/hooks/useSecureConversations.js +9 -7
  8. package/dist/cjs/hooks/useSecureConversations.js.map +1 -1
  9. package/dist/cjs/hooks/useSecureDevice.d.ts +14 -13
  10. package/dist/cjs/hooks/useSecureDevice.js +58 -25
  11. package/dist/cjs/hooks/useSecureDevice.js.map +1 -1
  12. package/dist/cjs/hooks/useSecureHandshakes.d.ts +64 -0
  13. package/dist/cjs/hooks/useSecureHandshakes.js +215 -0
  14. package/dist/cjs/hooks/useSecureHandshakes.js.map +1 -0
  15. package/dist/cjs/hooks/useSecureMessages.d.ts +10 -11
  16. package/dist/cjs/hooks/useSecureMessages.js +99 -21
  17. package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
  18. package/dist/cjs/index.d.ts +20 -14
  19. package/dist/cjs/index.js +25 -19
  20. package/dist/cjs/index.js.map +1 -1
  21. package/dist/cjs/package.json +1 -0
  22. package/dist/cjs/persistence/memory-store.d.ts +9 -0
  23. package/dist/cjs/persistence/memory-store.js +27 -0
  24. package/dist/cjs/persistence/memory-store.js.map +1 -0
  25. package/dist/cjs/persistence/repository.d.ts +36 -0
  26. package/dist/cjs/persistence/repository.js +72 -0
  27. package/dist/cjs/persistence/repository.js.map +1 -0
  28. package/dist/cjs/persistence/store.d.ts +11 -0
  29. package/dist/cjs/persistence/store.js +8 -0
  30. package/dist/cjs/persistence/store.js.map +1 -0
  31. package/dist/cjs/transport/rest.d.ts +1 -1
  32. package/dist/cjs/transport/socket.d.ts +1 -1
  33. package/dist/esm/context/secure-chat-context.d.ts +34 -18
  34. package/dist/esm/context/secure-chat-context.js +77 -22
  35. package/dist/esm/context/secure-chat-context.js.map +1 -1
  36. package/dist/esm/contract/index.js +2 -2
  37. package/dist/esm/contract/index.js.map +1 -1
  38. package/dist/esm/hooks/useSecureConversations.d.ts +1 -1
  39. package/dist/esm/hooks/useSecureConversations.js +6 -4
  40. package/dist/esm/hooks/useSecureConversations.js.map +1 -1
  41. package/dist/esm/hooks/useSecureDevice.d.ts +14 -13
  42. package/dist/esm/hooks/useSecureDevice.js +55 -22
  43. package/dist/esm/hooks/useSecureDevice.js.map +1 -1
  44. package/dist/esm/hooks/useSecureHandshakes.d.ts +64 -0
  45. package/dist/esm/hooks/useSecureHandshakes.js +212 -0
  46. package/dist/esm/hooks/useSecureHandshakes.js.map +1 -0
  47. package/dist/esm/hooks/useSecureMessages.d.ts +10 -11
  48. package/dist/esm/hooks/useSecureMessages.js +96 -18
  49. package/dist/esm/hooks/useSecureMessages.js.map +1 -1
  50. package/dist/esm/index.d.ts +20 -14
  51. package/dist/esm/index.js +10 -7
  52. package/dist/esm/index.js.map +1 -1
  53. package/dist/esm/persistence/memory-store.d.ts +9 -0
  54. package/dist/esm/persistence/memory-store.js +23 -0
  55. package/dist/esm/persistence/memory-store.js.map +1 -0
  56. package/dist/esm/persistence/repository.d.ts +36 -0
  57. package/dist/esm/persistence/repository.js +68 -0
  58. package/dist/esm/persistence/repository.js.map +1 -0
  59. package/dist/esm/persistence/store.d.ts +11 -0
  60. package/dist/esm/persistence/store.js +7 -0
  61. package/dist/esm/persistence/store.js.map +1 -0
  62. package/dist/esm/transport/rest.d.ts +1 -1
  63. package/dist/esm/transport/socket.d.ts +1 -1
  64. package/package.json +3 -3
@@ -0,0 +1,64 @@
1
+ import { SecureHandshakeModel } from "../contract/index.js";
2
+ /** Options for {@link useSecureHandshakes}. */
3
+ export interface UseSecureHandshakesOptions {
4
+ /**
5
+ * The device row id whose inbox to drain. Defaults to the persisted device's `.id`. Pass the id
6
+ * from `useSecureDevice` so processing starts the moment the device registers (a persisted device
7
+ * is picked up automatically on reload even without this).
8
+ */
9
+ deviceId?: string;
10
+ /** Disable processing (e.g. before sign-in). Default true. */
11
+ enabled?: boolean;
12
+ /** Page size for the catch-up fetch loop. Default 100. */
13
+ pageSize?: number;
14
+ /** Called per handshake-processing error; the inbox skips the bad row and continues. */
15
+ onError?: (err: unknown, handshake?: SecureHandshakeModel) => void;
16
+ }
17
+ /** The state and actions returned by {@link useSecureHandshakes}. */
18
+ export interface UseSecureHandshakesValues {
19
+ /** True until the initial catch-up loop settles. */
20
+ catchingUp: boolean;
21
+ /** True once catch-up completed and live subscriptions are active. */
22
+ ready: boolean;
23
+ /** The last processed delivery cursor (`seq`), or `null`. */
24
+ cursor: string | null;
25
+ /** Count of handshakes applied this session. */
26
+ processedCount: number;
27
+ /** The last error surfaced (also delivered via `onError`), or `null`. */
28
+ error: unknown;
29
+ /**
30
+ * Re-run the catch-up loop from the persisted cursor. The reusable primitive a future 409
31
+ * epoch-conflict rebase (on a membership Commit) calls before rebuilding + retrying its Commit.
32
+ */
33
+ resync: () => Promise<void>;
34
+ }
35
+ /**
36
+ * Process this device's MLS handshake inbox so the recipient side of secure chat works.
37
+ *
38
+ * On mount (once a device id is available) it catches up via `fetchHandshakes(since=cursor)`, re-joins
39
+ * the socket rooms for groups it already holds, then processes live `secure:welcome` /
40
+ * `secure:handshake` events — all serialized in `seq` order, deduped, and cursor-persisted. Mount it
41
+ * exactly once near `useSecureDevice`.
42
+ *
43
+ * @param options - {@link UseSecureHandshakesOptions}.
44
+ * @returns {@link UseSecureHandshakesValues}.
45
+ *
46
+ * @remarks
47
+ * Single-device only (Phase 3 adds own-device fan-out + MLS generation-counter gap detection). A
48
+ * Commit for a group whose Welcome hasn't been seen is skipped — `seq` ordering puts the Welcome
49
+ * first, so an unknown group means this device is genuinely not a member.
50
+ *
51
+ * Mount it exactly once. Processing is serialized *within* a mount, and the cursor is re-read from
52
+ * storage at the start of each run, so a serialized re-mount (or `deviceId` change) resumes without
53
+ * reprocessing. It does NOT serialize across a *concurrent* re-mount whose prior catch-up is still
54
+ * in flight; that case relies on `processWelcome` / `processCommit` being idempotent for a replayed
55
+ * blob. The mock is idempotent (so dev StrictMode double-invoke is harmless); harden this when the
56
+ * real MLS core lands (Task 1) if its handshake processing is not replay-safe.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * const { device } = useSecureDevice();
61
+ * useSecureHandshakes({ deviceId: device?.id });
62
+ * ```
63
+ */
64
+ export declare function useSecureHandshakes(options?: UseSecureHandshakesOptions): UseSecureHandshakesValues;
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ // useSecureHandshakes — drain and process this device's MLS handshake inbox (the recipient side).
3
+ //
4
+ // The blind DS delivers each device a stream of handshakes (Welcomes targeted at it, plus broadcast
5
+ // Commits/Proposals for its groups), ordered by a monotonic `seq`. This hook is what makes a
6
+ // RECIPIENT actually join and stay current: on connect it pulls `GET .../handshakes?since=<cursor>`
7
+ // to the end, then processes live `secure:welcome` / `secure:handshake` events — all funneled through
8
+ // ONE serialized, seq-ordered, idempotent path, persisting the cursor as it goes. A processed Welcome
9
+ // joins a group (rememberGroup); a processed Commit advances its epoch. Mount it once, near
10
+ // useSecureDevice.
11
+ //
12
+ // Ordering invariant: live events that arrive WHILE catching up are buffered and replayed in `seq`
13
+ // order AFTER catch-up — otherwise a high-seq live event would advance the cursor past not-yet-fetched
14
+ // rows and the dedupe check would drop them (data loss).
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.useSecureHandshakes = useSecureHandshakes;
17
+ const react_1 = require("react");
18
+ const base64_js_1 = require("../util/base64.js");
19
+ const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
20
+ /** Compare two decimal-string `seq` cursors numerically (string compare is wrong across digit widths). */
21
+ function compareSeq(a, b) {
22
+ const d = BigInt(a) - BigInt(b);
23
+ return d > 0n ? 1 : d < 0n ? -1 : 0;
24
+ }
25
+ /**
26
+ * Process this device's MLS handshake inbox so the recipient side of secure chat works.
27
+ *
28
+ * On mount (once a device id is available) it catches up via `fetchHandshakes(since=cursor)`, re-joins
29
+ * the socket rooms for groups it already holds, then processes live `secure:welcome` /
30
+ * `secure:handshake` events — all serialized in `seq` order, deduped, and cursor-persisted. Mount it
31
+ * exactly once near `useSecureDevice`.
32
+ *
33
+ * @param options - {@link UseSecureHandshakesOptions}.
34
+ * @returns {@link UseSecureHandshakesValues}.
35
+ *
36
+ * @remarks
37
+ * Single-device only (Phase 3 adds own-device fan-out + MLS generation-counter gap detection). A
38
+ * Commit for a group whose Welcome hasn't been seen is skipped — `seq` ordering puts the Welcome
39
+ * first, so an unknown group means this device is genuinely not a member.
40
+ *
41
+ * Mount it exactly once. Processing is serialized *within* a mount, and the cursor is re-read from
42
+ * storage at the start of each run, so a serialized re-mount (or `deviceId` change) resumes without
43
+ * reprocessing. It does NOT serialize across a *concurrent* re-mount whose prior catch-up is still
44
+ * in flight; that case relies on `processWelcome` / `processCommit` being idempotent for a replayed
45
+ * blob. The mock is idempotent (so dev StrictMode double-invoke is harmless); harden this when the
46
+ * real MLS core lands (Task 1) if its handshake processing is not replay-safe.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * const { device } = useSecureDevice();
51
+ * useSecureHandshakes({ deviceId: device?.id });
52
+ * ```
53
+ */
54
+ function useSecureHandshakes(options = {}) {
55
+ const { rest, crypto, socket, repo, resolveGroup, rememberGroup } = (0, secure_chat_context_js_1.useSecureChat)();
56
+ const { deviceId: deviceIdOption, pageSize = 100 } = options;
57
+ const enabled = options.enabled ?? true;
58
+ const [catchingUp, setCatchingUp] = (0, react_1.useState)(true);
59
+ const [ready, setReady] = (0, react_1.useState)(false);
60
+ const [cursor, setCursor] = (0, react_1.useState)(null);
61
+ const [processedCount, setProcessedCount] = (0, react_1.useState)(0);
62
+ const [error, setError] = (0, react_1.useState)(null);
63
+ // onError read through a ref so passing an inline callback doesn't re-run the effect.
64
+ const onErrorRef = (0, react_1.useRef)(options.onError);
65
+ onErrorRef.current = options.onError;
66
+ // The catch-up routine, published from the effect so `resync()` (stable) can invoke it.
67
+ const runCatchUpRef = (0, react_1.useRef)(null);
68
+ const resync = (0, react_1.useCallback)(async () => {
69
+ await runCatchUpRef.current?.();
70
+ }, []);
71
+ (0, react_1.useEffect)(() => {
72
+ if (!enabled)
73
+ return;
74
+ let alive = true;
75
+ const offFns = [];
76
+ // Async state shared across the catch-up loop, live handlers, and the serial apply queue.
77
+ const cursorRef = { current: null };
78
+ const catchingUpRef = { current: true };
79
+ const liveBuffer = [];
80
+ let queue = Promise.resolve();
81
+ let deviceId;
82
+ const report = (err, h) => {
83
+ if (alive)
84
+ setError(err);
85
+ onErrorRef.current?.(err, h);
86
+ };
87
+ const dispatchByKind = async (h) => {
88
+ const payload = (0, base64_js_1.fromBase64)(h.payload);
89
+ if (h.kind === "welcome") {
90
+ // Targeted at us → join the group, then join its room for future broadcast Commits.
91
+ if (h.targetDeviceId && h.targetDeviceId !== deviceId)
92
+ return;
93
+ const handle = await crypto.processWelcome(payload);
94
+ await rememberGroup(h.conversationId, handle);
95
+ socket.joinConversation(h.conversationId);
96
+ }
97
+ else if (h.kind === "commit") {
98
+ const group = await resolveGroup(h.conversationId);
99
+ if (!group) {
100
+ // Unknown group at a Commit: with seq ordering the Welcome precedes it, so we're not a
101
+ // member of this conversation. Skip (the cursor still advances so we don't re-fetch it).
102
+ report(new Error(`secure-chat: commit for unknown group ${h.conversationId}`), h);
103
+ return;
104
+ }
105
+ const advanced = await crypto.processCommit(group, payload);
106
+ await rememberGroup(h.conversationId, advanced);
107
+ }
108
+ else if (h.kind === "proposal") {
109
+ const group = await resolveGroup(h.conversationId);
110
+ if (group)
111
+ await crypto.processProposal(group, payload);
112
+ }
113
+ };
114
+ // The ONE place that mutates the cursor + crypto state. Dedupes by seq; advances the cursor even
115
+ // when a row is skipped or its dispatch throws, so a poison blob can never wedge the inbox. A hard
116
+ // crash mid-dispatch leaves the cursor unsaved, so the row replays on restart (no loss).
117
+ const applyOrdered = async (h) => {
118
+ if (cursorRef.current !== null && compareSeq(h.seq, cursorRef.current) <= 0)
119
+ return;
120
+ try {
121
+ await dispatchByKind(h);
122
+ }
123
+ catch (err) {
124
+ report(err, h);
125
+ }
126
+ cursorRef.current = h.seq;
127
+ await repo.saveHandshakeCursor(h.seq);
128
+ if (alive) {
129
+ setCursor(h.seq);
130
+ setProcessedCount((n) => n + 1);
131
+ }
132
+ };
133
+ const schedule = (h) => {
134
+ queue = queue.then(() => applyOrdered(h));
135
+ return queue;
136
+ };
137
+ const enqueueLive = (h) => {
138
+ // Buffer while catching up so a high-seq live event can't advance the cursor past rows the
139
+ // catch-up loop hasn't fetched yet (which the dedupe check would then drop).
140
+ if (catchingUpRef.current)
141
+ liveBuffer.push(h);
142
+ else
143
+ schedule(h);
144
+ };
145
+ // Coalesce overlapping invocations: a `resync()` fired while a catch-up is still draining returns
146
+ // the in-flight promise instead of starting a second drain (two drains would race the
147
+ // `catchingUpRef` gate + `liveBuffer` and could break seq ordering).
148
+ let catchUpInFlight = null;
149
+ const runCatchUp = () => {
150
+ if (catchUpInFlight)
151
+ return catchUpInFlight;
152
+ catchUpInFlight = (async () => {
153
+ catchingUpRef.current = true;
154
+ try {
155
+ for (;;) {
156
+ const page = await rest.fetchHandshakes(deviceId, {
157
+ since: cursorRef.current ?? undefined,
158
+ limit: pageSize,
159
+ });
160
+ for (const h of page.handshakes)
161
+ await schedule(h);
162
+ if (!page.hasMore)
163
+ break;
164
+ }
165
+ }
166
+ finally {
167
+ catchingUpRef.current = false;
168
+ // Replay anything that landed live during catch-up, in seq order, through the same queue.
169
+ const buffered = liveBuffer.splice(0).sort((a, b) => compareSeq(a.seq, b.seq));
170
+ for (const h of buffered)
171
+ schedule(h);
172
+ }
173
+ })().finally(() => {
174
+ catchUpInFlight = null;
175
+ });
176
+ return catchUpInFlight;
177
+ };
178
+ (async () => {
179
+ // Resolve the device row id (option wins; else the persisted device). Without one, there is no
180
+ // inbox to drain yet — the effect re-runs when `deviceId` is later supplied.
181
+ deviceId = deviceIdOption ?? (await repo.loadDevice())?.device?.id;
182
+ if (!alive || !deviceId)
183
+ return;
184
+ cursorRef.current = await repo.loadHandshakeCursor();
185
+ if (alive)
186
+ setCursor(cursorRef.current);
187
+ // Subscribe to live events BEFORE catch-up (buffered until catch-up completes).
188
+ offFns.push(socket.on("secure:welcome", enqueueLive));
189
+ offFns.push(socket.on("secure:handshake", enqueueLive));
190
+ runCatchUpRef.current = runCatchUp;
191
+ await runCatchUp();
192
+ // After a reload we hold group state but haven't joined the socket rooms, so broadcast Commits
193
+ // wouldn't arrive — re-join every known conversation.
194
+ try {
195
+ const convIds = await repo.listGroupConversationIds();
196
+ for (const c of convIds)
197
+ socket.joinConversation(c);
198
+ }
199
+ catch (err) {
200
+ report(err);
201
+ }
202
+ if (alive) {
203
+ setCatchingUp(false);
204
+ setReady(true);
205
+ }
206
+ })().catch((err) => report(err));
207
+ return () => {
208
+ alive = false;
209
+ offFns.forEach((off) => off());
210
+ runCatchUpRef.current = null;
211
+ };
212
+ }, [enabled, deviceIdOption, pageSize, rest, socket, repo, crypto, resolveGroup, rememberGroup]);
213
+ return { catchingUp, ready, cursor, processedCount, error, resync };
214
+ }
215
+ //# sourceMappingURL=useSecureHandshakes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSecureHandshakes.js","sourceRoot":"","sources":["../../../src/hooks/useSecureHandshakes.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { SecureMessageModel } from "../contract";
1
+ import { SecureMessageModel } from "../contract/index.js";
2
2
  import { GroupHandle } from "@agora-sdk/secure-chat-crypto";
3
3
  /** A stored message paired with its decrypted text (when a group handle is available). */
4
4
  export interface DecryptedSecureMessage {
@@ -9,9 +9,9 @@ export interface DecryptedSecureMessage {
9
9
  }
10
10
  /** Options for {@link useSecureMessages}. */
11
11
  export interface UseSecureMessagesOptions {
12
- /** The MLS group handle for this conversation (from the platform persistence layer). */
12
+ /** Override the MLS group handle. Defaults to the persisted handle via `resolveGroup`. */
13
13
  group?: GroupHandle;
14
- /** The caller's device row id required to send (the server verifies it belongs to the caller). */
14
+ /** Override the sender device row id. Defaults to the persisted device's `.id`. */
15
15
  senderDeviceId?: string;
16
16
  }
17
17
  /** The state and actions returned by {@link useSecureMessages}. */
@@ -28,24 +28,23 @@ export interface UseSecureMessagesValues {
28
28
  loadMore: () => Promise<void>;
29
29
  /** Reload from the newest message, replacing the current list. */
30
30
  refresh: () => Promise<void>;
31
- /** Encrypt + send a text message. Requires `group` + `senderDeviceId`. */
31
+ /** Encrypt + send a text message. Requires a resolvable group + sender device. */
32
32
  sendMessage: (text: string) => Promise<void>;
33
33
  }
34
34
  /**
35
35
  * Load, decrypt, send, and live-receive messages in one secure conversation.
36
36
  *
37
- * Decryption runs through the injected `SecureChatCrypto` against the conversation's MLS
38
- * `GroupHandle`. Without a `group` in `options`, ciphertext is still listed and received (as
39
- * `plaintext: null`) and sending is disabled — letting the transport work ahead of the crypto
40
- * wiring. Joins the conversation's socket room to receive `secure:message` events live.
37
+ * Auto-resolves the MLS group handle (via `resolveGroup`) and the sender device id (from the
38
+ * persisted device) unless overridden in `options`. Joins the conversation socket room for live
39
+ * `secure:message` events.
41
40
  *
42
41
  * @param conversationId - The conversation to read and send within.
43
- * @param options - {@link UseSecureMessagesOptions} — the MLS `group` handle and `senderDeviceId`.
44
- * @returns {@link UseSecureMessagesValues} — the message list, paging state, and `sendMessage`.
42
+ * @param options - {@link UseSecureMessagesOptions}.
43
+ * @returns {@link UseSecureMessagesValues}.
45
44
  *
46
45
  * @example
47
46
  * ```tsx
48
- * const { messages, sendMessage } = useSecureMessages(conversationId, { group, senderDeviceId });
47
+ * const { messages, sendMessage } = useSecureMessages(conversationId);
49
48
  * await sendMessage("hello 💜");
50
49
  * ```
51
50
  */
@@ -1,48 +1,105 @@
1
1
  "use strict";
2
2
  // useSecureMessages — load, decrypt, send, and live-receive messages in a secure conversation.
3
3
  //
4
- // Encryption/decryption runs through the injected `SecureChatCrypto` against the conversation's MLS
5
- // `GroupHandle`. Resolving conversationId → GroupHandle is owned by the platform persistence layer
6
- // (Phase 2: IndexedDB group state via processWelcome/importGroupState), so the caller passes the
7
- // handle in. Without it, ciphertext is still listed/received but left undecrypted (`plaintext: null`)
8
- // and sending is disabled — keeping the transport usable ahead of the crypto wiring.
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.
9
8
  Object.defineProperty(exports, "__esModule", { value: true });
10
9
  exports.useSecureMessages = useSecureMessages;
11
10
  const react_1 = require("react");
12
- const base64_1 = require("../util/base64");
13
- const secure_chat_context_1 = require("../context/secure-chat-context");
11
+ const base64_js_1 = require("../util/base64.js");
12
+ const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
14
13
  /**
15
14
  * Load, decrypt, send, and live-receive messages in one secure conversation.
16
15
  *
17
- * Decryption runs through the injected `SecureChatCrypto` against the conversation's MLS
18
- * `GroupHandle`. Without a `group` in `options`, ciphertext is still listed and received (as
19
- * `plaintext: null`) and sending is disabled — letting the transport work ahead of the crypto
20
- * wiring. Joins the conversation's socket room to receive `secure:message` events live.
16
+ * Auto-resolves the MLS group handle (via `resolveGroup`) and the sender device id (from the
17
+ * persisted device) unless overridden in `options`. Joins the conversation socket room for live
18
+ * `secure:message` events.
21
19
  *
22
20
  * @param conversationId - The conversation to read and send within.
23
- * @param options - {@link UseSecureMessagesOptions} — the MLS `group` handle and `senderDeviceId`.
24
- * @returns {@link UseSecureMessagesValues} — the message list, paging state, and `sendMessage`.
21
+ * @param options - {@link UseSecureMessagesOptions}.
22
+ * @returns {@link UseSecureMessagesValues}.
25
23
  *
26
24
  * @example
27
25
  * ```tsx
28
- * const { messages, sendMessage } = useSecureMessages(conversationId, { group, senderDeviceId });
26
+ * const { messages, sendMessage } = useSecureMessages(conversationId);
29
27
  * await sendMessage("hello 💜");
30
28
  * ```
31
29
  */
32
30
  function useSecureMessages(conversationId, options = {}) {
33
- const { rest, crypto, socket } = (0, secure_chat_context_1.useSecureChat)();
34
- const { group, senderDeviceId } = options;
31
+ const { rest, crypto, socket, repo, resolveGroup, getGroupVersion, subscribeGroupChange } = (0, secure_chat_context_js_1.useSecureChat)();
35
32
  const [messages, setMessages] = (0, react_1.useState)([]);
36
33
  const [before, setBefore] = (0, react_1.useState)(undefined);
37
34
  const [hasMore, setHasMore] = (0, react_1.useState)(true);
38
35
  const [loading, setLoading] = (0, react_1.useState)(false);
39
36
  const [error, setError] = (0, react_1.useState)(null);
37
+ const [group, setGroup] = (0, react_1.useState)(options.group ?? null);
38
+ const [senderDeviceId, setSenderDeviceId] = (0, react_1.useState)(options.senderDeviceId);
39
+ // Bumps when THIS conversation's group handle advances (a join or a processed Commit, driven by
40
+ // useSecureHandshakes calling rememberGroup). Feeds the group-resolve effect's deps so we re-resolve
41
+ // the now-current handle and flush buffered (plaintext:null) rows.
42
+ const [groupVersion, setGroupVersion] = (0, react_1.useState)(0);
43
+ // Latest messages, read by the "decrypt history once the group resolves" effect below without
44
+ // making `messages` one of its deps (which would loop).
45
+ const messagesRef = (0, react_1.useRef)(messages);
46
+ messagesRef.current = messages;
47
+ // Subscribe to provider group-change signals; only a change to OUR conversation's version updates
48
+ // state (React bails on an unchanged primitive), so unrelated conversations don't re-resolve us.
49
+ (0, react_1.useEffect)(() => {
50
+ return subscribeGroupChange(() => setGroupVersion(getGroupVersion(conversationId)));
51
+ }, [subscribeGroupChange, getGroupVersion, conversationId]);
52
+ // Resolve the group handle: explicit override, else persisted state.
53
+ (0, react_1.useEffect)(() => {
54
+ if (options.group) {
55
+ setGroup(options.group);
56
+ return;
57
+ }
58
+ // Clear any stale handle from the previous conversation before re-resolving, so live messages
59
+ // for the new conversation never decrypt against the old group during the async window.
60
+ setGroup(null);
61
+ let alive = true;
62
+ resolveGroup(conversationId)
63
+ .then((g) => {
64
+ if (alive)
65
+ setGroup(g);
66
+ })
67
+ .catch(() => {
68
+ if (alive)
69
+ setGroup(null);
70
+ });
71
+ return () => {
72
+ alive = false;
73
+ };
74
+ // `groupVersion` re-runs this when a Commit/join advances the handle → flushes buffered rows.
75
+ }, [options.group, conversationId, resolveGroup, groupVersion]);
76
+ // Resolve the sender device id: explicit override, else persisted device row.
77
+ (0, react_1.useEffect)(() => {
78
+ if (options.senderDeviceId) {
79
+ setSenderDeviceId(options.senderDeviceId);
80
+ return;
81
+ }
82
+ let alive = true;
83
+ repo
84
+ .loadDevice()
85
+ .then((d) => {
86
+ if (alive)
87
+ setSenderDeviceId(d?.device?.id ?? undefined);
88
+ })
89
+ .catch(() => {
90
+ if (alive)
91
+ setSenderDeviceId(undefined);
92
+ });
93
+ return () => {
94
+ alive = false;
95
+ };
96
+ }, [options.senderDeviceId, repo]);
40
97
  const decrypt = (0, react_1.useCallback)(async (model) => {
41
98
  if (!group)
42
99
  return { model, plaintext: null };
43
100
  try {
44
- const { plaintext } = await crypto.decryptMessage(group, (0, base64_1.fromBase64)(model.ciphertext));
45
- return { model, plaintext: (0, base64_1.bytesToUtf8)(plaintext) };
101
+ const { plaintext } = await crypto.decryptMessage(group, (0, base64_js_1.fromBase64)(model.ciphertext));
102
+ return { model, plaintext: (0, base64_js_1.bytesToUtf8)(plaintext) };
46
103
  }
47
104
  catch {
48
105
  // Buffer/skip: epoch not yet reached, or undecryptable. Surface ciphertext without text.
@@ -81,13 +138,16 @@ function useSecureMessages(conversationId, options = {}) {
81
138
  await load(false);
82
139
  }, [hasMore, loading, load]);
83
140
  const sendMessage = (0, react_1.useCallback)(async (text) => {
141
+ // Assumes the crypto identity is already hydrated (mount `useSecureDevice` under the same
142
+ // provider): the crypto layer tags the sender from the restored device identity, so after a
143
+ // reload the first send must wait for useSecureDevice's importDeviceState to complete.
84
144
  if (!group)
85
145
  throw new Error("Cannot send: no MLS group handle for this conversation.");
86
146
  if (!senderDeviceId)
87
147
  throw new Error("Cannot send: senderDeviceId is required.");
88
- const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, base64_1.utf8ToBytes)(text));
148
+ const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, base64_js_1.utf8ToBytes)(text));
89
149
  const sent = await rest.sendMessage(conversationId, {
90
- ciphertext: (0, base64_1.toBase64)(ciphertext),
150
+ ciphertext: (0, base64_js_1.toBase64)(ciphertext),
91
151
  epoch: epoch.toString(),
92
152
  senderDeviceId,
93
153
  });
@@ -98,13 +158,31 @@ function useSecureMessages(conversationId, options = {}) {
98
158
  refresh();
99
159
  // eslint-disable-next-line react-hooks/exhaustive-deps
100
160
  }, [conversationId]);
161
+ // Decrypt history that was listed before the group handle resolved. On reload, the first page loads
162
+ // while resolveGroup is still in flight, so those rows come back `plaintext: null`; once the handle
163
+ // arrives (decrypt is recreated with it), re-decrypt the still-undecrypted rows in place — no
164
+ // re-fetch, scroll/pagination preserved.
165
+ (0, react_1.useEffect)(() => {
166
+ if (!group)
167
+ return;
168
+ if (!messagesRef.current.some((m) => m.plaintext === null))
169
+ return;
170
+ let alive = true;
171
+ Promise.all(messagesRef.current.map((m) => (m.plaintext === null ? decrypt(m.model) : Promise.resolve(m)))).then((next) => {
172
+ if (alive)
173
+ setMessages(next);
174
+ });
175
+ return () => {
176
+ alive = false;
177
+ };
178
+ }, [group, decrypt]);
101
179
  // Live receive: join the conversation room and decrypt inbound ciphertext.
102
180
  (0, react_1.useEffect)(() => {
103
181
  socket.joinConversation(conversationId);
104
182
  const off = socket.on("secure:message", (model) => {
105
183
  if (model.conversationId !== conversationId)
106
184
  return;
107
- decrypt(model).then((m) => setMessages((prev) => prev.some((p) => p.model.id === m.model.id) ? prev : [m, ...prev]));
185
+ decrypt(model).then((m) => setMessages((prev) => (prev.some((p) => p.model.id === m.model.id) ? prev : [m, ...prev])));
108
186
  });
109
187
  return off;
110
188
  }, [socket, conversationId, decrypt]);
@@ -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":"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"}
@@ -1,15 +1,21 @@
1
- export { SecureChatProvider, useSecureChat } from "./context/secure-chat-context";
2
- export type { SecureChatProviderProps, SecureChatContextValue, } from "./context/secure-chat-context";
3
- export { useSecureDevice } from "./hooks/useSecureDevice";
4
- export type { UseSecureDeviceOptions, UseSecureDeviceValues } from "./hooks/useSecureDevice";
5
- export { useSecureConversations } from "./hooks/useSecureConversations";
6
- export type { UseSecureConversationsValues } from "./hooks/useSecureConversations";
7
- export { useSecureMessages } from "./hooks/useSecureMessages";
8
- export type { UseSecureMessagesOptions, UseSecureMessagesValues, DecryptedSecureMessage, } from "./hooks/useSecureMessages";
9
- export { SecureChatRestClient } from "./transport/rest";
10
- export type { SecureChatRestConfig } from "./transport/rest";
11
- export { SecureChatSocketClient } from "./transport/socket";
12
- export type { SecureSocket, SecureServerEvents, SecureClientEvents, SecureChatSocketConfig, } from "./transport/socket";
1
+ export { SecureChatProvider, useSecureChat } from "./context/secure-chat-context.js";
2
+ export type { SecureChatProviderProps, SecureChatContextValue, } from "./context/secure-chat-context.js";
3
+ export { useSecureDevice } from "./hooks/useSecureDevice.js";
4
+ export type { UseSecureDeviceOptions, UseSecureDeviceValues } from "./hooks/useSecureDevice.js";
5
+ export { useSecureConversations } from "./hooks/useSecureConversations.js";
6
+ export type { UseSecureConversationsValues } from "./hooks/useSecureConversations.js";
7
+ export { useSecureMessages } from "./hooks/useSecureMessages.js";
8
+ export type { UseSecureMessagesOptions, UseSecureMessagesValues, DecryptedSecureMessage, } from "./hooks/useSecureMessages.js";
9
+ export { useSecureHandshakes } from "./hooks/useSecureHandshakes.js";
10
+ export type { UseSecureHandshakesOptions, UseSecureHandshakesValues, } from "./hooks/useSecureHandshakes.js";
11
+ export { SecureChatRestClient } from "./transport/rest.js";
12
+ export type { SecureChatRestConfig } from "./transport/rest.js";
13
+ export { SecureChatSocketClient } from "./transport/socket.js";
14
+ export type { SecureSocket, SecureServerEvents, SecureClientEvents, SecureChatSocketConfig, } from "./transport/socket.js";
13
15
  export type { SecureChatCrypto, DeviceIdentity, KeyPackageBundle, GroupHandle, TargetedWelcome, CommitResult, PassphraseBackup, } from "@agora-sdk/secure-chat-crypto";
14
- export type * from "./contract";
15
- export { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "./util/base64";
16
+ export type * from "./contract/index.js";
17
+ export type { SecureChatStore } from "./persistence/store.js";
18
+ export { MemoryStore } from "./persistence/memory-store.js";
19
+ export { SecureChatRepository } from "./persistence/repository.js";
20
+ export type { PersistedDevice } from "./persistence/repository.js";
21
+ export { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "./util/base64.js";