@voidly/agent-sdk 2.1.0 → 3.0.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/index.d.mts +141 -1
- package/dist/index.d.ts +141 -1
- package/dist/index.js +2407 -275
- package/dist/index.mjs +2407 -275
- package/package.json +16 -4
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ export { decodeBase64, decodeUTF8, encodeBase64, encodeUTF8 } from 'tweetnacl-ut
|
|
|
8
8
|
* All encryption and decryption happens CLIENT-SIDE.
|
|
9
9
|
* The Voidly relay server NEVER sees private keys or plaintext.
|
|
10
10
|
*
|
|
11
|
-
* Crypto: X25519 key exchange
|
|
11
|
+
* Crypto: X25519 + ML-KEM-768 hybrid key exchange, XSalsa20-Poly1305, Ed25519 signatures
|
|
12
12
|
* Identity: did:voidly:{base58-encoded-ed25519-pubkey}
|
|
13
13
|
*/
|
|
14
14
|
|
|
@@ -17,12 +17,23 @@ interface AgentIdentity {
|
|
|
17
17
|
apiKey: string;
|
|
18
18
|
signingKeyPair: nacl.SignKeyPair;
|
|
19
19
|
encryptionKeyPair: nacl.BoxKeyPair;
|
|
20
|
+
/** ML-KEM-768 post-quantum keypair (optional — enables hybrid PQ encryption) */
|
|
21
|
+
mlkemPublicKey?: Uint8Array;
|
|
22
|
+
mlkemSecretKey?: Uint8Array;
|
|
20
23
|
}
|
|
21
24
|
interface AgentProfile {
|
|
22
25
|
did: string;
|
|
23
26
|
name: string | null;
|
|
24
27
|
signing_public_key: string;
|
|
25
28
|
encryption_public_key: string;
|
|
29
|
+
/** ML-KEM-768 public key (base64, 1184 bytes) — present if agent supports PQ */
|
|
30
|
+
mlkem_public_key?: string;
|
|
31
|
+
/** X3DH signed prekey bundle — enables async key agreement with offline agents */
|
|
32
|
+
signed_prekey?: {
|
|
33
|
+
public_key: string;
|
|
34
|
+
signature: string;
|
|
35
|
+
id: number;
|
|
36
|
+
};
|
|
26
37
|
capabilities: string[];
|
|
27
38
|
message_count: number;
|
|
28
39
|
}
|
|
@@ -64,6 +75,16 @@ interface VoidlyAgentConfig {
|
|
|
64
75
|
requireSignatures?: boolean;
|
|
65
76
|
/** Request timeout in milliseconds (default: 30000) */
|
|
66
77
|
timeout?: number;
|
|
78
|
+
/** Enable post-quantum hybrid encryption — ML-KEM-768 + X25519 (default: true) */
|
|
79
|
+
postQuantum?: boolean;
|
|
80
|
+
/** Enable deniable messaging — HMAC authentication instead of Ed25519 signatures (default: false) */
|
|
81
|
+
deniable?: boolean;
|
|
82
|
+
/** Enable Double Ratchet with DH ratchet for post-compromise recovery (default: true) */
|
|
83
|
+
doubleRatchet?: boolean;
|
|
84
|
+
/** Random delay range in ms before sending (metadata timing protection, default: 0 = disabled) */
|
|
85
|
+
jitterMs?: number;
|
|
86
|
+
/** Use long-poll for listen() instead of short-interval polling (default: true) */
|
|
87
|
+
longPoll?: boolean;
|
|
67
88
|
}
|
|
68
89
|
interface ListenOptions {
|
|
69
90
|
/** Milliseconds between polls (default: 2000, min: 500) */
|
|
@@ -143,6 +164,15 @@ declare class VoidlyAgent {
|
|
|
143
164
|
private sealedSender;
|
|
144
165
|
private requireSignatures;
|
|
145
166
|
private timeout;
|
|
167
|
+
private postQuantum;
|
|
168
|
+
private deniable;
|
|
169
|
+
private doubleRatchet;
|
|
170
|
+
private jitterMs;
|
|
171
|
+
private longPoll;
|
|
172
|
+
private mlkemPublicKey;
|
|
173
|
+
private mlkemSecretKey;
|
|
174
|
+
private _signedPrekey;
|
|
175
|
+
private _signedPrekeyId;
|
|
146
176
|
private _pinnedDids;
|
|
147
177
|
private _listeners;
|
|
148
178
|
private _conversations;
|
|
@@ -169,6 +199,22 @@ declare class VoidlyAgent {
|
|
|
169
199
|
apiKey: string;
|
|
170
200
|
signingSecretKey: string;
|
|
171
201
|
encryptionSecretKey: string;
|
|
202
|
+
ratchetStates?: Record<string, {
|
|
203
|
+
sendChainKey: string;
|
|
204
|
+
sendStep: number;
|
|
205
|
+
recvChainKey: string;
|
|
206
|
+
recvStep: number;
|
|
207
|
+
rootKey?: string;
|
|
208
|
+
dhSendSecretKey?: string;
|
|
209
|
+
dhSendPublicKey?: string;
|
|
210
|
+
dhRecvPubKey?: string;
|
|
211
|
+
prevSendStep?: number;
|
|
212
|
+
}>;
|
|
213
|
+
mlkemPublicKey?: string;
|
|
214
|
+
mlkemSecretKey?: string;
|
|
215
|
+
signedPrekeySecret?: string;
|
|
216
|
+
signedPrekeyPublic?: string;
|
|
217
|
+
signedPrekeyId?: number;
|
|
172
218
|
}, config?: VoidlyAgentConfig): VoidlyAgent;
|
|
173
219
|
/**
|
|
174
220
|
* Export credentials for persistence.
|
|
@@ -181,6 +227,22 @@ declare class VoidlyAgent {
|
|
|
181
227
|
encryptionSecretKey: string;
|
|
182
228
|
signingPublicKey: string;
|
|
183
229
|
encryptionPublicKey: string;
|
|
230
|
+
ratchetStates?: Record<string, {
|
|
231
|
+
sendChainKey: string;
|
|
232
|
+
sendStep: number;
|
|
233
|
+
recvChainKey: string;
|
|
234
|
+
recvStep: number;
|
|
235
|
+
rootKey?: string;
|
|
236
|
+
dhSendSecretKey?: string;
|
|
237
|
+
dhSendPublicKey?: string;
|
|
238
|
+
dhRecvPubKey?: string;
|
|
239
|
+
prevSendStep?: number;
|
|
240
|
+
}>;
|
|
241
|
+
mlkemPublicKey?: string;
|
|
242
|
+
mlkemSecretKey?: string;
|
|
243
|
+
signedPrekeySecret?: string;
|
|
244
|
+
signedPrekeyPublic?: string;
|
|
245
|
+
signedPrekeyId?: number;
|
|
184
246
|
};
|
|
185
247
|
/**
|
|
186
248
|
* Get the number of messages that failed to decrypt.
|
|
@@ -810,6 +872,82 @@ declare class VoidlyAgent {
|
|
|
810
872
|
status: string;
|
|
811
873
|
warning?: string;
|
|
812
874
|
}>;
|
|
875
|
+
/**
|
|
876
|
+
* Upload prekey bundle for X3DH async key agreement.
|
|
877
|
+
* Other agents can fetch your prekeys and establish encrypted sessions
|
|
878
|
+
* even while you're offline.
|
|
879
|
+
*
|
|
880
|
+
* @param count Number of one-time prekeys to upload (default: 20)
|
|
881
|
+
*/
|
|
882
|
+
uploadPrekeys(count?: number): Promise<{
|
|
883
|
+
uploaded: number;
|
|
884
|
+
signed_prekey_updated: boolean;
|
|
885
|
+
}>;
|
|
886
|
+
/**
|
|
887
|
+
* Fetch another agent's prekey bundle for X3DH key agreement.
|
|
888
|
+
* Use this to establish an encrypted session with an offline agent.
|
|
889
|
+
*/
|
|
890
|
+
fetchPrekeys(did: string): Promise<{
|
|
891
|
+
identity_key: string;
|
|
892
|
+
signing_key: string;
|
|
893
|
+
signed_prekey: {
|
|
894
|
+
public_key: string;
|
|
895
|
+
signature: string;
|
|
896
|
+
id: number;
|
|
897
|
+
} | null;
|
|
898
|
+
one_time_prekey: {
|
|
899
|
+
id: number;
|
|
900
|
+
public_key: string;
|
|
901
|
+
} | null;
|
|
902
|
+
mlkem_public_key: string | null;
|
|
903
|
+
} | null>;
|
|
904
|
+
/**
|
|
905
|
+
* Create a channel with client-side encryption.
|
|
906
|
+
* The channel symmetric key is generated locally and encrypted per-member.
|
|
907
|
+
* The relay NEVER sees the plaintext channel key — true E2E for groups.
|
|
908
|
+
*/
|
|
909
|
+
createEncryptedChannel(options: {
|
|
910
|
+
name: string;
|
|
911
|
+
description?: string;
|
|
912
|
+
topic?: string;
|
|
913
|
+
private?: boolean;
|
|
914
|
+
}): Promise<{
|
|
915
|
+
id: string;
|
|
916
|
+
name: string;
|
|
917
|
+
channelKey: Uint8Array;
|
|
918
|
+
}>;
|
|
919
|
+
/**
|
|
920
|
+
* Post a client-side encrypted message to a channel.
|
|
921
|
+
* Uses the channel's shared symmetric key — relay never sees plaintext.
|
|
922
|
+
*
|
|
923
|
+
* @param channelId Channel ID
|
|
924
|
+
* @param message Plaintext message
|
|
925
|
+
* @param channelKey 32-byte symmetric channel key (from createEncryptedChannel or received via invite)
|
|
926
|
+
*/
|
|
927
|
+
postEncrypted(channelId: string, message: string, channelKey: Uint8Array): Promise<{
|
|
928
|
+
id: string;
|
|
929
|
+
}>;
|
|
930
|
+
/**
|
|
931
|
+
* Read and decrypt channel messages using client-side channel key.
|
|
932
|
+
* Ignores server-side encryption entirely — true E2E.
|
|
933
|
+
*
|
|
934
|
+
* @param channelId Channel ID
|
|
935
|
+
* @param channelKey 32-byte symmetric channel key
|
|
936
|
+
*/
|
|
937
|
+
readEncrypted(channelId: string, channelKey: Uint8Array, options?: {
|
|
938
|
+
since?: string;
|
|
939
|
+
before?: string;
|
|
940
|
+
limit?: number;
|
|
941
|
+
}): Promise<{
|
|
942
|
+
messages: Array<{
|
|
943
|
+
id: string;
|
|
944
|
+
from: string;
|
|
945
|
+
content: string;
|
|
946
|
+
timestamp: string;
|
|
947
|
+
signatureValid: boolean;
|
|
948
|
+
}>;
|
|
949
|
+
count: number;
|
|
950
|
+
}>;
|
|
813
951
|
/**
|
|
814
952
|
* Listen for incoming messages with an event-driven callback.
|
|
815
953
|
* Uses adaptive polling — speeds up when messages are flowing, slows down when idle.
|
|
@@ -878,6 +1016,8 @@ declare class VoidlyAgent {
|
|
|
878
1016
|
* ```
|
|
879
1017
|
*/
|
|
880
1018
|
conversation(peerDid: string, threadId?: string): Conversation;
|
|
1019
|
+
/** @internal Fetch with timeout via AbortController */
|
|
1020
|
+
private _timedFetch;
|
|
881
1021
|
/** @internal Auto-pin keys on first contact (TOFU) */
|
|
882
1022
|
private _autoPinKeys;
|
|
883
1023
|
/** @internal Fetch with exponential backoff retry */
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { decodeBase64, decodeUTF8, encodeBase64, encodeUTF8 } from 'tweetnacl-ut
|
|
|
8
8
|
* All encryption and decryption happens CLIENT-SIDE.
|
|
9
9
|
* The Voidly relay server NEVER sees private keys or plaintext.
|
|
10
10
|
*
|
|
11
|
-
* Crypto: X25519 key exchange
|
|
11
|
+
* Crypto: X25519 + ML-KEM-768 hybrid key exchange, XSalsa20-Poly1305, Ed25519 signatures
|
|
12
12
|
* Identity: did:voidly:{base58-encoded-ed25519-pubkey}
|
|
13
13
|
*/
|
|
14
14
|
|
|
@@ -17,12 +17,23 @@ interface AgentIdentity {
|
|
|
17
17
|
apiKey: string;
|
|
18
18
|
signingKeyPair: nacl.SignKeyPair;
|
|
19
19
|
encryptionKeyPair: nacl.BoxKeyPair;
|
|
20
|
+
/** ML-KEM-768 post-quantum keypair (optional — enables hybrid PQ encryption) */
|
|
21
|
+
mlkemPublicKey?: Uint8Array;
|
|
22
|
+
mlkemSecretKey?: Uint8Array;
|
|
20
23
|
}
|
|
21
24
|
interface AgentProfile {
|
|
22
25
|
did: string;
|
|
23
26
|
name: string | null;
|
|
24
27
|
signing_public_key: string;
|
|
25
28
|
encryption_public_key: string;
|
|
29
|
+
/** ML-KEM-768 public key (base64, 1184 bytes) — present if agent supports PQ */
|
|
30
|
+
mlkem_public_key?: string;
|
|
31
|
+
/** X3DH signed prekey bundle — enables async key agreement with offline agents */
|
|
32
|
+
signed_prekey?: {
|
|
33
|
+
public_key: string;
|
|
34
|
+
signature: string;
|
|
35
|
+
id: number;
|
|
36
|
+
};
|
|
26
37
|
capabilities: string[];
|
|
27
38
|
message_count: number;
|
|
28
39
|
}
|
|
@@ -64,6 +75,16 @@ interface VoidlyAgentConfig {
|
|
|
64
75
|
requireSignatures?: boolean;
|
|
65
76
|
/** Request timeout in milliseconds (default: 30000) */
|
|
66
77
|
timeout?: number;
|
|
78
|
+
/** Enable post-quantum hybrid encryption — ML-KEM-768 + X25519 (default: true) */
|
|
79
|
+
postQuantum?: boolean;
|
|
80
|
+
/** Enable deniable messaging — HMAC authentication instead of Ed25519 signatures (default: false) */
|
|
81
|
+
deniable?: boolean;
|
|
82
|
+
/** Enable Double Ratchet with DH ratchet for post-compromise recovery (default: true) */
|
|
83
|
+
doubleRatchet?: boolean;
|
|
84
|
+
/** Random delay range in ms before sending (metadata timing protection, default: 0 = disabled) */
|
|
85
|
+
jitterMs?: number;
|
|
86
|
+
/** Use long-poll for listen() instead of short-interval polling (default: true) */
|
|
87
|
+
longPoll?: boolean;
|
|
67
88
|
}
|
|
68
89
|
interface ListenOptions {
|
|
69
90
|
/** Milliseconds between polls (default: 2000, min: 500) */
|
|
@@ -143,6 +164,15 @@ declare class VoidlyAgent {
|
|
|
143
164
|
private sealedSender;
|
|
144
165
|
private requireSignatures;
|
|
145
166
|
private timeout;
|
|
167
|
+
private postQuantum;
|
|
168
|
+
private deniable;
|
|
169
|
+
private doubleRatchet;
|
|
170
|
+
private jitterMs;
|
|
171
|
+
private longPoll;
|
|
172
|
+
private mlkemPublicKey;
|
|
173
|
+
private mlkemSecretKey;
|
|
174
|
+
private _signedPrekey;
|
|
175
|
+
private _signedPrekeyId;
|
|
146
176
|
private _pinnedDids;
|
|
147
177
|
private _listeners;
|
|
148
178
|
private _conversations;
|
|
@@ -169,6 +199,22 @@ declare class VoidlyAgent {
|
|
|
169
199
|
apiKey: string;
|
|
170
200
|
signingSecretKey: string;
|
|
171
201
|
encryptionSecretKey: string;
|
|
202
|
+
ratchetStates?: Record<string, {
|
|
203
|
+
sendChainKey: string;
|
|
204
|
+
sendStep: number;
|
|
205
|
+
recvChainKey: string;
|
|
206
|
+
recvStep: number;
|
|
207
|
+
rootKey?: string;
|
|
208
|
+
dhSendSecretKey?: string;
|
|
209
|
+
dhSendPublicKey?: string;
|
|
210
|
+
dhRecvPubKey?: string;
|
|
211
|
+
prevSendStep?: number;
|
|
212
|
+
}>;
|
|
213
|
+
mlkemPublicKey?: string;
|
|
214
|
+
mlkemSecretKey?: string;
|
|
215
|
+
signedPrekeySecret?: string;
|
|
216
|
+
signedPrekeyPublic?: string;
|
|
217
|
+
signedPrekeyId?: number;
|
|
172
218
|
}, config?: VoidlyAgentConfig): VoidlyAgent;
|
|
173
219
|
/**
|
|
174
220
|
* Export credentials for persistence.
|
|
@@ -181,6 +227,22 @@ declare class VoidlyAgent {
|
|
|
181
227
|
encryptionSecretKey: string;
|
|
182
228
|
signingPublicKey: string;
|
|
183
229
|
encryptionPublicKey: string;
|
|
230
|
+
ratchetStates?: Record<string, {
|
|
231
|
+
sendChainKey: string;
|
|
232
|
+
sendStep: number;
|
|
233
|
+
recvChainKey: string;
|
|
234
|
+
recvStep: number;
|
|
235
|
+
rootKey?: string;
|
|
236
|
+
dhSendSecretKey?: string;
|
|
237
|
+
dhSendPublicKey?: string;
|
|
238
|
+
dhRecvPubKey?: string;
|
|
239
|
+
prevSendStep?: number;
|
|
240
|
+
}>;
|
|
241
|
+
mlkemPublicKey?: string;
|
|
242
|
+
mlkemSecretKey?: string;
|
|
243
|
+
signedPrekeySecret?: string;
|
|
244
|
+
signedPrekeyPublic?: string;
|
|
245
|
+
signedPrekeyId?: number;
|
|
184
246
|
};
|
|
185
247
|
/**
|
|
186
248
|
* Get the number of messages that failed to decrypt.
|
|
@@ -810,6 +872,82 @@ declare class VoidlyAgent {
|
|
|
810
872
|
status: string;
|
|
811
873
|
warning?: string;
|
|
812
874
|
}>;
|
|
875
|
+
/**
|
|
876
|
+
* Upload prekey bundle for X3DH async key agreement.
|
|
877
|
+
* Other agents can fetch your prekeys and establish encrypted sessions
|
|
878
|
+
* even while you're offline.
|
|
879
|
+
*
|
|
880
|
+
* @param count Number of one-time prekeys to upload (default: 20)
|
|
881
|
+
*/
|
|
882
|
+
uploadPrekeys(count?: number): Promise<{
|
|
883
|
+
uploaded: number;
|
|
884
|
+
signed_prekey_updated: boolean;
|
|
885
|
+
}>;
|
|
886
|
+
/**
|
|
887
|
+
* Fetch another agent's prekey bundle for X3DH key agreement.
|
|
888
|
+
* Use this to establish an encrypted session with an offline agent.
|
|
889
|
+
*/
|
|
890
|
+
fetchPrekeys(did: string): Promise<{
|
|
891
|
+
identity_key: string;
|
|
892
|
+
signing_key: string;
|
|
893
|
+
signed_prekey: {
|
|
894
|
+
public_key: string;
|
|
895
|
+
signature: string;
|
|
896
|
+
id: number;
|
|
897
|
+
} | null;
|
|
898
|
+
one_time_prekey: {
|
|
899
|
+
id: number;
|
|
900
|
+
public_key: string;
|
|
901
|
+
} | null;
|
|
902
|
+
mlkem_public_key: string | null;
|
|
903
|
+
} | null>;
|
|
904
|
+
/**
|
|
905
|
+
* Create a channel with client-side encryption.
|
|
906
|
+
* The channel symmetric key is generated locally and encrypted per-member.
|
|
907
|
+
* The relay NEVER sees the plaintext channel key — true E2E for groups.
|
|
908
|
+
*/
|
|
909
|
+
createEncryptedChannel(options: {
|
|
910
|
+
name: string;
|
|
911
|
+
description?: string;
|
|
912
|
+
topic?: string;
|
|
913
|
+
private?: boolean;
|
|
914
|
+
}): Promise<{
|
|
915
|
+
id: string;
|
|
916
|
+
name: string;
|
|
917
|
+
channelKey: Uint8Array;
|
|
918
|
+
}>;
|
|
919
|
+
/**
|
|
920
|
+
* Post a client-side encrypted message to a channel.
|
|
921
|
+
* Uses the channel's shared symmetric key — relay never sees plaintext.
|
|
922
|
+
*
|
|
923
|
+
* @param channelId Channel ID
|
|
924
|
+
* @param message Plaintext message
|
|
925
|
+
* @param channelKey 32-byte symmetric channel key (from createEncryptedChannel or received via invite)
|
|
926
|
+
*/
|
|
927
|
+
postEncrypted(channelId: string, message: string, channelKey: Uint8Array): Promise<{
|
|
928
|
+
id: string;
|
|
929
|
+
}>;
|
|
930
|
+
/**
|
|
931
|
+
* Read and decrypt channel messages using client-side channel key.
|
|
932
|
+
* Ignores server-side encryption entirely — true E2E.
|
|
933
|
+
*
|
|
934
|
+
* @param channelId Channel ID
|
|
935
|
+
* @param channelKey 32-byte symmetric channel key
|
|
936
|
+
*/
|
|
937
|
+
readEncrypted(channelId: string, channelKey: Uint8Array, options?: {
|
|
938
|
+
since?: string;
|
|
939
|
+
before?: string;
|
|
940
|
+
limit?: number;
|
|
941
|
+
}): Promise<{
|
|
942
|
+
messages: Array<{
|
|
943
|
+
id: string;
|
|
944
|
+
from: string;
|
|
945
|
+
content: string;
|
|
946
|
+
timestamp: string;
|
|
947
|
+
signatureValid: boolean;
|
|
948
|
+
}>;
|
|
949
|
+
count: number;
|
|
950
|
+
}>;
|
|
813
951
|
/**
|
|
814
952
|
* Listen for incoming messages with an event-driven callback.
|
|
815
953
|
* Uses adaptive polling — speeds up when messages are flowing, slows down when idle.
|
|
@@ -878,6 +1016,8 @@ declare class VoidlyAgent {
|
|
|
878
1016
|
* ```
|
|
879
1017
|
*/
|
|
880
1018
|
conversation(peerDid: string, threadId?: string): Conversation;
|
|
1019
|
+
/** @internal Fetch with timeout via AbortController */
|
|
1020
|
+
private _timedFetch;
|
|
881
1021
|
/** @internal Auto-pin keys on first contact (TOFU) */
|
|
882
1022
|
private _autoPinKeys;
|
|
883
1023
|
/** @internal Fetch with exponential backoff retry */
|