@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.
- package/dist/cjs/context/secure-chat-context.d.ts +34 -18
- package/dist/cjs/context/secure-chat-context.js +78 -23
- package/dist/cjs/context/secure-chat-context.js.map +1 -1
- package/dist/cjs/contract/index.js +2 -2
- package/dist/cjs/contract/index.js.map +1 -1
- package/dist/cjs/hooks/useSecureConversations.d.ts +1 -1
- package/dist/cjs/hooks/useSecureConversations.js +9 -7
- package/dist/cjs/hooks/useSecureConversations.js.map +1 -1
- package/dist/cjs/hooks/useSecureDevice.d.ts +14 -13
- package/dist/cjs/hooks/useSecureDevice.js +58 -25
- package/dist/cjs/hooks/useSecureDevice.js.map +1 -1
- package/dist/cjs/hooks/useSecureHandshakes.d.ts +64 -0
- package/dist/cjs/hooks/useSecureHandshakes.js +215 -0
- package/dist/cjs/hooks/useSecureHandshakes.js.map +1 -0
- package/dist/cjs/hooks/useSecureMessages.d.ts +10 -11
- package/dist/cjs/hooks/useSecureMessages.js +99 -21
- package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
- package/dist/cjs/index.d.ts +20 -14
- package/dist/cjs/index.js +25 -19
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/persistence/memory-store.d.ts +9 -0
- package/dist/cjs/persistence/memory-store.js +27 -0
- package/dist/cjs/persistence/memory-store.js.map +1 -0
- package/dist/cjs/persistence/repository.d.ts +36 -0
- package/dist/cjs/persistence/repository.js +72 -0
- package/dist/cjs/persistence/repository.js.map +1 -0
- package/dist/cjs/persistence/store.d.ts +11 -0
- package/dist/cjs/persistence/store.js +8 -0
- package/dist/cjs/persistence/store.js.map +1 -0
- package/dist/cjs/transport/rest.d.ts +1 -1
- package/dist/cjs/transport/socket.d.ts +1 -1
- package/dist/esm/context/secure-chat-context.d.ts +34 -18
- package/dist/esm/context/secure-chat-context.js +77 -22
- package/dist/esm/context/secure-chat-context.js.map +1 -1
- package/dist/esm/contract/index.js +2 -2
- package/dist/esm/contract/index.js.map +1 -1
- package/dist/esm/hooks/useSecureConversations.d.ts +1 -1
- package/dist/esm/hooks/useSecureConversations.js +6 -4
- package/dist/esm/hooks/useSecureConversations.js.map +1 -1
- package/dist/esm/hooks/useSecureDevice.d.ts +14 -13
- package/dist/esm/hooks/useSecureDevice.js +55 -22
- package/dist/esm/hooks/useSecureDevice.js.map +1 -1
- package/dist/esm/hooks/useSecureHandshakes.d.ts +64 -0
- package/dist/esm/hooks/useSecureHandshakes.js +212 -0
- package/dist/esm/hooks/useSecureHandshakes.js.map +1 -0
- package/dist/esm/hooks/useSecureMessages.d.ts +10 -11
- package/dist/esm/hooks/useSecureMessages.js +96 -18
- package/dist/esm/hooks/useSecureMessages.js.map +1 -1
- package/dist/esm/index.d.ts +20 -14
- package/dist/esm/index.js +10 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/persistence/memory-store.d.ts +9 -0
- package/dist/esm/persistence/memory-store.js +23 -0
- package/dist/esm/persistence/memory-store.js.map +1 -0
- package/dist/esm/persistence/repository.d.ts +36 -0
- package/dist/esm/persistence/repository.js +68 -0
- package/dist/esm/persistence/repository.js.map +1 -0
- package/dist/esm/persistence/store.d.ts +11 -0
- package/dist/esm/persistence/store.js +7 -0
- package/dist/esm/persistence/store.js.map +1 -0
- package/dist/esm/transport/rest.d.ts +1 -1
- package/dist/esm/transport/socket.d.ts +1 -1
- package/package.json +3 -3
|
@@ -1,39 +1,96 @@
|
|
|
1
1
|
// useSecureMessages — load, decrypt, send, and live-receive messages in a secure conversation.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { useSecureChat } from "../context/secure-chat-context";
|
|
3
|
+
// Self-sufficient once a store is wired: the MLS GroupHandle is auto-resolved from persistence via
|
|
4
|
+
// resolveGroup, and senderDeviceId is read from the persisted device. Both stay overridable through
|
|
5
|
+
// options for advanced use. Without a resolvable handle, ciphertext is still listed/received
|
|
6
|
+
// (plaintext: null) and sending is disabled.
|
|
7
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "../util/base64.js";
|
|
9
|
+
import { useSecureChat } from "../context/secure-chat-context.js";
|
|
11
10
|
/**
|
|
12
11
|
* Load, decrypt, send, and live-receive messages in one secure conversation.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `
|
|
17
|
-
* wiring. Joins the conversation's socket room to receive `secure:message` events live.
|
|
13
|
+
* Auto-resolves the MLS group handle (via `resolveGroup`) and the sender device id (from the
|
|
14
|
+
* persisted device) unless overridden in `options`. Joins the conversation socket room for live
|
|
15
|
+
* `secure:message` events.
|
|
18
16
|
*
|
|
19
17
|
* @param conversationId - The conversation to read and send within.
|
|
20
|
-
* @param options - {@link UseSecureMessagesOptions}
|
|
21
|
-
* @returns {@link UseSecureMessagesValues}
|
|
18
|
+
* @param options - {@link UseSecureMessagesOptions}.
|
|
19
|
+
* @returns {@link UseSecureMessagesValues}.
|
|
22
20
|
*
|
|
23
21
|
* @example
|
|
24
22
|
* ```tsx
|
|
25
|
-
* const { messages, sendMessage } = useSecureMessages(conversationId
|
|
23
|
+
* const { messages, sendMessage } = useSecureMessages(conversationId);
|
|
26
24
|
* await sendMessage("hello 💜");
|
|
27
25
|
* ```
|
|
28
26
|
*/
|
|
29
27
|
export function useSecureMessages(conversationId, options = {}) {
|
|
30
|
-
const { rest, crypto, socket } = useSecureChat();
|
|
31
|
-
const { group, senderDeviceId } = options;
|
|
28
|
+
const { rest, crypto, socket, repo, resolveGroup, getGroupVersion, subscribeGroupChange } = useSecureChat();
|
|
32
29
|
const [messages, setMessages] = useState([]);
|
|
33
30
|
const [before, setBefore] = useState(undefined);
|
|
34
31
|
const [hasMore, setHasMore] = useState(true);
|
|
35
32
|
const [loading, setLoading] = useState(false);
|
|
36
33
|
const [error, setError] = useState(null);
|
|
34
|
+
const [group, setGroup] = useState(options.group ?? null);
|
|
35
|
+
const [senderDeviceId, setSenderDeviceId] = useState(options.senderDeviceId);
|
|
36
|
+
// Bumps when THIS conversation's group handle advances (a join or a processed Commit, driven by
|
|
37
|
+
// useSecureHandshakes calling rememberGroup). Feeds the group-resolve effect's deps so we re-resolve
|
|
38
|
+
// the now-current handle and flush buffered (plaintext:null) rows.
|
|
39
|
+
const [groupVersion, setGroupVersion] = useState(0);
|
|
40
|
+
// Latest messages, read by the "decrypt history once the group resolves" effect below without
|
|
41
|
+
// making `messages` one of its deps (which would loop).
|
|
42
|
+
const messagesRef = useRef(messages);
|
|
43
|
+
messagesRef.current = messages;
|
|
44
|
+
// Subscribe to provider group-change signals; only a change to OUR conversation's version updates
|
|
45
|
+
// state (React bails on an unchanged primitive), so unrelated conversations don't re-resolve us.
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
return subscribeGroupChange(() => setGroupVersion(getGroupVersion(conversationId)));
|
|
48
|
+
}, [subscribeGroupChange, getGroupVersion, conversationId]);
|
|
49
|
+
// Resolve the group handle: explicit override, else persisted state.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (options.group) {
|
|
52
|
+
setGroup(options.group);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Clear any stale handle from the previous conversation before re-resolving, so live messages
|
|
56
|
+
// for the new conversation never decrypt against the old group during the async window.
|
|
57
|
+
setGroup(null);
|
|
58
|
+
let alive = true;
|
|
59
|
+
resolveGroup(conversationId)
|
|
60
|
+
.then((g) => {
|
|
61
|
+
if (alive)
|
|
62
|
+
setGroup(g);
|
|
63
|
+
})
|
|
64
|
+
.catch(() => {
|
|
65
|
+
if (alive)
|
|
66
|
+
setGroup(null);
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
alive = false;
|
|
70
|
+
};
|
|
71
|
+
// `groupVersion` re-runs this when a Commit/join advances the handle → flushes buffered rows.
|
|
72
|
+
}, [options.group, conversationId, resolveGroup, groupVersion]);
|
|
73
|
+
// Resolve the sender device id: explicit override, else persisted device row.
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (options.senderDeviceId) {
|
|
76
|
+
setSenderDeviceId(options.senderDeviceId);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
let alive = true;
|
|
80
|
+
repo
|
|
81
|
+
.loadDevice()
|
|
82
|
+
.then((d) => {
|
|
83
|
+
if (alive)
|
|
84
|
+
setSenderDeviceId(d?.device?.id ?? undefined);
|
|
85
|
+
})
|
|
86
|
+
.catch(() => {
|
|
87
|
+
if (alive)
|
|
88
|
+
setSenderDeviceId(undefined);
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
alive = false;
|
|
92
|
+
};
|
|
93
|
+
}, [options.senderDeviceId, repo]);
|
|
37
94
|
const decrypt = useCallback(async (model) => {
|
|
38
95
|
if (!group)
|
|
39
96
|
return { model, plaintext: null };
|
|
@@ -78,6 +135,9 @@ export function useSecureMessages(conversationId, options = {}) {
|
|
|
78
135
|
await load(false);
|
|
79
136
|
}, [hasMore, loading, load]);
|
|
80
137
|
const sendMessage = useCallback(async (text) => {
|
|
138
|
+
// Assumes the crypto identity is already hydrated (mount `useSecureDevice` under the same
|
|
139
|
+
// provider): the crypto layer tags the sender from the restored device identity, so after a
|
|
140
|
+
// reload the first send must wait for useSecureDevice's importDeviceState to complete.
|
|
81
141
|
if (!group)
|
|
82
142
|
throw new Error("Cannot send: no MLS group handle for this conversation.");
|
|
83
143
|
if (!senderDeviceId)
|
|
@@ -95,13 +155,31 @@ export function useSecureMessages(conversationId, options = {}) {
|
|
|
95
155
|
refresh();
|
|
96
156
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
97
157
|
}, [conversationId]);
|
|
158
|
+
// Decrypt history that was listed before the group handle resolved. On reload, the first page loads
|
|
159
|
+
// while resolveGroup is still in flight, so those rows come back `plaintext: null`; once the handle
|
|
160
|
+
// arrives (decrypt is recreated with it), re-decrypt the still-undecrypted rows in place — no
|
|
161
|
+
// re-fetch, scroll/pagination preserved.
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (!group)
|
|
164
|
+
return;
|
|
165
|
+
if (!messagesRef.current.some((m) => m.plaintext === null))
|
|
166
|
+
return;
|
|
167
|
+
let alive = true;
|
|
168
|
+
Promise.all(messagesRef.current.map((m) => (m.plaintext === null ? decrypt(m.model) : Promise.resolve(m)))).then((next) => {
|
|
169
|
+
if (alive)
|
|
170
|
+
setMessages(next);
|
|
171
|
+
});
|
|
172
|
+
return () => {
|
|
173
|
+
alive = false;
|
|
174
|
+
};
|
|
175
|
+
}, [group, decrypt]);
|
|
98
176
|
// Live receive: join the conversation room and decrypt inbound ciphertext.
|
|
99
177
|
useEffect(() => {
|
|
100
178
|
socket.joinConversation(conversationId);
|
|
101
179
|
const off = socket.on("secure:message", (model) => {
|
|
102
180
|
if (model.conversationId !== conversationId)
|
|
103
181
|
return;
|
|
104
|
-
decrypt(model).then((m) => setMessages((prev) => prev.some((p) => p.model.id === m.model.id) ? prev : [m, ...prev]));
|
|
182
|
+
decrypt(model).then((m) => setMessages((prev) => (prev.some((p) => p.model.id === m.model.id) ? prev : [m, ...prev])));
|
|
105
183
|
});
|
|
106
184
|
return off;
|
|
107
185
|
}, [socket, conversationId, decrypt]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -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 {
|
|
10
|
-
export type {
|
|
11
|
-
export {
|
|
12
|
-
export type {
|
|
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 {
|
|
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";
|
package/dist/esm/index.js
CHANGED
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
// injection of a `SecureChatCrypto`. Platform packages (@agora-sdk/secure-chat-react-js, etc.)
|
|
5
5
|
// re-export this and add the concrete crypto + persistence.
|
|
6
6
|
// ── context / provider ──────────────────────────────────────────────────────
|
|
7
|
-
export { SecureChatProvider, useSecureChat } from "./context/secure-chat-context";
|
|
7
|
+
export { SecureChatProvider, useSecureChat } from "./context/secure-chat-context.js";
|
|
8
8
|
// ── hooks ────────────────────────────────────────────────────────────────────
|
|
9
|
-
export { useSecureDevice } from "./hooks/useSecureDevice";
|
|
10
|
-
export { useSecureConversations } from "./hooks/useSecureConversations";
|
|
11
|
-
export { useSecureMessages } from "./hooks/useSecureMessages";
|
|
9
|
+
export { useSecureDevice } from "./hooks/useSecureDevice.js";
|
|
10
|
+
export { useSecureConversations } from "./hooks/useSecureConversations.js";
|
|
11
|
+
export { useSecureMessages } from "./hooks/useSecureMessages.js";
|
|
12
|
+
export { useSecureHandshakes } from "./hooks/useSecureHandshakes.js";
|
|
12
13
|
// ── transport (for advanced / non-React use) ─────────────────────────────────
|
|
13
|
-
export { SecureChatRestClient } from "./transport/rest";
|
|
14
|
-
export { SecureChatSocketClient } from "./transport/socket";
|
|
14
|
+
export { SecureChatRestClient } from "./transport/rest.js";
|
|
15
|
+
export { SecureChatSocketClient } from "./transport/socket.js";
|
|
16
|
+
export { MemoryStore } from "./persistence/memory-store.js";
|
|
17
|
+
export { SecureChatRepository } from "./persistence/repository.js";
|
|
15
18
|
// ── utils ────────────────────────────────────────────────────────────────────
|
|
16
|
-
export { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "./util/base64";
|
|
19
|
+
export { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "./util/base64.js";
|
|
17
20
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,4DAA4D;AAE5D,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,4DAA4D;AAE5D,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAMrF,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAMjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAMrE,gFAAgF;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAwB/D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,gFAAgF;AAChF,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SecureChatStore } from "./store.js";
|
|
2
|
+
/** A `Map`-backed {@link SecureChatStore}. Non-persistent; the default when no store is injected. */
|
|
3
|
+
export declare class MemoryStore implements SecureChatStore {
|
|
4
|
+
private readonly map;
|
|
5
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
6
|
+
set(key: string, value: Uint8Array): Promise<void>;
|
|
7
|
+
delete(key: string): Promise<void>;
|
|
8
|
+
list(prefix: string): Promise<string[]>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// In-memory SecureChatStore — the provider default and the unit-test backing store.
|
|
2
|
+
//
|
|
3
|
+
// Not persistent: state is lost on reload. Platforms inject a durable store (IndexedDB on web) for
|
|
4
|
+
// real persistence; this keeps core usable in tests and SSR without one.
|
|
5
|
+
/** A `Map`-backed {@link SecureChatStore}. Non-persistent; the default when no store is injected. */
|
|
6
|
+
export class MemoryStore {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.map = new Map();
|
|
9
|
+
}
|
|
10
|
+
async get(key) {
|
|
11
|
+
return this.map.get(key) ?? null;
|
|
12
|
+
}
|
|
13
|
+
async set(key, value) {
|
|
14
|
+
this.map.set(key, value);
|
|
15
|
+
}
|
|
16
|
+
async delete(key) {
|
|
17
|
+
this.map.delete(key);
|
|
18
|
+
}
|
|
19
|
+
async list(prefix) {
|
|
20
|
+
return [...this.map.keys()].filter((k) => k.startsWith(prefix));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=memory-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../../src/persistence/memory-store.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,EAAE;AACF,mGAAmG;AACnG,yEAAyE;AAIzE,qGAAqG;AACrG,MAAM,OAAO,WAAW;IAAxB;QACmB,QAAG,GAAG,IAAI,GAAG,EAAsB,CAAC;IAiBvD,CAAC;IAfC,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAiB;QACtC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClE,CAAC;CACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SecureDeviceModel } from "../contract/index.js";
|
|
2
|
+
import type { SecureChatStore } from "./store.js";
|
|
3
|
+
/** The persisted device record: stable id, opaque crypto device-state, and the server row. */
|
|
4
|
+
export interface PersistedDevice {
|
|
5
|
+
/** Stable MLS device id; survives reload. */
|
|
6
|
+
deviceId: string;
|
|
7
|
+
/** Opaque bytes from `crypto.exportDeviceState()`. */
|
|
8
|
+
deviceState: Uint8Array;
|
|
9
|
+
/** The registered server row (rehydrates UI without a refetch), or `null` if not yet registered. */
|
|
10
|
+
device: SecureDeviceModel | null;
|
|
11
|
+
}
|
|
12
|
+
/** Typed persistence for device identity, per-conversation group state, and the handshake cursor. */
|
|
13
|
+
export declare class SecureChatRepository {
|
|
14
|
+
private readonly store;
|
|
15
|
+
constructor(store: SecureChatStore);
|
|
16
|
+
/** Load the persisted device record, or `null` if none saved (first run / evicted). */
|
|
17
|
+
loadDevice(): Promise<PersistedDevice | null>;
|
|
18
|
+
/** Persist (replace) the device record. */
|
|
19
|
+
saveDevice(d: PersistedDevice): Promise<void>;
|
|
20
|
+
/** Remove the persisted device record. */
|
|
21
|
+
clearDevice(): Promise<void>;
|
|
22
|
+
/** Load opaque MLS group state for a conversation, or `null` if none. */
|
|
23
|
+
loadGroupState(conversationId: string): Promise<Uint8Array | null>;
|
|
24
|
+
/** Persist opaque MLS group state for a conversation. */
|
|
25
|
+
saveGroupState(conversationId: string, state: Uint8Array): Promise<void>;
|
|
26
|
+
/** Remove persisted group state for a conversation. */
|
|
27
|
+
deleteGroupState(conversationId: string): Promise<void>;
|
|
28
|
+
/** List the conversation ids that have persisted group state. */
|
|
29
|
+
listGroupConversationIds(): Promise<string[]>;
|
|
30
|
+
/** Load the persisted handshake delivery cursor (`seq`), or `null`. */
|
|
31
|
+
loadHandshakeCursor(): Promise<string | null>;
|
|
32
|
+
/** Persist the handshake delivery cursor (`seq`). */
|
|
33
|
+
saveHandshakeCursor(seq: string): Promise<void>;
|
|
34
|
+
/** Wipe all persisted secure-chat state (sign-out / device revoke). */
|
|
35
|
+
clearAll(): Promise<void>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// SecureChatRepository — typed façade over a SecureChatStore.
|
|
2
|
+
//
|
|
3
|
+
// The ONLY place in the SDK that knows the persistence key strings and how each record is
|
|
4
|
+
// serialized. Binary fields are base64-wrapped inside JSON; opaque crypto blobs (group/device
|
|
5
|
+
// state) are stored as-is. Built by SecureChatProvider over the injected store.
|
|
6
|
+
import { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "../util/base64.js";
|
|
7
|
+
const DEVICE_KEY = "device";
|
|
8
|
+
const GROUP_PREFIX = "group:";
|
|
9
|
+
const CURSOR_KEY = "handshake:cursor";
|
|
10
|
+
/** Typed persistence for device identity, per-conversation group state, and the handshake cursor. */
|
|
11
|
+
export class SecureChatRepository {
|
|
12
|
+
constructor(store) {
|
|
13
|
+
this.store = store;
|
|
14
|
+
}
|
|
15
|
+
/** Load the persisted device record, or `null` if none saved (first run / evicted). */
|
|
16
|
+
async loadDevice() {
|
|
17
|
+
const bytes = await this.store.get(DEVICE_KEY);
|
|
18
|
+
if (!bytes)
|
|
19
|
+
return null;
|
|
20
|
+
const rec = JSON.parse(bytesToUtf8(bytes));
|
|
21
|
+
return { deviceId: rec.deviceId, deviceState: fromBase64(rec.deviceState), device: rec.device };
|
|
22
|
+
}
|
|
23
|
+
/** Persist (replace) the device record. */
|
|
24
|
+
async saveDevice(d) {
|
|
25
|
+
const rec = {
|
|
26
|
+
deviceId: d.deviceId,
|
|
27
|
+
deviceState: toBase64(d.deviceState),
|
|
28
|
+
device: d.device,
|
|
29
|
+
};
|
|
30
|
+
await this.store.set(DEVICE_KEY, utf8ToBytes(JSON.stringify(rec)));
|
|
31
|
+
}
|
|
32
|
+
/** Remove the persisted device record. */
|
|
33
|
+
async clearDevice() {
|
|
34
|
+
await this.store.delete(DEVICE_KEY);
|
|
35
|
+
}
|
|
36
|
+
/** Load opaque MLS group state for a conversation, or `null` if none. */
|
|
37
|
+
async loadGroupState(conversationId) {
|
|
38
|
+
return this.store.get(GROUP_PREFIX + conversationId);
|
|
39
|
+
}
|
|
40
|
+
/** Persist opaque MLS group state for a conversation. */
|
|
41
|
+
async saveGroupState(conversationId, state) {
|
|
42
|
+
await this.store.set(GROUP_PREFIX + conversationId, state);
|
|
43
|
+
}
|
|
44
|
+
/** Remove persisted group state for a conversation. */
|
|
45
|
+
async deleteGroupState(conversationId) {
|
|
46
|
+
await this.store.delete(GROUP_PREFIX + conversationId);
|
|
47
|
+
}
|
|
48
|
+
/** List the conversation ids that have persisted group state. */
|
|
49
|
+
async listGroupConversationIds() {
|
|
50
|
+
const keys = await this.store.list(GROUP_PREFIX);
|
|
51
|
+
return keys.map((k) => k.slice(GROUP_PREFIX.length));
|
|
52
|
+
}
|
|
53
|
+
/** Load the persisted handshake delivery cursor (`seq`), or `null`. */
|
|
54
|
+
async loadHandshakeCursor() {
|
|
55
|
+
const bytes = await this.store.get(CURSOR_KEY);
|
|
56
|
+
return bytes ? bytesToUtf8(bytes) : null;
|
|
57
|
+
}
|
|
58
|
+
/** Persist the handshake delivery cursor (`seq`). */
|
|
59
|
+
async saveHandshakeCursor(seq) {
|
|
60
|
+
await this.store.set(CURSOR_KEY, utf8ToBytes(seq));
|
|
61
|
+
}
|
|
62
|
+
/** Wipe all persisted secure-chat state (sign-out / device revoke). */
|
|
63
|
+
async clearAll() {
|
|
64
|
+
const keys = await this.store.list("");
|
|
65
|
+
await Promise.all(keys.map((k) => this.store.delete(k)));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/persistence/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** A platform-agnostic async key→blob store. Implementations: `MemoryStore`, `createIndexedDBStore`. */
|
|
2
|
+
export interface SecureChatStore {
|
|
3
|
+
/** Read the bytes at `key`, or `null` if absent. */
|
|
4
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
5
|
+
/** Write `value` at `key`, overwriting any existing value. */
|
|
6
|
+
set(key: string, value: Uint8Array): Promise<void>;
|
|
7
|
+
/** Remove `key` if present (no-op when absent). */
|
|
8
|
+
delete(key: string): Promise<void>;
|
|
9
|
+
/** Return all keys that start with `prefix` (use `""` for every key). */
|
|
10
|
+
list(prefix: string): Promise<string[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// The persistence seam — a dumb, async key→blob store.
|
|
2
|
+
//
|
|
3
|
+
// This is ALL a platform must implement: web ships an IndexedDB-backed store, native swaps a
|
|
4
|
+
// keystore later. The SDK owns the key schema and (de)serialization on top of this (see
|
|
5
|
+
// ./repository.ts); the store itself never interprets keys or values. Values are opaque bytes.
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/persistence/store.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,6FAA6F;AAC7F,wFAAwF;AACxF,+FAA+F"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddSecureMemberBody, CreateSecureConversationBody, PublishKeyPackagesBody, RegisterDeviceBody, RemoveSecureMemberBody, SecureConversationMemberModel, SecureConversationModel, SecureDeviceModel, SecureHandshakeModel, SecureKeyBackupModel, SecureKeyPackageClaim, SecureMessageModel, SendSecureMessageBody, UploadKeyBackupBody } from "../contract";
|
|
1
|
+
import { AddSecureMemberBody, CreateSecureConversationBody, PublishKeyPackagesBody, RegisterDeviceBody, RemoveSecureMemberBody, SecureConversationMemberModel, SecureConversationModel, SecureDeviceModel, SecureHandshakeModel, SecureKeyBackupModel, SecureKeyPackageClaim, SecureMessageModel, SendSecureMessageBody, UploadKeyBackupBody } from "../contract/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Configuration for {@link SecureChatRestClient}. The base URL and access token are read through
|
|
4
4
|
* resolver callbacks rather than captured once, so a late-set `baseUrl` or a refreshed token take
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Socket } from "socket.io-client";
|
|
2
|
-
import { SecureHandshakeModel, SecureMessageModel } from "../contract";
|
|
2
|
+
import { SecureHandshakeModel, SecureMessageModel } from "../contract/index.js";
|
|
3
3
|
/** Server → client events on the `/secure` namespace (§10). */
|
|
4
4
|
export interface SecureServerEvents {
|
|
5
5
|
"secure:message": (message: SecureMessageModel) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agora-sdk/secure-chat-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Agora SDK Plus, maintained by Jenova Marie",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"axios": "^1.4.0",
|
|
39
39
|
"socket.io-client": "^4.8.1",
|
|
40
|
-
"@agora-sdk/secure-chat-crypto": "0.
|
|
40
|
+
"@agora-sdk/secure-chat-crypto": "0.3.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@agora-sdk/core": "^1.2.2",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
48
|
-
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
48
|
+
"build:cjs": "tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
49
49
|
"build": "rimraf dist && pnpm run build:esm && pnpm run build:cjs",
|
|
50
50
|
"prepublish": "pnpm run build"
|
|
51
51
|
}
|