@vaultsandbox/client 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +190 -21
  2. package/README.md +3 -3
  3. package/dist/client.d.ts +11 -3
  4. package/dist/client.js +83 -30
  5. package/dist/client.js.map +1 -1
  6. package/dist/crypto/decrypt.js +12 -4
  7. package/dist/crypto/decrypt.js.map +1 -1
  8. package/dist/crypto/signature.js +3 -1
  9. package/dist/crypto/signature.js.map +1 -1
  10. package/dist/email.d.ts +2 -2
  11. package/dist/email.js +25 -12
  12. package/dist/email.js.map +1 -1
  13. package/dist/http/api-client.d.ts +4 -2
  14. package/dist/http/api-client.js +17 -3
  15. package/dist/http/api-client.js.map +1 -1
  16. package/dist/inbox.d.ts +69 -3
  17. package/dist/inbox.js +142 -14
  18. package/dist/inbox.js.map +1 -1
  19. package/dist/index.d.ts +2 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/strategies/delivery-strategy.d.ts +7 -5
  23. package/dist/strategies/polling-strategy.d.ts +5 -5
  24. package/dist/strategies/polling-strategy.js +46 -21
  25. package/dist/strategies/polling-strategy.js.map +1 -1
  26. package/dist/strategies/sse-strategy.d.ts +8 -3
  27. package/dist/strategies/sse-strategy.js +112 -15
  28. package/dist/strategies/sse-strategy.js.map +1 -1
  29. package/dist/sync/inbox-sync.d.ts +31 -0
  30. package/dist/sync/inbox-sync.js +52 -0
  31. package/dist/sync/inbox-sync.js.map +1 -0
  32. package/dist/types/index.d.ts +64 -17
  33. package/dist/types/index.js.map +1 -1
  34. package/dist/utils/email-utils.d.ts +14 -3
  35. package/dist/utils/email-utils.js +41 -1
  36. package/dist/utils/email-utils.js.map +1 -1
  37. package/dist/utils/hash.d.ts +15 -0
  38. package/dist/utils/hash.js +31 -0
  39. package/dist/utils/hash.js.map +1 -0
  40. package/package.json +5 -5
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Inbox synchronization utilities for hash-based sync with deletion handling
3
+ */
4
+ import type { ApiClient } from '../http/api-client.js';
5
+ import type { EmailData } from '../types/index.js';
6
+ /**
7
+ * Result of a sync operation.
8
+ */
9
+ export interface SyncResult {
10
+ /** Emails that exist on the server but not locally */
11
+ added: EmailData[];
12
+ /** Email IDs that exist locally but not on the server */
13
+ deleted: string[];
14
+ /** Whether the inbox was already in sync (no changes) */
15
+ unchanged: boolean;
16
+ }
17
+ /**
18
+ * Synchronizes the local email cache with the server using hash comparison.
19
+ *
20
+ * This implements the spec's hash-based sync algorithm:
21
+ * 1. Compute local hash from current email IDs
22
+ * 2. Get server hash via /sync endpoint
23
+ * 3. If hashes match, no sync needed
24
+ * 4. If hashes differ, fetch full email list and reconcile
25
+ *
26
+ * @param apiClient - The API client for server communication
27
+ * @param emailAddress - The inbox email address
28
+ * @param localEmails - Map of local email IDs to EmailData
29
+ * @returns Promise resolving to sync result with added/deleted emails
30
+ */
31
+ export declare function syncInbox(apiClient: ApiClient, emailAddress: string, localEmails: Map<string, EmailData>): Promise<SyncResult>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Inbox synchronization utilities for hash-based sync with deletion handling
3
+ */
4
+ import createDebug from 'debug';
5
+ import { computeEmailsHash } from '../utils/hash.js';
6
+ const debug = createDebug('vaultsandbox:sync');
7
+ /**
8
+ * Synchronizes the local email cache with the server using hash comparison.
9
+ *
10
+ * This implements the spec's hash-based sync algorithm:
11
+ * 1. Compute local hash from current email IDs
12
+ * 2. Get server hash via /sync endpoint
13
+ * 3. If hashes match, no sync needed
14
+ * 4. If hashes differ, fetch full email list and reconcile
15
+ *
16
+ * @param apiClient - The API client for server communication
17
+ * @param emailAddress - The inbox email address
18
+ * @param localEmails - Map of local email IDs to EmailData
19
+ * @returns Promise resolving to sync result with added/deleted emails
20
+ */
21
+ export async function syncInbox(apiClient, emailAddress, localEmails) {
22
+ debug('Starting sync for inbox %s', emailAddress);
23
+ // Step 1: Compute local hash from current email IDs
24
+ const localIds = Array.from(localEmails.keys());
25
+ const localHash = computeEmailsHash(localIds);
26
+ debug('Computed local hash: %s (from %d emails)', localHash, localIds.length);
27
+ // Step 2: Get server hash
28
+ const syncStatus = await apiClient.getSyncStatus(emailAddress);
29
+ debug('Server hash: %s (with %d emails)', syncStatus.emailsHash, syncStatus.emailCount);
30
+ // Step 3: Compare hashes
31
+ if (localHash === syncStatus.emailsHash) {
32
+ debug('Hashes match - inbox %s is in sync', emailAddress);
33
+ return { added: [], deleted: [], unchanged: true };
34
+ }
35
+ debug('Hash mismatch detected for inbox %s - fetching full email list', emailAddress);
36
+ // Step 4: Fetch full email list from server
37
+ const serverEmails = await apiClient.listEmails(emailAddress, false);
38
+ const serverIds = new Set(serverEmails.map((e) => e.id));
39
+ const localIdSet = new Set(localIds);
40
+ // Step 5: Find new emails (on server but not local)
41
+ const newEmails = serverEmails.filter((e) => !localIdSet.has(e.id));
42
+ debug('Found %d new emails on server', newEmails.length);
43
+ // Step 6: Find deleted emails (local but not on server)
44
+ const deletedIds = localIds.filter((id) => !serverIds.has(id));
45
+ debug('Found %d emails deleted from server', deletedIds.length);
46
+ return {
47
+ added: newEmails,
48
+ deleted: deletedIds,
49
+ unchanged: false,
50
+ };
51
+ }
52
+ //# sourceMappingURL=inbox-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox-sync.js","sourceRoot":"","sources":["../../src/sync/inbox-sync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,WAAW,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD,MAAM,KAAK,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC;AAc/C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAAoB,EACpB,YAAoB,EACpB,WAAmC;IAEnC,KAAK,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;IAElD,oDAAoD;IACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC9C,KAAK,CAAC,0CAA0C,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE9E,0BAA0B;IAC1B,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC/D,KAAK,CAAC,kCAAkC,EAAE,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAExF,yBAAyB;IACzB,IAAI,SAAS,KAAK,UAAU,CAAC,UAAU,EAAE,CAAC;QACxC,KAAK,CAAC,oCAAoC,EAAE,YAAY,CAAC,CAAC;QAC1D,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,gEAAgE,EAAE,YAAY,CAAC,CAAC;IAEtF,4CAA4C;IAC5C,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAErC,oDAAoD;IACpD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpE,KAAK,CAAC,+BAA+B,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAEzD,wDAAwD;IACxD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/D,KAAK,CAAC,qCAAqC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEhE,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,KAAK;KACjB,CAAC;AACJ,CAAC"}
@@ -11,11 +11,10 @@ export interface ClientConfig {
11
11
  apiKey: string;
12
12
  /**
13
13
  * The email delivery strategy to use.
14
- * - `sse`: Use Server-Sent Events for real-time updates.
14
+ * - `sse`: Use Server-Sent Events for real-time updates (default).
15
15
  * - `polling`: Use traditional polling.
16
- * - `auto`: Use SSE if available, otherwise fall back to polling (default).
17
16
  */
18
- strategy?: 'sse' | 'polling' | 'auto';
17
+ strategy?: 'sse' | 'polling';
19
18
  /** The base interval for polling in milliseconds (default: 2000). */
20
19
  pollingInterval?: number;
21
20
  /** The maximum number of retries for failed HTTP requests (default: 3). */
@@ -37,6 +36,10 @@ export interface CreateInboxOptions {
37
36
  ttl?: number;
38
37
  /** A specific email address to request for the inbox. */
39
38
  emailAddress?: string;
39
+ /** Enable or disable email authentication checks (SPF, DKIM, DMARC, PTR). Omit to use server default. */
40
+ emailAuth?: boolean;
41
+ /** Request encrypted or plain inbox. Omit to use server default based on encryptionPolicy. */
42
+ encryption?: 'encrypted' | 'plain';
40
43
  }
41
44
  /**
42
45
  * Exported inbox data structure for sharing or backup purposes.
@@ -52,10 +55,12 @@ export interface ExportedInboxData {
52
55
  expiresAt: string;
53
56
  /** Unique hash identifier for the inbox */
54
57
  inboxHash: string;
55
- /** Server's ML-DSA-65 public key (base64url encoded, 1952 bytes decoded) */
56
- serverSigPk: string;
57
- /** ML-KEM-768 secret key (base64url encoded, 2400 bytes decoded) */
58
- secretKey: string;
58
+ /** Whether this inbox uses encryption. */
59
+ encrypted: boolean;
60
+ /** Server's ML-DSA-65 public key (base64url encoded, 1952 bytes decoded). Only present for encrypted inboxes. */
61
+ serverSigPk?: string;
62
+ /** ML-KEM-768 secret key (base64url encoded, 2400 bytes decoded). Only present for encrypted inboxes. */
63
+ secretKey?: string;
59
64
  /** ISO 8601 timestamp when the export was created */
60
65
  exportedAt: string;
61
66
  }
