@voidly/agent-sdk 2.2.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 CHANGED
@@ -28,6 +28,12 @@ interface AgentProfile {
28
28
  encryption_public_key: string;
29
29
  /** ML-KEM-768 public key (base64, 1184 bytes) — present if agent supports PQ */
30
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
+ };
31
37
  capabilities: string[];
32
38
  message_count: number;
33
39
  }
@@ -71,6 +77,14 @@ interface VoidlyAgentConfig {
71
77
  timeout?: number;
72
78
  /** Enable post-quantum hybrid encryption — ML-KEM-768 + X25519 (default: true) */
73
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;
74
88
  }
75
89
  interface ListenOptions {
76
90
  /** Milliseconds between polls (default: 2000, min: 500) */
@@ -151,8 +165,14 @@ declare class VoidlyAgent {
151
165
  private requireSignatures;
152
166
  private timeout;
153
167
  private postQuantum;
168
+ private deniable;
169
+ private doubleRatchet;
170
+ private jitterMs;
171
+ private longPoll;
154
172
  private mlkemPublicKey;
155
173
  private mlkemSecretKey;
174
+ private _signedPrekey;
175
+ private _signedPrekeyId;
156
176
  private _pinnedDids;
157
177
  private _listeners;
158
178
  private _conversations;
@@ -184,9 +204,17 @@ declare class VoidlyAgent {
184
204
  sendStep: number;
185
205
  recvChainKey: string;
186
206
  recvStep: number;
207
+ rootKey?: string;
208
+ dhSendSecretKey?: string;
209
+ dhSendPublicKey?: string;
210
+ dhRecvPubKey?: string;
211
+ prevSendStep?: number;
187
212
  }>;
188
213
  mlkemPublicKey?: string;
189
214
  mlkemSecretKey?: string;
215
+ signedPrekeySecret?: string;
216
+ signedPrekeyPublic?: string;
217
+ signedPrekeyId?: number;
190
218
  }, config?: VoidlyAgentConfig): VoidlyAgent;
191
219
  /**
192
220
  * Export credentials for persistence.
@@ -204,9 +232,17 @@ declare class VoidlyAgent {
204
232
  sendStep: number;
205
233
  recvChainKey: string;
206
234
  recvStep: number;
235
+ rootKey?: string;
236
+ dhSendSecretKey?: string;
237
+ dhSendPublicKey?: string;
238
+ dhRecvPubKey?: string;
239
+ prevSendStep?: number;
207
240
  }>;
208
241
  mlkemPublicKey?: string;
209
242
  mlkemSecretKey?: string;
243
+ signedPrekeySecret?: string;
244
+ signedPrekeyPublic?: string;
245
+ signedPrekeyId?: number;
210
246
  };
211
247
  /**
212
248
  * Get the number of messages that failed to decrypt.
@@ -836,6 +872,82 @@ declare class VoidlyAgent {
836
872
  status: string;
837
873
  warning?: string;
838
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
+ }>;
839
951
  /**
840
952
  * Listen for incoming messages with an event-driven callback.
841
953
  * Uses adaptive polling — speeds up when messages are flowing, slows down when idle.
package/dist/index.d.ts CHANGED
@@ -28,6 +28,12 @@ interface AgentProfile {
28
28
  encryption_public_key: string;
29
29
  /** ML-KEM-768 public key (base64, 1184 bytes) — present if agent supports PQ */
30
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
+ };
31
37
  capabilities: string[];
32
38
  message_count: number;
33
39
  }
@@ -71,6 +77,14 @@ interface VoidlyAgentConfig {
71
77
  timeout?: number;
72
78
  /** Enable post-quantum hybrid encryption — ML-KEM-768 + X25519 (default: true) */
73
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;
74
88
  }
75
89
  interface ListenOptions {
76
90
  /** Milliseconds between polls (default: 2000, min: 500) */
@@ -151,8 +165,14 @@ declare class VoidlyAgent {
151
165
  private requireSignatures;
152
166
  private timeout;
153
167
  private postQuantum;
168
+ private deniable;
169
+ private doubleRatchet;
170
+ private jitterMs;
171
+ private longPoll;
154
172
  private mlkemPublicKey;
155
173
  private mlkemSecretKey;
174
+ private _signedPrekey;
175
+ private _signedPrekeyId;
156
176
  private _pinnedDids;
157
177
  private _listeners;
158
178
  private _conversations;
@@ -184,9 +204,17 @@ declare class VoidlyAgent {
184
204
  sendStep: number;
185
205
  recvChainKey: string;
186
206
  recvStep: number;
207
+ rootKey?: string;
208
+ dhSendSecretKey?: string;
209
+ dhSendPublicKey?: string;
210
+ dhRecvPubKey?: string;
211
+ prevSendStep?: number;
187
212
  }>;
188
213
  mlkemPublicKey?: string;
189
214
  mlkemSecretKey?: string;
215
+ signedPrekeySecret?: string;
216
+ signedPrekeyPublic?: string;
217
+ signedPrekeyId?: number;
190
218
  }, config?: VoidlyAgentConfig): VoidlyAgent;
191
219
  /**
192
220
  * Export credentials for persistence.
@@ -204,9 +232,17 @@ declare class VoidlyAgent {
204
232
  sendStep: number;
205
233
  recvChainKey: string;
206
234
  recvStep: number;
235
+ rootKey?: string;
236
+ dhSendSecretKey?: string;
237
+ dhSendPublicKey?: string;
238
+ dhRecvPubKey?: string;
239
+ prevSendStep?: number;
207
240
  }>;
208
241
  mlkemPublicKey?: string;
209
242
  mlkemSecretKey?: string;
243
+ signedPrekeySecret?: string;
244
+ signedPrekeyPublic?: string;
245
+ signedPrekeyId?: number;
210
246
  };
211
247
  /**
212
248
  * Get the number of messages that failed to decrypt.
@@ -836,6 +872,82 @@ declare class VoidlyAgent {
836
872
  status: string;
837
873
  warning?: string;
838
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
+ }>;
839
951
  /**
840
952
  * Listen for incoming messages with an event-driven callback.
841
953
  * Uses adaptive polling — speeds up when messages are flowing, slows down when idle.