@xdevplatform/chat-xdk 0.1.0 → 0.2.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/LICENSE +21 -0
- package/README.md +27 -23
- package/index.d.ts +365 -77
- package/index.js +178 -47
- package/package.json +6 -2
- package/pkg/chat_xdk_wasm.d.ts +124 -44
- package/pkg/chat_xdk_wasm.js +224 -223
- package/pkg/chat_xdk_wasm_bg.wasm +0 -0
- package/pkg/chat_xdk_wasm_bg.wasm.d.ts +15 -9
- package/pkg/package.json +21 -0
package/index.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface PublicKeys {
|
|
|
10
10
|
identity: string;
|
|
11
11
|
/** Base64-encoded signing public key */
|
|
12
12
|
signing: string;
|
|
13
|
+
/**
|
|
14
|
+
* Always the empty string; reserved. The registered key version set via
|
|
15
|
+
* setKeyVersion is tracked internally and not surfaced here.
|
|
16
|
+
*/
|
|
17
|
+
version: string;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
/**
|
|
@@ -34,7 +39,8 @@ export interface PublicKeyRegistrationPayload {
|
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
/**
|
|
37
|
-
* Result from
|
|
42
|
+
* Result from encryptMessage, encryptReply, encryptAddReaction, and
|
|
43
|
+
* encryptRemoveReaction.
|
|
38
44
|
*/
|
|
39
45
|
export interface SendPayload {
|
|
40
46
|
/** Base64-encoded Thrift MessageCreateEvent. */
|
|
@@ -52,7 +58,7 @@ export interface SendPayload {
|
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
/**
|
|
55
|
-
*
|
|
61
|
+
* An action signature authenticating a conversation key change or member add.
|
|
56
62
|
*/
|
|
57
63
|
export interface ActionSignature {
|
|
58
64
|
messageId: string;
|
|
@@ -60,19 +66,8 @@ export interface ActionSignature {
|
|
|
60
66
|
signature: string;
|
|
61
67
|
signatureVersion: string;
|
|
62
68
|
publicKeyVersion: string;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* A recipient for encryptConversationKeyForRecipients.
|
|
68
|
-
*/
|
|
69
|
-
export interface RecipientInput {
|
|
70
|
-
/** The recipient's user ID (snowflake string). */
|
|
71
|
-
userId: string;
|
|
72
|
-
/** Base64-encoded identity public key (SEC1 or SPKI). */
|
|
73
|
-
publicKey: string;
|
|
74
|
-
/** Key version string from the X API. */
|
|
75
|
-
keyVersion: string;
|
|
69
|
+
/** Omitted for conversation-key changes; the signed payload embeds the plaintext conversation key. */
|
|
70
|
+
signaturePayload?: string;
|
|
76
71
|
}
|
|
77
72
|
|
|
78
73
|
/**
|
|
@@ -124,8 +119,8 @@ export interface DecryptEventsResult {
|
|
|
124
119
|
messages: DecryptedMessage[];
|
|
125
120
|
/** Extracted conversation keys (for caching). */
|
|
126
121
|
conversationKeys: ConversationKeyResult;
|
|
127
|
-
/** Errors encountered during decryption (index → error message). */
|
|
128
|
-
errors: { [index:
|
|
122
|
+
/** Errors encountered during decryption (event index, as a string key → error message). */
|
|
123
|
+
errors: { [index: string]: string };
|
|
129
124
|
}
|
|
130
125
|
|
|
131
126
|
/**
|
|
@@ -137,7 +132,7 @@ export interface ImageDimensions {
|
|
|
137
132
|
}
|
|
138
133
|
|
|
139
134
|
/**
|
|
140
|
-
* Encrypted key for a single
|
|
135
|
+
* Encrypted conversation key for a single participant.
|
|
141
136
|
*/
|
|
142
137
|
export interface EncryptedKeyForRecipient {
|
|
143
138
|
userId: string;
|
|
@@ -146,7 +141,7 @@ export interface EncryptedKeyForRecipient {
|
|
|
146
141
|
}
|
|
147
142
|
|
|
148
143
|
/**
|
|
149
|
-
* A public key input for
|
|
144
|
+
* A public key input for prepareConversationKeyChange / prepareGroupMembersChange.
|
|
150
145
|
*
|
|
151
146
|
* Represents a single public key version for a user, as returned by the
|
|
152
147
|
* X API `GET /2/dm/encryption/public_keys` endpoint.
|
|
@@ -164,26 +159,209 @@ export interface PublicKeyInput {
|
|
|
164
159
|
}
|
|
165
160
|
|
|
166
161
|
/**
|
|
167
|
-
* Result from
|
|
162
|
+
* Result from prepareConversationKeyChange / prepareGroupMembersChange.
|
|
168
163
|
*
|
|
169
|
-
* Contains everything needed to POST to the X API
|
|
170
|
-
*
|
|
164
|
+
* Contains everything needed to POST the change to the X API: the new key
|
|
165
|
+
* (to keep locally), the per-participant encrypted copies, and the action
|
|
166
|
+
* signature that lets recipients verify the change.
|
|
171
167
|
*/
|
|
172
|
-
export interface
|
|
168
|
+
export interface PreparedConversationChange {
|
|
169
|
+
/** Conversation id the change applies to (derived for a one-to-one, or the id you passed). */
|
|
170
|
+
conversationId: string;
|
|
173
171
|
/** Raw conversation key bytes (32 bytes). Store locally for encrypting messages. */
|
|
174
172
|
conversationKey: Uint8Array;
|
|
175
173
|
/** Timestamp-based version string for this conversation key. */
|
|
176
174
|
conversationKeyVersion: string;
|
|
177
175
|
/** Encrypted keys for each participant, ready to POST to the API. */
|
|
178
176
|
participantKeys: EncryptedKeyForRecipient[];
|
|
177
|
+
/** Action signatures authenticating the change, ready to POST to the API. */
|
|
178
|
+
actionSignatures: ActionSignature[];
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/**
|
|
182
182
|
* Entity descriptor tuple: [startByteOffset, endByteOffset, entityType].
|
|
183
|
-
* entityType is one of: "url", "mention", "hashtag", "cashtag", "email",
|
|
183
|
+
* entityType is one of: "url", "mention", "hashtag", "cashtag", "email",
|
|
184
|
+
* "address", "phoneNumber" (the snake_case spelling "phone_number" is
|
|
185
|
+
* accepted too). Unrecognized entity types are silently dropped — the
|
|
186
|
+
* message encrypts without that entity and no error is raised.
|
|
184
187
|
*/
|
|
185
188
|
export type EntityTuple = [number, number, string];
|
|
186
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Parameters for encryptMessage.
|
|
192
|
+
*/
|
|
193
|
+
export interface EncryptMessageParams {
|
|
194
|
+
/** ID of the message being sent. */
|
|
195
|
+
messageId: string;
|
|
196
|
+
/** User ID of the sender. */
|
|
197
|
+
senderId: string;
|
|
198
|
+
/** ID of the conversation the message belongs to. */
|
|
199
|
+
conversationId: string;
|
|
200
|
+
/** Raw 32-byte conversation key used to encrypt the message content. */
|
|
201
|
+
conversationKey: Uint8Array;
|
|
202
|
+
/** The plaintext message text. */
|
|
203
|
+
text: string;
|
|
204
|
+
/** Version of the conversation key used for encryption. */
|
|
205
|
+
conversationKeyVersion: string;
|
|
206
|
+
/** Version of the signing key used to sign the message. */
|
|
207
|
+
signingKeyVersion: string;
|
|
208
|
+
/** Optional rich-text entities (URLs, mentions, etc.) to embed. */
|
|
209
|
+
entities?: EntityTuple[] | null;
|
|
210
|
+
/** Optional attachments (posts, URLs, media, etc.) to include in the message. */
|
|
211
|
+
attachments?: AttachmentDescriptor[] | null;
|
|
212
|
+
/** Whether to send a push notification. Omitted defaults to true. */
|
|
213
|
+
shouldNotify?: boolean | null;
|
|
214
|
+
/** Optional TTL in milliseconds for disappearing messages. */
|
|
215
|
+
ttlMsec?: number | null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Parameters for encryptReply.
|
|
220
|
+
*/
|
|
221
|
+
export interface EncryptReplyParams {
|
|
222
|
+
/** ID of the reply message being sent. */
|
|
223
|
+
messageId: string;
|
|
224
|
+
/** User ID of the sender. */
|
|
225
|
+
senderId: string;
|
|
226
|
+
/** ID of the conversation the reply belongs to. */
|
|
227
|
+
conversationId: string;
|
|
228
|
+
/** Raw 32-byte conversation key used to encrypt the message content. */
|
|
229
|
+
conversationKey: Uint8Array;
|
|
230
|
+
/** The plaintext reply text. */
|
|
231
|
+
text: string;
|
|
232
|
+
/** Version of the conversation key used for encryption. */
|
|
233
|
+
conversationKeyVersion: string;
|
|
234
|
+
/** Version of the signing key used to sign the message. */
|
|
235
|
+
signingKeyVersion: string;
|
|
236
|
+
/** The sequenceId of the message being replied to. */
|
|
237
|
+
replyToSequenceId: string;
|
|
238
|
+
/**
|
|
239
|
+
* The sender ID of the message being replied to (for preview).
|
|
240
|
+
* Prefer a string: snowflake user ids exceed the range where JavaScript
|
|
241
|
+
* numbers stay exact. Numbers are accepted only while integral and within
|
|
242
|
+
* `Number.MAX_SAFE_INTEGER`.
|
|
243
|
+
*/
|
|
244
|
+
replyToSenderId?: string | number | null;
|
|
245
|
+
/** The text of the message being replied to (for preview). */
|
|
246
|
+
replyToText?: string | null;
|
|
247
|
+
/** Optional rich-text entities (URLs, mentions, etc.) to embed in the outgoing message. */
|
|
248
|
+
entities?: EntityTuple[] | null;
|
|
249
|
+
/** Optional attachments (posts, URLs, media, etc.) to include in the outgoing message. */
|
|
250
|
+
attachments?: AttachmentDescriptor[] | null;
|
|
251
|
+
/** Optional rich-text entities from the original message (for the reply preview). */
|
|
252
|
+
replyToEntities?: EntityTuple[] | null;
|
|
253
|
+
/** Optional attachments from the original message (for the reply preview). */
|
|
254
|
+
replyToAttachments?: AttachmentDescriptor[] | null;
|
|
255
|
+
/** Whether to send a push notification. Omitted defaults to true. */
|
|
256
|
+
shouldNotify?: boolean | null;
|
|
257
|
+
/** Optional TTL in milliseconds for disappearing messages. */
|
|
258
|
+
ttlMsec?: number | null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Parameters for encryptAddReaction and encryptRemoveReaction.
|
|
263
|
+
*
|
|
264
|
+
* All fields are required; the same params object can be passed to both
|
|
265
|
+
* methods to add and later remove the same reaction.
|
|
266
|
+
*/
|
|
267
|
+
export interface EncryptReactionParams {
|
|
268
|
+
/** ID of the reaction message being sent. */
|
|
269
|
+
messageId: string;
|
|
270
|
+
/** User ID of the sender. */
|
|
271
|
+
senderId: string;
|
|
272
|
+
/** ID of the conversation the reaction belongs to. */
|
|
273
|
+
conversationId: string;
|
|
274
|
+
/** Raw 32-byte conversation key used to encrypt the reaction content. */
|
|
275
|
+
conversationKey: Uint8Array;
|
|
276
|
+
/** The sequenceId of the message being reacted to. */
|
|
277
|
+
targetMessageSequenceId: string;
|
|
278
|
+
/** The reaction emoji. */
|
|
279
|
+
emoji: string;
|
|
280
|
+
/** Version of the conversation key used for encryption. */
|
|
281
|
+
conversationKeyVersion: string;
|
|
282
|
+
/** Version of the signing key used to sign the message. */
|
|
283
|
+
signingKeyVersion: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Parameters for prepareConversationKeyChange.
|
|
288
|
+
*/
|
|
289
|
+
export interface ConversationKeyChangeParams {
|
|
290
|
+
/** User ID of the sender signing the change. */
|
|
291
|
+
senderId: string;
|
|
292
|
+
/** Version of the signing key used to sign the change. */
|
|
293
|
+
signingKeyVersion: string;
|
|
294
|
+
/** Identity public keys for every participant the new key is encrypted for. */
|
|
295
|
+
publicKeys: PublicKeyInput[];
|
|
296
|
+
/**
|
|
297
|
+
* Conversation the change applies to. Omit for a one-to-one (the canonical
|
|
298
|
+
* id is derived from the two participants); pass the existing id for a
|
|
299
|
+
* group key rotation.
|
|
300
|
+
*/
|
|
301
|
+
conversationId?: string | null;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Parameters for prepareGroupMembersChange.
|
|
306
|
+
*
|
|
307
|
+
* The current* fields snapshot the group state the change is made against.
|
|
308
|
+
* An unset optional signs the null sentinel, so every binding produces
|
|
309
|
+
* identical signed bytes.
|
|
310
|
+
*/
|
|
311
|
+
export interface GroupMembersChangeParams {
|
|
312
|
+
/** User ID of the sender signing the change. */
|
|
313
|
+
senderId: string;
|
|
314
|
+
/** Version of the signing key used to sign the change. */
|
|
315
|
+
signingKeyVersion: string;
|
|
316
|
+
/** Identity public keys for every participant of the updated roster. */
|
|
317
|
+
publicKeys: PublicKeyInput[];
|
|
318
|
+
/** ID of the group conversation being changed. */
|
|
319
|
+
conversationId: string;
|
|
320
|
+
/** User IDs being added to the group. */
|
|
321
|
+
newMemberIds: string[];
|
|
322
|
+
/** User IDs of the current members. */
|
|
323
|
+
currentMemberIds: string[];
|
|
324
|
+
/** User IDs of the current admins. */
|
|
325
|
+
currentAdminIds: string[];
|
|
326
|
+
/** User IDs of members whose join is still pending. */
|
|
327
|
+
currentPendingMemberIds: string[];
|
|
328
|
+
/** The group's current title, if set. */
|
|
329
|
+
currentTitle?: string | null;
|
|
330
|
+
/** The group's current avatar URL, if set. */
|
|
331
|
+
currentAvatarUrl?: string | null;
|
|
332
|
+
/** The group's current message TTL in milliseconds, if set. */
|
|
333
|
+
currentTtlMsec?: number | null;
|
|
334
|
+
/** The group's current screen-capture-blocking state; omit when unset. */
|
|
335
|
+
currentScreenCaptureBlockingEnabled?: boolean | null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Parameters for prepareGroupCreate.
|
|
340
|
+
*
|
|
341
|
+
* An unset optional signs the null sentinel, so every binding produces
|
|
342
|
+
* identical signed bytes.
|
|
343
|
+
*/
|
|
344
|
+
export interface GroupCreateParams {
|
|
345
|
+
/** User ID of the sender signing the create. */
|
|
346
|
+
senderId: string;
|
|
347
|
+
/** Version of the signing key used to sign the create. */
|
|
348
|
+
signingKeyVersion: string;
|
|
349
|
+
/** Identity public keys for every participant of the new group. */
|
|
350
|
+
publicKeys: PublicKeyInput[];
|
|
351
|
+
/** ID of the new group conversation (the g-prefixed id minted by the initialize endpoint). */
|
|
352
|
+
conversationId: string;
|
|
353
|
+
/** User IDs of the group's members. */
|
|
354
|
+
memberIds: string[];
|
|
355
|
+
/** User IDs of the group's admins. */
|
|
356
|
+
adminIds: string[];
|
|
357
|
+
/** The group's title, if set. */
|
|
358
|
+
title?: string | null;
|
|
359
|
+
/** The group's avatar URL, if set. */
|
|
360
|
+
avatarUrl?: string | null;
|
|
361
|
+
/** The group's message TTL in milliseconds, if set. */
|
|
362
|
+
ttlMsec?: number | null;
|
|
363
|
+
}
|
|
364
|
+
|
|
187
365
|
// NOTE: AttachmentDescriptor uses snake_case as it's part of the Thrift protocol
|
|
188
366
|
// and matches the wire format used by the X API
|
|
189
367
|
/**
|
|
@@ -221,7 +399,12 @@ export interface Event {
|
|
|
221
399
|
attachments?: AttachmentInfo[];
|
|
222
400
|
/** For message events: media hash keys derived from attachments (if any). */
|
|
223
401
|
mediaHashes?: MediaHashReference[];
|
|
224
|
-
/**
|
|
402
|
+
/**
|
|
403
|
+
* The conversation key version (a snowflake/timestamp string). On message
|
|
404
|
+
* events: the version the message and any attached media were encrypted
|
|
405
|
+
* under — decrypt them with the matching key from the conversationKeys
|
|
406
|
+
* map. On keyChange events: the new key version introduced by the change.
|
|
407
|
+
*/
|
|
225
408
|
keyVersion?: string;
|
|
226
409
|
/** For keyChange events: encrypted conversation keys, one per participant. */
|
|
227
410
|
participantKeys?: ParticipantKey[];
|
|
@@ -231,8 +414,8 @@ export interface Event {
|
|
|
231
414
|
|
|
232
415
|
/**
|
|
233
416
|
* Decrypted message content. Permissive convenience shape: `contentType`
|
|
234
|
-
* discriminates which fields are present.
|
|
235
|
-
*
|
|
417
|
+
* discriminates which fields are present (e.g. `text` on 'text' content,
|
|
418
|
+
* `emoji`/`targetMessageId` on reactions, `newText` on edits).
|
|
236
419
|
*/
|
|
237
420
|
export interface MessageContent {
|
|
238
421
|
/**
|
|
@@ -281,9 +464,8 @@ export interface MediaHashReference {
|
|
|
281
464
|
|
|
282
465
|
/**
|
|
283
466
|
* An attachment on a decrypted message. Permissive convenience shape: the
|
|
284
|
-
* fields are flattened and `attachmentType` discriminates which
|
|
285
|
-
*
|
|
286
|
-
* `./types` entry.
|
|
467
|
+
* per-variant fields are flattened and `attachmentType` discriminates which
|
|
468
|
+
* apply ('media', 'url', 'post', 'unifiedCard', or 'money').
|
|
287
469
|
*/
|
|
288
470
|
export interface AttachmentInfo {
|
|
289
471
|
/** One of: 'media', 'url', 'post', 'unifiedCard', 'money'. */
|
|
@@ -315,6 +497,12 @@ export interface CreateChatOptions {
|
|
|
315
497
|
/**
|
|
316
498
|
* Juicebox configuration JSON from the X API.
|
|
317
499
|
* Obtain this from: GET /2/dm/encryption/juicebox/config
|
|
500
|
+
*
|
|
501
|
+
* Accepted shapes match the native bindings: the `sdk_config` wrapper
|
|
502
|
+
* (its embedded SDK config string is unwrapped for the Juicebox client),
|
|
503
|
+
* the `token_map` array (converted to a realms config with majority
|
|
504
|
+
* recover threshold), or a raw realms config. Realm auth tokens always
|
|
505
|
+
* come from `getAuthToken`, not the config.
|
|
318
506
|
*/
|
|
319
507
|
juiceboxConfig: string;
|
|
320
508
|
|
|
@@ -335,11 +523,51 @@ export interface CreateChatOptions {
|
|
|
335
523
|
getAuthToken: (realmId: string) => Promise<string>;
|
|
336
524
|
|
|
337
525
|
/**
|
|
338
|
-
* Optional number of PIN guesses allowed before lockout.
|
|
526
|
+
* Optional override for the number of PIN guesses allowed before lockout.
|
|
527
|
+
* A non-negative integer wins over the config, including across later
|
|
528
|
+
* `updateConfig()` calls. When omitted, the config's `max_guess_count`
|
|
529
|
+
* applies when it is a non-negative integer (0 included), defaulting to
|
|
530
|
+
* 20 for the `sdk_config` shape and 5 otherwise.
|
|
339
531
|
*/
|
|
340
532
|
maxGuessCount?: number;
|
|
341
533
|
}
|
|
342
534
|
|
|
535
|
+
/**
|
|
536
|
+
* Incremental stream encryptor for large payloads.
|
|
537
|
+
*
|
|
538
|
+
* Feed plaintext with `push`; call `finish` once to emit the final frame.
|
|
539
|
+
* `finish()` consumes and frees the WASM object — do not call `free()` after
|
|
540
|
+
* it (doing so throws). Call `free()` only when abandoning a stream without
|
|
541
|
+
* finishing it.
|
|
542
|
+
*/
|
|
543
|
+
export declare class StreamEncryptor {
|
|
544
|
+
/** Encrypt a plaintext chunk, returning ciphertext available so far. */
|
|
545
|
+
push(plaintext: Uint8Array): Uint8Array;
|
|
546
|
+
/** Emit the final frame; consumes and frees the encryptor. */
|
|
547
|
+
finish(): Uint8Array;
|
|
548
|
+
/** Release the underlying WASM object when abandoning an unfinished stream. */
|
|
549
|
+
free(): void;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Incremental stream decryptor for large payloads.
|
|
554
|
+
*
|
|
555
|
+
* Feed ciphertext with `push`; call `finish` once at end of input. `finish`
|
|
556
|
+
* throws if the stream ended before its final frame (truncation), so do not
|
|
557
|
+
* treat plaintext from `push` as complete until `finish` succeeds.
|
|
558
|
+
* `finish()` consumes and frees the WASM object — do not call `free()` after
|
|
559
|
+
* it (doing so throws). Call `free()` only when abandoning a stream without
|
|
560
|
+
* finishing it.
|
|
561
|
+
*/
|
|
562
|
+
export declare class StreamDecryptor {
|
|
563
|
+
/** Decrypt a ciphertext chunk, returning plaintext available so far. */
|
|
564
|
+
push(ciphertext: Uint8Array): Uint8Array;
|
|
565
|
+
/** Decrypt the final frame; consumes and frees the decryptor. */
|
|
566
|
+
finish(): Uint8Array;
|
|
567
|
+
/** Release the underlying WASM object when abandoning an unfinished stream. */
|
|
568
|
+
free(): void;
|
|
569
|
+
}
|
|
570
|
+
|
|
343
571
|
/**
|
|
344
572
|
* Common interface for all Chat methods (shared by Chat and ChatWithJuicebox).
|
|
345
573
|
*
|
|
@@ -347,12 +575,19 @@ export interface CreateChatOptions {
|
|
|
347
575
|
* `ChatWithJuicebox` (returned by `createChat()`) adds Juicebox lifecycle methods.
|
|
348
576
|
*/
|
|
349
577
|
interface ChatCrypto {
|
|
350
|
-
/**
|
|
578
|
+
/**
|
|
579
|
+
* When enabled — the default — `decryptEvent` throws for any signed event
|
|
580
|
+
* whose signature cannot be verified (invalid, missing, or no matching
|
|
581
|
+
* signing key) instead of returning it with `verified: false`.
|
|
582
|
+
*/
|
|
351
583
|
setRejectUnverified(reject: boolean): void;
|
|
352
584
|
|
|
353
585
|
/** Generate new keypairs and return the registration payload. */
|
|
354
586
|
generateKeypairs(): PublicKeyRegistrationPayload;
|
|
355
587
|
|
|
588
|
+
/** Set the registered public key version (call after unlock()). */
|
|
589
|
+
setKeyVersion(version: string): void;
|
|
590
|
+
|
|
356
591
|
/** Get current public keys. */
|
|
357
592
|
getPublicKeys(): PublicKeys;
|
|
358
593
|
|
|
@@ -371,9 +606,6 @@ interface ChatCrypto {
|
|
|
371
606
|
/** Decrypt an encrypted conversation key (ECIES). */
|
|
372
607
|
decryptConversationKey(encryptedKeyB64: string): Uint8Array;
|
|
373
608
|
|
|
374
|
-
/** Generate a new conversation key. */
|
|
375
|
-
generateConversationKey(): Uint8Array;
|
|
376
|
-
|
|
377
609
|
/** Extract and decrypt conversation keys from raw KeyChange event strings. */
|
|
378
610
|
extractConversationKeys(events: string[]): ConversationKeyResult;
|
|
379
611
|
|
|
@@ -386,12 +618,22 @@ interface ChatCrypto {
|
|
|
386
618
|
* 3. Decrypts the message using the appropriate conversation key
|
|
387
619
|
*
|
|
388
620
|
* @param events - Raw base64-encoded event strings from the webhook
|
|
389
|
-
* @param signingKeys - All known signing keys for all participants (with
|
|
621
|
+
* @param signingKeys - All known signing keys for all participants (with
|
|
622
|
+
* userId). Under the default reject-unverified policy, omitting this makes
|
|
623
|
+
* every signed event land in `errors`; only after
|
|
624
|
+
* `setRejectUnverified(false)` are such events returned with
|
|
625
|
+
* `verified: false`.
|
|
390
626
|
*/
|
|
391
627
|
decryptEvents(events: string[], signingKeys?: SigningKeyEntry[]): DecryptEventsResult;
|
|
392
628
|
|
|
393
|
-
/**
|
|
394
|
-
|
|
629
|
+
/**
|
|
630
|
+
* Decrypt a raw webhook event payload.
|
|
631
|
+
*
|
|
632
|
+
* Under the default reject-unverified policy, omitting `signingKeys` makes
|
|
633
|
+
* every signed event throw; only after `setRejectUnverified(false)` are
|
|
634
|
+
* such events returned with `verified: false`.
|
|
635
|
+
*/
|
|
636
|
+
decryptEvent(eventB64: string, conversationKeys?: ConversationKeyMap | null, signingKeys?: SigningKeyEntry[]): Event;
|
|
395
637
|
|
|
396
638
|
/** Sign data. Returns raw signature bytes (64 bytes). */
|
|
397
639
|
sign(data: Uint8Array): Uint8Array;
|
|
@@ -399,17 +641,20 @@ interface ChatCrypto {
|
|
|
399
641
|
/** Verify a signature. */
|
|
400
642
|
verify(publicKeyB64: string, signature: Uint8Array, data: Uint8Array): boolean;
|
|
401
643
|
|
|
644
|
+
/** Verify that an identity key signed a signing key (key binding). */
|
|
645
|
+
verifyKeyBinding(identityPublicKeyB64: string, signingPublicKeyB64: string, identityPublicKeySignatureB64: string): boolean;
|
|
646
|
+
|
|
402
647
|
/** Encrypt a text message. */
|
|
403
|
-
encryptMessage(
|
|
648
|
+
encryptMessage(params: EncryptMessageParams): SendPayload;
|
|
404
649
|
|
|
405
650
|
/** Encrypt a reply. */
|
|
406
|
-
encryptReply(
|
|
651
|
+
encryptReply(params: EncryptReplyParams): SendPayload;
|
|
407
652
|
|
|
408
653
|
/** Encrypt a reaction-add. */
|
|
409
|
-
encryptAddReaction(
|
|
654
|
+
encryptAddReaction(params: EncryptReactionParams): SendPayload;
|
|
410
655
|
|
|
411
656
|
/** Encrypt a reaction-remove. */
|
|
412
|
-
encryptRemoveReaction(
|
|
657
|
+
encryptRemoveReaction(params: EncryptReactionParams): SendPayload;
|
|
413
658
|
|
|
414
659
|
/** Encrypt a stream (e.g. media). */
|
|
415
660
|
encryptStream(plaintext: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
@@ -417,33 +662,59 @@ interface ChatCrypto {
|
|
|
417
662
|
/** Decrypt a streaming-encrypted payload (e.g. media). */
|
|
418
663
|
decryptStream(encrypted: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
419
664
|
|
|
665
|
+
/** Create an incremental stream encryptor for large payloads. */
|
|
666
|
+
streamEncryptor(conversationKey: Uint8Array): StreamEncryptor;
|
|
667
|
+
|
|
668
|
+
/** Create an incremental stream decryptor for large payloads. */
|
|
669
|
+
streamDecryptor(conversationKey: Uint8Array): StreamDecryptor;
|
|
670
|
+
|
|
420
671
|
/** Encrypt a UTF-8 string and return base64 ciphertext. Use for metadata fields like group names. */
|
|
421
672
|
encrypt(plaintext: string, conversationKey: Uint8Array): string;
|
|
422
673
|
|
|
423
674
|
/** Decrypt a base64-encoded ciphertext and return the UTF-8 plaintext. Use for metadata fields like group names. */
|
|
424
675
|
decrypt(ciphertextB64: string, conversationKey: Uint8Array): string;
|
|
425
676
|
|
|
426
|
-
/** Encrypt a conversation key for one or more recipients. */
|
|
427
|
-
encryptConversationKeyForRecipients(conversationKey: Uint8Array, recipients: RecipientInput[]): EncryptedKeyForRecipient[];
|
|
428
|
-
|
|
429
677
|
/**
|
|
430
|
-
* Prepare conversation
|
|
678
|
+
* Prepare a signed conversation-key change, ready to send to the X API.
|
|
431
679
|
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
680
|
+
* Use this to start a one-to-one or rotate an existing conversation's key
|
|
681
|
+
* (one-to-one or group). Creating a group or adding members requires a
|
|
682
|
+
* paired group signature as well — use prepareGroupCreate or
|
|
683
|
+
* prepareGroupMembersChange for those.
|
|
436
684
|
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
685
|
+
* Pass the flat array of public keys (self plus recipients) from the X API
|
|
686
|
+
* in params.publicKeys. Omit params.conversationId for a one-to-one (it is
|
|
687
|
+
* derived from the two participants); pass the existing id for a group key
|
|
688
|
+
* rotation.
|
|
689
|
+
*
|
|
690
|
+
* @returns PreparedConversationChange ready to POST to the API
|
|
439
691
|
*/
|
|
440
|
-
|
|
692
|
+
prepareConversationKeyChange(params: ConversationKeyChangeParams): PreparedConversationChange;
|
|
441
693
|
|
|
442
|
-
/**
|
|
443
|
-
|
|
694
|
+
/**
|
|
695
|
+
* Prepare a signed group member-add change, ready to send to the X API.
|
|
696
|
+
*
|
|
697
|
+
* Use this when adding members to an existing group. Creating the group is
|
|
698
|
+
* prepareGroupCreate; a key rotation without a roster change is
|
|
699
|
+
* prepareConversationKeyChange.
|
|
700
|
+
*
|
|
701
|
+
* @returns PreparedConversationChange with two action signatures: the
|
|
702
|
+
* conversation-key change and the member add
|
|
703
|
+
*/
|
|
704
|
+
prepareGroupMembersChange(params: GroupMembersChangeParams): PreparedConversationChange;
|
|
444
705
|
|
|
445
|
-
/**
|
|
446
|
-
|
|
706
|
+
/**
|
|
707
|
+
* Prepare a signed group create, ready to send to the X API.
|
|
708
|
+
*
|
|
709
|
+
* Use this once, when creating a group (conversationId is the g-prefixed id
|
|
710
|
+
* minted by the initialize endpoint). Later key rotations use
|
|
711
|
+
* prepareConversationKeyChange; roster additions use
|
|
712
|
+
* prepareGroupMembersChange.
|
|
713
|
+
*
|
|
714
|
+
* @returns PreparedConversationChange with two action signatures: the
|
|
715
|
+
* conversation-key change and the group create
|
|
716
|
+
*/
|
|
717
|
+
prepareGroupCreate(params: GroupCreateParams): PreparedConversationChange;
|
|
447
718
|
}
|
|
448
719
|
|
|
449
720
|
/** Internal crypto engine wrapped by ChatWithJuicebox. Not part of the public API. */
|
|
@@ -460,25 +731,25 @@ declare class Chat implements ChatCrypto {
|
|
|
460
731
|
hasIdentityKey(): boolean;
|
|
461
732
|
lock(): void;
|
|
462
733
|
decryptConversationKey(encryptedKeyB64: string): Uint8Array;
|
|
463
|
-
generateConversationKey(): Uint8Array;
|
|
464
734
|
extractConversationKeys(events: string[]): ConversationKeyResult;
|
|
465
735
|
decryptEvents(events: string[], signingKeys?: SigningKeyEntry[]): DecryptEventsResult;
|
|
466
|
-
decryptEvent(eventB64: string, conversationKeys
|
|
736
|
+
decryptEvent(eventB64: string, conversationKeys?: ConversationKeyMap | null, signingKeys?: SigningKeyEntry[]): Event;
|
|
467
737
|
sign(data: Uint8Array): Uint8Array;
|
|
468
738
|
verify(publicKeyB64: string, signature: Uint8Array, data: Uint8Array): boolean;
|
|
469
739
|
verifyKeyBinding(identityPublicKeyB64: string, signingPublicKeyB64: string, identityPublicKeySignatureB64: string): boolean;
|
|
470
|
-
encryptMessage(
|
|
471
|
-
encryptReply(
|
|
472
|
-
encryptAddReaction(
|
|
473
|
-
encryptRemoveReaction(
|
|
740
|
+
encryptMessage(params: EncryptMessageParams): SendPayload;
|
|
741
|
+
encryptReply(params: EncryptReplyParams): SendPayload;
|
|
742
|
+
encryptAddReaction(params: EncryptReactionParams): SendPayload;
|
|
743
|
+
encryptRemoveReaction(params: EncryptReactionParams): SendPayload;
|
|
474
744
|
encryptStream(plaintext: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
475
745
|
decryptStream(encrypted: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
746
|
+
streamEncryptor(conversationKey: Uint8Array): StreamEncryptor;
|
|
747
|
+
streamDecryptor(conversationKey: Uint8Array): StreamDecryptor;
|
|
476
748
|
encrypt(plaintext: string, conversationKey: Uint8Array): string;
|
|
477
749
|
decrypt(ciphertextB64: string, conversationKey: Uint8Array): string;
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
signKeyChange(publicKeyVersion: string, messageId: string, senderId: string, conversationId: string, conversationKeyVersion: string, conversationKey: Uint8Array): ActionSignature;
|
|
750
|
+
prepareConversationKeyChange(params: ConversationKeyChangeParams): PreparedConversationChange;
|
|
751
|
+
prepareGroupMembersChange(params: GroupMembersChangeParams): PreparedConversationChange;
|
|
752
|
+
prepareGroupCreate(params: GroupCreateParams): PreparedConversationChange;
|
|
482
753
|
}
|
|
483
754
|
|
|
484
755
|
/**
|
|
@@ -497,6 +768,11 @@ export declare class ChatWithJuicebox implements ChatCrypto {
|
|
|
497
768
|
delete(): Promise<void>;
|
|
498
769
|
/** The new PIN must meet the same strength requirements as setup(). */
|
|
499
770
|
changePin(oldPin: string | Uint8Array, newPin: string | Uint8Array): Promise<void>;
|
|
771
|
+
/**
|
|
772
|
+
* Re-create the Juicebox client from a new config (e.g. refreshed auth
|
|
773
|
+
* tokens) and re-resolve the PIN guess budget from it; an explicit
|
|
774
|
+
* createChat `maxGuessCount` override keeps winning.
|
|
775
|
+
*/
|
|
500
776
|
updateConfig(juiceboxConfig: string): void;
|
|
501
777
|
|
|
502
778
|
setRejectUnverified(reject: boolean): void;
|
|
@@ -509,31 +785,43 @@ export declare class ChatWithJuicebox implements ChatCrypto {
|
|
|
509
785
|
hasIdentityKey(): boolean;
|
|
510
786
|
lock(): void;
|
|
511
787
|
decryptConversationKey(encryptedKeyB64: string): Uint8Array;
|
|
512
|
-
generateConversationKey(): Uint8Array;
|
|
513
788
|
extractConversationKeys(events: string[]): ConversationKeyResult;
|
|
514
789
|
decryptEvents(events: string[], signingKeys?: SigningKeyEntry[]): DecryptEventsResult;
|
|
515
|
-
decryptEvent(eventB64: string, conversationKeys
|
|
790
|
+
decryptEvent(eventB64: string, conversationKeys?: ConversationKeyMap | null, signingKeys?: SigningKeyEntry[]): Event;
|
|
516
791
|
sign(data: Uint8Array): Uint8Array;
|
|
517
792
|
verify(publicKeyB64: string, signature: Uint8Array, data: Uint8Array): boolean;
|
|
518
793
|
verifyKeyBinding(identityPublicKeyB64: string, signingPublicKeyB64: string, identityPublicKeySignatureB64: string): boolean;
|
|
519
|
-
encryptMessage(
|
|
520
|
-
encryptReply(
|
|
521
|
-
encryptAddReaction(
|
|
522
|
-
encryptRemoveReaction(
|
|
794
|
+
encryptMessage(params: EncryptMessageParams): SendPayload;
|
|
795
|
+
encryptReply(params: EncryptReplyParams): SendPayload;
|
|
796
|
+
encryptAddReaction(params: EncryptReactionParams): SendPayload;
|
|
797
|
+
encryptRemoveReaction(params: EncryptReactionParams): SendPayload;
|
|
523
798
|
encryptStream(plaintext: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
524
799
|
decryptStream(encrypted: Uint8Array, conversationKey: Uint8Array): Uint8Array;
|
|
800
|
+
streamEncryptor(conversationKey: Uint8Array): StreamEncryptor;
|
|
801
|
+
streamDecryptor(conversationKey: Uint8Array): StreamDecryptor;
|
|
525
802
|
encrypt(plaintext: string, conversationKey: Uint8Array): string;
|
|
526
803
|
decrypt(ciphertextB64: string, conversationKey: Uint8Array): string;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
804
|
+
prepareConversationKeyChange(params: ConversationKeyChangeParams): PreparedConversationChange;
|
|
805
|
+
prepareGroupMembersChange(params: GroupMembersChangeParams): PreparedConversationChange;
|
|
806
|
+
prepareGroupCreate(params: GroupCreateParams): PreparedConversationChange;
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Release the WASM-side crypto engine: clears key material (`lock()`) and
|
|
810
|
+
* frees the underlying WASM object. The instance must not be used
|
|
811
|
+
* afterwards. When reusing the instance, `lock()` alone suffices for key
|
|
812
|
+
* hygiene.
|
|
813
|
+
*/
|
|
814
|
+
free(): void;
|
|
531
815
|
}
|
|
532
816
|
|
|
533
817
|
/**
|
|
534
818
|
* Create a Chat instance with integrated Juicebox key storage.
|
|
535
819
|
*
|
|
536
820
|
* Each call creates an independent instance with its own Juicebox client.
|
|
821
|
+
* The Juicebox auth-token callback is a process-wide global that each
|
|
822
|
+
* instance re-arms before its own operations, so sequential use of multiple
|
|
823
|
+
* instances is fine but concurrent Juicebox operations across instances in
|
|
824
|
+
* one process are not supported.
|
|
537
825
|
*/
|
|
538
826
|
export declare function createChat(options: CreateChatOptions): Promise<ChatWithJuicebox>;
|
|
539
827
|
|