@@ -71,8 +76,12 @@ export interface InboxData {
71
76
  expiresAt: string;
72
77
  /** Base64URL-encoded SHA-256 hash of the client KEM public key, used for SSE subscriptions and API references. */
73
78
  inboxHash: string;
74
- /** Base64URL-encoded server signing public key for verifying server signatures. */
75
- serverSigPk: string;
79
+ /** Whether this inbox uses encryption. */
80
+ encrypted: boolean;
81
+ /** Base64URL-encoded server signing public key for verifying server signatures. Only present for encrypted inboxes. */
82
+ serverSigPk?: string;
83
+ /** Whether email authentication checks (SPF, DKIM, DMARC, PTR) are enabled for this inbox. */
84
+ emailAuth?: boolean;
76
85
  }
77
86
  /**
78
87
  * The synchronization status of an inbox.
@@ -106,10 +115,10 @@ export interface WaitForCountOptions {
106
115
  timeout?: number;
107
116
  }
108
117
  /**
109
- * Raw email data returned from the API.
118
+ * Encrypted email data returned from the API.
110
119
  * @internal
111
120
  */
112
- export interface EmailData {
121
+ export interface EncryptedEmailData {
113
122
  id: string;
114
123
  inboxId: string;
115
124
  receivedAt: string;
@@ -117,6 +126,26 @@ export interface EmailData {
117
126
  encryptedMetadata: EncryptedData;
118
127
  encryptedParsed?: EncryptedData;
119
128
  }
129
+ /**
130
+ * Plain (unencrypted) email data returned from the API.
131
+ * @internal
132
+ */
133
+ export interface PlainEmailData {
134
+ id: string;
135
+ inboxId: string;
136
+ receivedAt: string;
137
+ isRead: boolean;
138
+ /** Base64-encoded JSON metadata */
139
+ metadata: string;
140
+ /** Base64-encoded JSON parsed content */
141
+ parsed?: string;
142
+ }
143
+ /**
144
+ * Raw email data returned from the API (encrypted or plain).
145
+ * Use `isEncryptedEmailData()` type guard to discriminate.
146
+ * @internal
147
+ */
148
+ export type EmailData = EncryptedEmailData | PlainEmailData;
120
149
  /**
121
150
  * The structure of encrypted data returned from the server.
122
151
  * @internal
@@ -187,17 +216,21 @@ export interface RawEmail {
187
216
  raw: string;
188
217
  }
189
218
  /**
219
+ * Raw email data from the API (encrypted or plain).
190
220
  * @internal
191
221
  */
192
222
  export interface RawEmailData {
193
223
  id: string;
194
- encryptedRaw: EncryptedData;
224
+ /** Encrypted raw email content. Present for encrypted inboxes. */
225
+ encryptedRaw?: EncryptedData;
226
+ /** Base64-encoded raw email content. Present for plain inboxes. */
227
+ raw?: string;
195
228
  }
196
229
  /**
197
230
  * The result of an SPF (Sender Policy Framework) validation check.
198
231
  */
199
232
  export interface SPFResult {
200
- result: 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror';
233
+ result: 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror' | 'skipped';
201
234
  domain?: string;
202
235
  ip?: string;
203
236
  details?: string;
@@ -206,7 +239,7 @@ export interface SPFResult {
206
239
  * The result of a DKIM (DomainKeys Identified Mail) validation check.
207
240
  */
208
241
  export interface DKIMResult {
209
- result: 'pass' | 'fail' | 'none';
242
+ result: 'pass' | 'fail' | 'none' | 'skipped';
210
243
  domain?: string;
211
244
  selector?: string;
212
245
  signature?: string;
@@ -215,7 +248,7 @@ export interface DKIMResult {
215
248
  * The result of a DMARC (Domain-based Message Authentication, Reporting, and Conformance) validation check.
216
249
  */
217
250
  export interface DMARCResult {
218
- result: 'pass' | 'fail' | 'none';
251
+ result: 'pass' | 'fail' | 'none' | 'skipped';
219
252
  policy?: 'none' | 'quarantine' | 'reject';
220
253
  aligned?: boolean;
221
254
  domain?: string;
@@ -224,7 +257,7 @@ export interface DMARCResult {
224
257
  * The result of a reverse DNS validation check.
225
258
  */
226
259
  export interface ReverseDNSResult {
227
- verified: boolean;
260
+ result: 'pass' | 'fail' | 'none' | 'skipped';
228
261
  ip?: string;
229
262
  hostname?: string;
230
263
  }
@@ -291,12 +324,22 @@ export interface IEmail {
291
324
  export interface AuthResults extends AuthResultsData {
292
325
  validate(): AuthValidation;
293
326
  }
327
+ /**
328
+ * The server's encryption policy for inboxes.
329
+ * - `always`: All inboxes are encrypted, no override allowed
330
+ * - `enabled`: Inboxes are encrypted by default, can request plain
331
+ * - `disabled`: Inboxes are plain by default, can request encrypted
332
+ * - `never`: All inboxes are plain, no override allowed
333
+ */
334
+ export type EncryptionPolicy = 'always' | 'enabled' | 'disabled' | 'never';
294
335
  /**
295
336
  * Information about the VaultSandbox server.
296
337
  */
297
338
  export interface ServerInfo {
298
339
  /** Base64URL-encoded server signing public key for ML-DSA-65. */
299
340
  serverSigPk: string;
341
+ /** The server's encryption policy for inboxes. */
342
+ encryptionPolicy: EncryptionPolicy;
300
343
  /** Cryptographic algorithms supported by the server. */
301
344
  algs: {
302
345
  /** Key encapsulation mechanism algorithm (e.g., 'ML-KEM-768'). */
@@ -337,12 +380,16 @@ export interface SSEConfig {
337
380
  backoffMultiplier?: number;
338
381
  }
339
382
  /**
383
+ * SSE message data for new email notifications.
340
384
  * @internal
341
385
  */
342
386
  export interface SSEMessageData {
343
387
  inboxId: string;
344
388
  emailId: string;
345
- encryptedMetadata: EncryptedData;
389
+ /** Encrypted metadata. Present for encrypted inboxes. */
390
+ encryptedMetadata?: EncryptedData;
391
+ /** Base64-encoded JSON metadata. Present for plain inboxes. */
392
+ metadata?: string;
346
393
  }
347
394
  /**
348
395
  * A quantum-safe keypair used for encryption and decryption.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,25 @@
1
1
  /**
2
2
  * Shared email utilities for decryption and filtering
3
3
  */
4
- import type { Keypair, EmailData, IEmail, WaitOptions } from '../types/index.js';
4
+ import type { Keypair, EmailData, EncryptedEmailData, PlainEmailData, IEmail, WaitOptions } from '../types/index.js';
5
5
  import type { ApiClient } from '../http/api-client.js';
6
6
  /**
7
- * Decrypts an EmailData object into an Email instance.
7
+ * Type guard to determine if email data is encrypted.
8
+ * @param email - The email data to check
9
+ * @returns true if the email has encryptedMetadata (encrypted format)
10
+ */
11
+ export declare function isEncryptedEmailData(email: EmailData): email is EncryptedEmailData;
12
+ /**
13
+ * Decrypts an EncryptedEmailData object into an Email instance.
8
14
  * Expects full email data with encryptedParsed content.
9
15
  * IMPORTANT: Signature verification happens BEFORE decryption for security
10
16
  */
11
- export declare function decryptEmailData(emailData: EmailData, keypair: Keypair, emailAddress: string, apiClient: ApiClient): Promise<IEmail>;
17
+ export declare function decryptEmailData(emailData: EncryptedEmailData, keypair: Keypair, emailAddress: string, apiClient: ApiClient): Promise<IEmail>;
18
+ /**
19
+ * Decodes a PlainEmailData object into an Email instance.
20
+ * Plain emails have base64-encoded metadata and parsed content.
21
+ */
22
+ export declare function decodeBase64EmailData(emailData: PlainEmailData, emailAddress: string, apiClient: ApiClient): IEmail;
12
23
  /**
13
24
  * Finds the first email matching the specified criteria
14
25
  */
@@ -6,7 +6,15 @@ import { decryptMetadata, decryptParsed } from '../crypto/decrypt.js';
6
6
  import { verifySignature } from '../crypto/signature.js';
7
7
  import { fromBase64 } from '../crypto/utils.js';
8
8
  /**
9
- * Decrypts an EmailData object into an Email instance.
9
+ * Type guard to determine if email data is encrypted.
10
+ * @param email - The email data to check
11
+ * @returns true if the email has encryptedMetadata (encrypted format)
12
+ */
13
+ export function isEncryptedEmailData(email) {
14
+ return 'encryptedMetadata' in email;
15
+ }
16
+ /**
17
+ * Decrypts an EncryptedEmailData object into an Email instance.
10
18
  * Expects full email data with encryptedParsed content.
11
19
  * IMPORTANT: Signature verification happens BEFORE decryption for security
12
20
  */
@@ -39,6 +47,36 @@ export async function decryptEmailData(emailData, keypair, emailAddress, apiClie
39
47
  }
40
48
  return new Email(emailData, metadata, parsed, emailAddress, apiClient, keypair);
41
49
  }
50
+ /**
51
+ * Decodes a PlainEmailData object into an Email instance.
52
+ * Plain emails have base64-encoded metadata and parsed content.
53
+ */
54
+ export function decodeBase64EmailData(emailData, emailAddress, apiClient) {
55
+ // Decode base64 metadata
56
+ const metadataJson = Buffer.from(emailData.metadata, 'base64').toString('utf-8');
57
+ const metadata = JSON.parse(metadataJson);
58
+ // Decode parsed content if available
59
+ let parsed = null;
60
+ if (emailData.parsed) {
61
+ const parsedJson = Buffer.from(emailData.parsed, 'base64').toString('utf-8');
62
+ parsed = JSON.parse(parsedJson);
63
+ // Transform attachment content from base64 strings to Uint8Array
64
+ // Same as encrypted path - server sends attachment content as base64
65
+ if (parsed?.attachments) {
66
+ parsed.attachments = parsed.attachments.map((att) => {
67
+ if (att.content && typeof att.content === 'string') {
68
+ return {
69
+ ...att,
70
+ content: fromBase64(att.content),
71
+ };
72
+ }
73
+ return att;
74
+ });
75
+ }
76
+ }
77
+ // Pass null for keypair since plain emails don't need decryption
78
+ return new Email(emailData, metadata, parsed, emailAddress, apiClient, null);
79
+ }
42
80
  /**
43
81
  * Finds the first email matching the specified criteria
44
82
  */
@@ -56,6 +94,7 @@ export function findMatchingEmail(emails, options) {
56
94
  export function matchesFilters(email, options) {
57
95
  // Check subject filter
58
96
  if (options.subject) {
97
+ /* istanbul ignore else - defensive check for non-TypeScript callers */
59
98
  if (typeof options.subject === 'string') {
60
99
  if (!email.subject.includes(options.subject)) {
61
100
  return false;
@@ -69,6 +108,7 @@ export function matchesFilters(email, options) {
69
108
  }
70
109
  // Check from filter
71
110
  if (options.from) {
111
+ /* istanbul ignore else - defensive check for non-TypeScript callers */
72
112
  if (typeof options.from === 'string') {
73
113
  if (!email.from.includes(options.from)) {
74
114
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"email-utils.js","sourceRoot":"","sources":["../../src/utils/email-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"email-utils.js","sourceRoot":"","sources":["../../src/utils/email-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hash utilities for email synchronization
3
+ */
4
+ /**
5
+ * Computes the emails hash using the spec algorithm:
6
+ * BASE64URL(SHA256(SORT(emailIds).join(",")))
7
+ *
8
+ * This hash is used to efficiently detect changes between
9
+ * the local and server email lists without transferring
10
+ * the full list.
11
+ *
12
+ * @param emailIds - Array of email IDs to hash
13
+ * @returns Base64URL encoded SHA-256 hash (no padding)
14
+ */
15
+ export declare function computeEmailsHash(emailIds: string[]): string;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Hash utilities for email synchronization
3
+ */
4
+ import { createHash } from 'crypto';
5
+ /**
6
+ * Computes the emails hash using the spec algorithm:
7
+ * BASE64URL(SHA256(SORT(emailIds).join(",")))
8
+ *
9
+ * This hash is used to efficiently detect changes between
10
+ * the local and server email lists without transferring
11
+ * the full list.
12
+ *
13
+ * @param emailIds - Array of email IDs to hash
14
+ * @returns Base64URL encoded SHA-256 hash (no padding)
15
+ */
16
+ export function computeEmailsHash(emailIds) {
17
+ const sorted = [...emailIds].sort();
18
+ const joined = sorted.join(',');
19
+ const hash = createHash('sha256').update(joined).digest();
20
+ return base64UrlEncode(hash);
21
+ }
22
+ /**
23
+ * Encodes a buffer as Base64URL (RFC 4648 §5) without padding.
24
+ *
25
+ * @param buffer - The buffer to encode
26
+ * @returns Base64URL encoded string without padding
27
+ */
28
+ function base64UrlEncode(buffer) {
29
+ return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
30
+ }
31
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAkB;IAClD,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;IAC1D,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC9F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultsandbox/client",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Node.js SDK for VaultSandbox Gateway — quantum-safe email testing with zero crypto knowledge required. Create isolated inboxes, validate SPF/DKIM/DMARC, and test your full email stack in CI/CD pipelines.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/vaultsandbox/client-node",
@@ -38,7 +38,7 @@
38
38
  "vaultsandbox"
39
39
  ],
40
40
  "author": "Antero <antero@vaultsandbox.com>",
41
- "license": "MIT",
41
+ "license": "Apache-2.0",
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
@@ -61,7 +61,7 @@
61
61
  "prepublishOnly": "npm run clean && npm run build"
62
62
  },
63
63
  "dependencies": {
64
- "@noble/post-quantum": "0.5.2",
64
+ "@noble/post-quantum": "0.5.4",
65
65
  "axios": "1.13.2",
66
66
  "debug": "4.4.3",
67
67
  "eventsource": "4.1.0"
@@ -70,8 +70,8 @@
70
70
  "@types/debug": "4.1.12",
71
71
  "@types/jest": "30.0.0",
72
72
  "@types/node": "24.10.2",
73
- "@typescript-eslint/eslint-plugin": "8.47.0",
74
- "@typescript-eslint/parser": "8.49.0",
73
+ "@typescript-eslint/eslint-plugin": "8.52.0",
74
+ "@typescript-eslint/parser": "8.52.0",
75
75
  "dotenv": "17.2.3",
76
76
  "eslint": "9.39.1",
77
77
  "eslint-config-prettier": "10.1.8",