@capsara/sdk 1.0.1

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 (139) hide show
  1. package/LICENSE +74 -0
  2. package/README.md +230 -0
  3. package/dist/builder/capsa-builder.d.ts +167 -0
  4. package/dist/builder/capsa-builder.d.ts.map +1 -0
  5. package/dist/builder/capsa-builder.js +489 -0
  6. package/dist/builder/capsa-builder.js.map +1 -0
  7. package/dist/client/capsara-client.d.ts +96 -0
  8. package/dist/client/capsara-client.d.ts.map +1 -0
  9. package/dist/client/capsara-client.js +266 -0
  10. package/dist/client/capsara-client.js.map +1 -0
  11. package/dist/errors/account-error.d.ts +73 -0
  12. package/dist/errors/account-error.d.ts.map +1 -0
  13. package/dist/errors/account-error.js +155 -0
  14. package/dist/errors/account-error.js.map +1 -0
  15. package/dist/errors/audit-error.d.ts +34 -0
  16. package/dist/errors/audit-error.d.ts.map +1 -0
  17. package/dist/errors/audit-error.js +93 -0
  18. package/dist/errors/audit-error.js.map +1 -0
  19. package/dist/errors/auth-error.d.ts +38 -0
  20. package/dist/errors/auth-error.d.ts.map +1 -0
  21. package/dist/errors/auth-error.js +87 -0
  22. package/dist/errors/auth-error.js.map +1 -0
  23. package/dist/errors/capsa-error.d.ts +64 -0
  24. package/dist/errors/capsa-error.d.ts.map +1 -0
  25. package/dist/errors/capsa-error.js +172 -0
  26. package/dist/errors/capsa-error.js.map +1 -0
  27. package/dist/errors/capsara-error.d.ts +52 -0
  28. package/dist/errors/capsara-error.d.ts.map +1 -0
  29. package/dist/errors/capsara-error.js +83 -0
  30. package/dist/errors/capsara-error.js.map +1 -0
  31. package/dist/errors/index.d.ts +8 -0
  32. package/dist/errors/index.d.ts.map +1 -0
  33. package/dist/errors/index.js +7 -0
  34. package/dist/errors/index.js.map +1 -0
  35. package/dist/index.d.ts +7 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +5 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/internal/capsa-cache.d.ts +49 -0
  40. package/dist/internal/capsa-cache.d.ts.map +1 -0
  41. package/dist/internal/capsa-cache.js +118 -0
  42. package/dist/internal/capsa-cache.js.map +1 -0
  43. package/dist/internal/config/http-client.d.ts +37 -0
  44. package/dist/internal/config/http-client.d.ts.map +1 -0
  45. package/dist/internal/config/http-client.js +63 -0
  46. package/dist/internal/config/http-client.js.map +1 -0
  47. package/dist/internal/config/retry-interceptor.d.ts +18 -0
  48. package/dist/internal/config/retry-interceptor.d.ts.map +1 -0
  49. package/dist/internal/config/retry-interceptor.js +103 -0
  50. package/dist/internal/config/retry-interceptor.js.map +1 -0
  51. package/dist/internal/crypto/compression.d.ts +15 -0
  52. package/dist/internal/crypto/compression.d.ts.map +1 -0
  53. package/dist/internal/crypto/compression.js +34 -0
  54. package/dist/internal/crypto/compression.js.map +1 -0
  55. package/dist/internal/crypto/key-generator.d.ts +23 -0
  56. package/dist/internal/crypto/key-generator.d.ts.map +1 -0
  57. package/dist/internal/crypto/key-generator.js +65 -0
  58. package/dist/internal/crypto/key-generator.js.map +1 -0
  59. package/dist/internal/crypto/primitives.d.ts +67 -0
  60. package/dist/internal/crypto/primitives.d.ts.map +1 -0
  61. package/dist/internal/crypto/primitives.js +230 -0
  62. package/dist/internal/crypto/primitives.js.map +1 -0
  63. package/dist/internal/crypto/signatures.d.ts +30 -0
  64. package/dist/internal/crypto/signatures.d.ts.map +1 -0
  65. package/dist/internal/crypto/signatures.js +153 -0
  66. package/dist/internal/crypto/signatures.js.map +1 -0
  67. package/dist/internal/decryptor/capsa-decryptor.d.ts +89 -0
  68. package/dist/internal/decryptor/capsa-decryptor.d.ts.map +1 -0
  69. package/dist/internal/decryptor/capsa-decryptor.js +263 -0
  70. package/dist/internal/decryptor/capsa-decryptor.js.map +1 -0
  71. package/dist/internal/http-factory.d.ts +78 -0
  72. package/dist/internal/http-factory.d.ts.map +1 -0
  73. package/dist/internal/http-factory.js +201 -0
  74. package/dist/internal/http-factory.js.map +1 -0
  75. package/dist/internal/index.d.ts +5 -0
  76. package/dist/internal/index.d.ts.map +1 -0
  77. package/dist/internal/index.js +5 -0
  78. package/dist/internal/index.js.map +1 -0
  79. package/dist/internal/retry-executor.d.ts +74 -0
  80. package/dist/internal/retry-executor.d.ts.map +1 -0
  81. package/dist/internal/retry-executor.js +204 -0
  82. package/dist/internal/retry-executor.js.map +1 -0
  83. package/dist/internal/services/account-service.d.ts +56 -0
  84. package/dist/internal/services/account-service.d.ts.map +1 -0
  85. package/dist/internal/services/account-service.js +114 -0
  86. package/dist/internal/services/account-service.js.map +1 -0
  87. package/dist/internal/services/audit-service.d.ts +25 -0
  88. package/dist/internal/services/audit-service.d.ts.map +1 -0
  89. package/dist/internal/services/audit-service.js +43 -0
  90. package/dist/internal/services/audit-service.js.map +1 -0
  91. package/dist/internal/services/auth-service.d.ts +44 -0
  92. package/dist/internal/services/auth-service.d.ts.map +1 -0
  93. package/dist/internal/services/auth-service.js +170 -0
  94. package/dist/internal/services/auth-service.js.map +1 -0
  95. package/dist/internal/services/capsa-service.d.ts +40 -0
  96. package/dist/internal/services/capsa-service.d.ts.map +1 -0
  97. package/dist/internal/services/capsa-service.js +82 -0
  98. package/dist/internal/services/capsa-service.js.map +1 -0
  99. package/dist/internal/services/download-service.d.ts +62 -0
  100. package/dist/internal/services/download-service.d.ts.map +1 -0
  101. package/dist/internal/services/download-service.js +114 -0
  102. package/dist/internal/services/download-service.js.map +1 -0
  103. package/dist/internal/services/key-service.d.ts +28 -0
  104. package/dist/internal/services/key-service.d.ts.map +1 -0
  105. package/dist/internal/services/key-service.js +45 -0
  106. package/dist/internal/services/key-service.js.map +1 -0
  107. package/dist/internal/services/limits-service.d.ts +30 -0
  108. package/dist/internal/services/limits-service.d.ts.map +1 -0
  109. package/dist/internal/services/limits-service.js +73 -0
  110. package/dist/internal/services/limits-service.js.map +1 -0
  111. package/dist/internal/services/upload-service.d.ts +61 -0
  112. package/dist/internal/services/upload-service.d.ts.map +1 -0
  113. package/dist/internal/services/upload-service.js +258 -0
  114. package/dist/internal/services/upload-service.js.map +1 -0
  115. package/dist/internal/types.d.ts +74 -0
  116. package/dist/internal/types.d.ts.map +1 -0
  117. package/dist/internal/types.js +3 -0
  118. package/dist/internal/types.js.map +1 -0
  119. package/dist/internal/upload/multipart-builder.d.ts +57 -0
  120. package/dist/internal/upload/multipart-builder.d.ts.map +1 -0
  121. package/dist/internal/upload/multipart-builder.js +139 -0
  122. package/dist/internal/upload/multipart-builder.js.map +1 -0
  123. package/dist/internal/utils/id-generator.d.ts +8 -0
  124. package/dist/internal/utils/id-generator.d.ts.map +1 -0
  125. package/dist/internal/utils/id-generator.js +20 -0
  126. package/dist/internal/utils/id-generator.js.map +1 -0
  127. package/dist/internal/utils/mimetype-lookup.d.ts +8 -0
  128. package/dist/internal/utils/mimetype-lookup.d.ts.map +1 -0
  129. package/dist/internal/utils/mimetype-lookup.js +118 -0
  130. package/dist/internal/utils/mimetype-lookup.js.map +1 -0
  131. package/dist/internal/version.d.ts +20 -0
  132. package/dist/internal/version.d.ts.map +1 -0
  133. package/dist/internal/version.js +25 -0
  134. package/dist/internal/version.js.map +1 -0
  135. package/dist/types/index.d.ts +143 -0
  136. package/dist/types/index.d.ts.map +1 -0
  137. package/dist/types/index.js +20 -0
  138. package/dist/types/index.js.map +1 -0
  139. package/package.json +61 -0
@@ -0,0 +1,263 @@
1
+ /** Capsa decryption utilities for client-side decryption of API responses. */
2
+ import * as crypto from 'crypto';
3
+ import { decryptAES, decryptMasterKey } from '../crypto/primitives.js';
4
+ import { buildCanonicalString, verifyCapsaSignature } from '../crypto/signatures.js';
5
+ import { decompressData } from '../crypto/compression.js';
6
+ function findKeychainEntry(capsa, partyId) {
7
+ return capsa.keychain.keys.find((key) => key.party === partyId) || null;
8
+ }
9
+ function findDelegateEntry(capsa, partyId) {
10
+ return (capsa.keychain.keys.find((key) => key.actingFor && key.actingFor.includes(partyId)) || null);
11
+ }
12
+ /**
13
+ * Decrypt capsa using party's private key
14
+ *
15
+ * SECURITY FEATURES:
16
+ * - Verifies capsa signature before decryption
17
+ * - Requires auth tags for all AES-GCM decryption
18
+ * - Validates keychain entry exists
19
+ *
20
+ * NOTE: partyId is optional. If not provided, uses the first keychain entry
21
+ * (which is the authenticated party's key when retrieved from API).
22
+ *
23
+ * @param capsa - Encrypted capsa from API
24
+ * @param privateKey - Party's RSA private key in PEM format
25
+ * @param partyId - Party ID (optional - auto-detected from keychain if omitted)
26
+ * @param creatorPublicKey - Creator's RSA public key in PEM format (for signature verification)
27
+ * @param verifySignature - Whether to verify signature (default: true, set false to skip)
28
+ * @returns Decrypted capsa data
29
+ * @throws Error if signature invalid, party not in keychain, or decryption fails
30
+ */
31
+ export function decryptCapsa(capsa, privateKey, partyId, creatorPublicKey, verifySignature = true) {
32
+ // SECURITY: Verify capsa signature before decrypting
33
+ if (verifySignature) {
34
+ if (!creatorPublicKey) {
35
+ throw new Error('creatorPublicKey is required for signature verification. Pass verifySignature=false to skip (not recommended).');
36
+ }
37
+ // SECURITY VALIDATION: Verify signature object exists with required fields
38
+ if (!capsa.signature || typeof capsa.signature !== 'object' || !capsa.signature.signature) {
39
+ throw new Error(`Capsa signature is missing or invalid (capsa: ${capsa.id}). Capsa may be corrupted or created with an old SDK version.`);
40
+ }
41
+ // Validate signature format (RSA-SHA256 produces 512-byte signature, base64url-encoded)
42
+ try {
43
+ const signatureBuffer = Buffer.from(capsa.signature.signature, 'base64url');
44
+ if (signatureBuffer.length !== 512) {
45
+ throw new Error(`Signature length validation failed: expected 512 bytes (RSA-4096-SHA256), got ${signatureBuffer.length} bytes (capsa: ${capsa.id}). Possible data corruption.`);
46
+ }
47
+ }
48
+ catch (error) {
49
+ if (error instanceof Error && error.message.includes('Signature length validation')) {
50
+ throw error;
51
+ }
52
+ throw new Error(`Signature format validation failed: invalid base64url encoding (capsa: ${capsa.id}).`);
53
+ }
54
+ if (!creatorPublicKey.includes('BEGIN') || !creatorPublicKey.includes('PUBLIC KEY')) {
55
+ throw new Error(`Creator public key format validation failed: missing PEM headers (creator: ${capsa.creator}).`);
56
+ }
57
+ // Build canonical string from capsa data (createdAt excluded - not part of signature)
58
+ const canonicalString = buildCanonicalString({
59
+ packageId: capsa.id,
60
+ totalSize: capsa.totalSize,
61
+ algorithm: capsa.keychain.algorithm,
62
+ files: capsa.files,
63
+ structuredIV: capsa.structuredIV,
64
+ subjectIV: capsa.subjectIV,
65
+ bodyIV: capsa.bodyIV,
66
+ });
67
+ const signatureValid = verifyCapsaSignature(capsa.signature, canonicalString, creatorPublicKey);
68
+ if (!signatureValid) {
69
+ throw new Error(`Signature verification failed: capsa data does not match signature (capsa: ${capsa.id}, creator: ${capsa.creator}). Capsa may have been tampered with or corrupted.`);
70
+ }
71
+ }
72
+ let keychainEntry;
73
+ if (partyId) {
74
+ const foundEntry = findKeychainEntry(capsa, partyId);
75
+ if (!foundEntry) {
76
+ const delegateEntry = findDelegateEntry(capsa, partyId);
77
+ if (!delegateEntry) {
78
+ throw new Error(`Party ${partyId} not found in capsa keychain. Cannot decrypt.`);
79
+ }
80
+ keychainEntry = delegateEntry;
81
+ }
82
+ else {
83
+ keychainEntry = foundEntry;
84
+ }
85
+ }
86
+ else {
87
+ // No partyId - use first keychain entry (API returns only authenticated party's key)
88
+ if (!capsa.keychain.keys || capsa.keychain.keys.length === 0) {
89
+ throw new Error('No keychain entries found in capsa. Cannot decrypt.');
90
+ }
91
+ const firstEntry = capsa.keychain.keys[0];
92
+ if (!firstEntry) {
93
+ throw new Error('First keychain entry is undefined. Cannot decrypt.');
94
+ }
95
+ keychainEntry = firstEntry;
96
+ }
97
+ if (!keychainEntry.encryptedKey) {
98
+ const partyInfo = partyId || keychainEntry.party;
99
+ throw new Error(`Party ${partyInfo} has no encrypted key in keychain. This party may be a delegated recipient without direct access.`);
100
+ }
101
+ // SECURITY VALIDATION: Verify encrypted key format and integrity
102
+ // RSA-4096-OAEP outputs exactly 512 bytes, base64url-encoded
103
+ const encryptedKeyBuffer = Buffer.from(keychainEntry.encryptedKey, 'base64url');
104
+ if (encryptedKeyBuffer.length !== 512) {
105
+ throw new Error(`Encrypted key length validation failed: expected 512 bytes (RSA-4096), got ${encryptedKeyBuffer.length} bytes (capsa: ${capsa.id}, party: ${partyId || keychainEntry.party}). Possible data corruption.`);
106
+ }
107
+ if (!privateKey || typeof privateKey !== 'string') {
108
+ throw new Error('Private key is invalid or missing');
109
+ }
110
+ if (!privateKey.includes('BEGIN') || !privateKey.includes('PRIVATE KEY')) {
111
+ throw new Error(`Private key format validation failed: missing PEM headers. Key may be corrupted.`);
112
+ }
113
+ let masterKey;
114
+ try {
115
+ masterKey = decryptMasterKey(keychainEntry.encryptedKey, privateKey);
116
+ }
117
+ catch (error) {
118
+ // Preserve original error details for diagnostics
119
+ const originalMessage = error instanceof Error ? error.message : String(error);
120
+ throw new Error(`RSA master key decryption failed: ${originalMessage} (capsa: ${capsa.id}, party: ${partyId || keychainEntry.party}, encryptedKeyLength: ${encryptedKeyBuffer.length})`);
121
+ }
122
+ // SECURITY VALIDATION: Verify decrypted master key is correct size
123
+ // AES-256 requires exactly 32 bytes
124
+ if (masterKey.length !== 32) {
125
+ throw new Error(`Master key size validation failed: expected 32 bytes (AES-256), got ${masterKey.length} bytes. RSA decryption may have succeeded with wrong key.`);
126
+ }
127
+ let subject;
128
+ let body;
129
+ let structured;
130
+ if (capsa.encryptedSubject && capsa.subjectIV) {
131
+ if (!capsa.subjectAuthTag) {
132
+ // eslint-disable-next-line no-console
133
+ console.warn('WARNING: encryptedSubject missing authTag - skipping decryption for security');
134
+ }
135
+ else {
136
+ const subjectBuffer = decryptAES(capsa.encryptedSubject, masterKey, capsa.subjectIV, capsa.subjectAuthTag);
137
+ subject = subjectBuffer.toString('utf-8');
138
+ }
139
+ }
140
+ if (capsa.encryptedBody && capsa.bodyIV) {
141
+ if (!capsa.bodyAuthTag) {
142
+ // eslint-disable-next-line no-console
143
+ console.warn('WARNING: encryptedBody missing authTag - skipping decryption for security');
144
+ }
145
+ else {
146
+ const bodyBuffer = decryptAES(capsa.encryptedBody, masterKey, capsa.bodyIV, capsa.bodyAuthTag);
147
+ body = bodyBuffer.toString('utf-8');
148
+ }
149
+ }
150
+ if (capsa.encryptedStructured && capsa.structuredIV) {
151
+ if (!capsa.structuredAuthTag) {
152
+ // eslint-disable-next-line no-console
153
+ console.warn('WARNING: encryptedStructured missing authTag - skipping decryption for security');
154
+ }
155
+ else {
156
+ const structuredBuffer = decryptAES(capsa.encryptedStructured, masterKey, capsa.structuredIV, capsa.structuredAuthTag);
157
+ structured = JSON.parse(structuredBuffer.toString('utf-8'));
158
+ }
159
+ }
160
+ // Map soft_deleted to expired for SDK consumers (soft_deleted is internal server status)
161
+ const status = capsa.status === 'soft_deleted' ? 'expired' :
162
+ capsa.status === 'expired' ? 'expired' : 'active';
163
+ const decryptedCapsa = {
164
+ id: capsa.id,
165
+ creator: capsa.creator,
166
+ createdAt: capsa.createdAt,
167
+ updatedAt: capsa.updatedAt,
168
+ status,
169
+ subject,
170
+ body,
171
+ structured,
172
+ files: capsa.files,
173
+ accessControl: capsa.accessControl,
174
+ keychain: capsa.keychain,
175
+ signature: capsa.signature,
176
+ metadata: capsa.metadata,
177
+ stats: {
178
+ totalSize: capsa.totalSize,
179
+ fileCount: capsa.files?.length ?? 0,
180
+ },
181
+ _encrypted: capsa,
182
+ _masterKey: masterKey, // Placeholder, will be redefined as non-enumerable
183
+ clearMasterKey: function () {
184
+ // Implementation added below
185
+ }
186
+ };
187
+ // Non-enumerable to prevent serialization
188
+ Object.defineProperty(decryptedCapsa, '_masterKey', {
189
+ value: masterKey,
190
+ enumerable: false, // Hidden from enumeration
191
+ writable: false, // Immutable
192
+ configurable: true // Allow clearMasterKey() to replace with zeroed buffer
193
+ });
194
+ decryptedCapsa.clearMasterKey = function () {
195
+ if (this._masterKey && this._masterKey.length > 0) {
196
+ // Overwrite master key buffer with cryptographically random data
197
+ crypto.randomFillSync(this._masterKey);
198
+ Object.defineProperty(this, '_masterKey', {
199
+ value: Buffer.alloc(0),
200
+ enumerable: false,
201
+ writable: false,
202
+ configurable: false // Lock down after clearing
203
+ });
204
+ }
205
+ };
206
+ return decryptedCapsa;
207
+ }
208
+ /**
209
+ * Decrypt a file from a capsa
210
+ *
211
+ * SECURITY: Requires non-empty authTag for AES-GCM integrity verification
212
+ *
213
+ * @param encryptedFileData - Encrypted file data (base64url)
214
+ * @param masterKey - Decrypted master key
215
+ * @param iv - Initialization vector for file
216
+ * @param authTag - Authentication tag for file (REQUIRED)
217
+ * @returns Decrypted file buffer
218
+ * @throws Error if authTag is missing or decryption fails
219
+ */
220
+ export async function decryptFile(encryptedFileData, masterKey, iv, authTag, compressed) {
221
+ // SECURITY: Validate authTag is present
222
+ if (!authTag || authTag.trim() === '') {
223
+ throw new Error('SECURITY ERROR: authTag is required for file decryption. Missing authTag indicates potential tampering.');
224
+ }
225
+ try {
226
+ const decryptedData = decryptAES(encryptedFileData, masterKey, iv, authTag);
227
+ if (compressed) {
228
+ return await decompressData(decryptedData);
229
+ }
230
+ return decryptedData;
231
+ }
232
+ catch (error) {
233
+ const message = error instanceof Error ? error.message : 'Unknown error';
234
+ throw new Error(`Failed to decrypt file: ${message}`);
235
+ }
236
+ }
237
+ /**
238
+ * Decrypt filename from capsa
239
+ *
240
+ * SECURITY: Requires non-empty authTag for AES-GCM integrity verification
241
+ *
242
+ * @param encryptedFilename - Encrypted filename (base64url)
243
+ * @param masterKey - Decrypted master key
244
+ * @param iv - Initialization vector for filename
245
+ * @param authTag - Authentication tag for filename (REQUIRED)
246
+ * @returns Decrypted filename
247
+ * @throws Error if authTag is missing or decryption fails
248
+ */
249
+ export function decryptFilename(encryptedFilename, masterKey, iv, authTag) {
250
+ // SECURITY: Validate authTag is present
251
+ if (!authTag || authTag.trim() === '') {
252
+ throw new Error('SECURITY ERROR: authTag is required for filename decryption. Missing authTag indicates potential tampering.');
253
+ }
254
+ try {
255
+ const filenameBuffer = decryptAES(encryptedFilename, masterKey, iv, authTag);
256
+ return filenameBuffer.toString('utf-8');
257
+ }
258
+ catch (error) {
259
+ const message = error instanceof Error ? error.message : 'Unknown error';
260
+ throw new Error(`Failed to decrypt filename: ${message}`);
261
+ }
262
+ }
263
+ //# sourceMappingURL=capsa-decryptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capsa-decryptor.js","sourceRoot":"","sources":["../../../src/internal/decryptor/capsa-decryptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * HTTP client factory - eliminates HTTP setup duplication across services
3
+ * @file capsara.sdk/typescript/src/internal/http-factory.ts
4
+ */
5
+ import { AxiosInstance } from 'axios';
6
+ import * as http from 'http';
7
+ import * as https from 'https';
8
+ import type { RetryConfig } from './config/retry-interceptor.js';
9
+ /**
10
+ * HTTP client timeout configuration
11
+ */
12
+ export interface HttpTimeoutConfig {
13
+ /** Timeout for standard API requests (ms) */
14
+ apiTimeout: number;
15
+ /** Timeout for multipart envelope uploads (ms) */
16
+ uploadTimeout: number;
17
+ /** Timeout for file downloads (ms) */
18
+ downloadTimeout: number;
19
+ /** Socket connection timeout (ms) */
20
+ connectTimeout: number;
21
+ /** Keep-alive probe interval (ms) */
22
+ keepAliveInterval: number;
23
+ /** Maximum concurrent sockets per host */
24
+ maxSockets: number;
25
+ /** Maximum idle sockets to keep alive */
26
+ maxFreeSockets: number;
27
+ }
28
+ /**
29
+ * Default timeout configuration
30
+ *
31
+ * CRITICAL: SDK timeouts must EXCEED server timeouts to prevent ECONNRESET errors
32
+ *
33
+ * vault.api server timeouts:
34
+ * - Server request timeout: 10 minutes
35
+ * - Server keepAlive: 11 minutes
36
+ * - MongoDB socket timeout: 30 seconds
37
+ * - Circuit breaker timeout: 30 seconds
38
+ */
39
+ export declare const DEFAULT_TIMEOUT_CONFIG: HttpTimeoutConfig;
40
+ /**
41
+ * Options for creating an HTTP client
42
+ */
43
+ export interface HttpClientOptions {
44
+ /** API base URL */
45
+ baseUrl: string;
46
+ /** Timeout configuration */
47
+ timeout?: Partial<HttpTimeoutConfig>;
48
+ /** Retry configuration */
49
+ retry?: RetryConfig;
50
+ /** Function to get auth token (for authenticated requests) */
51
+ getToken?: () => string | null;
52
+ /** Custom user agent string to append to default SDK user agent */
53
+ userAgent?: string;
54
+ }
55
+ /**
56
+ * Logger interface for retry interceptor
57
+ */
58
+ export interface RetryLogger {
59
+ log: (message: string) => void;
60
+ }
61
+ /**
62
+ * Create a configured axios instance with retry and optional auth
63
+ *
64
+ * This factory eliminates the HTTP setup duplication found in AuthClient,
65
+ * KeyManager, LimitsManager, AccountClient, and CapsaraClient.
66
+ *
67
+ * @param options - HTTP client configuration
68
+ * @returns Configured axios instance
69
+ */
70
+ export declare function createHttpClient(options: HttpClientOptions): AxiosInstance;
71
+ /**
72
+ * Create HTTP/HTTPS agent for raw requests with custom timeout
73
+ * @param protocol - 'http:' or 'https:'
74
+ * @param timeout - Request timeout in milliseconds
75
+ * @param config - Timeout configuration
76
+ */
77
+ export declare function createAgentForProtocol(protocol: string, timeout: number, config?: HttpTimeoutConfig): http.Agent | https.Agent;
78
+ //# sourceMappingURL=http-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-factory.d.ts","sourceRoot":"","sources":["../../src/internal/http-factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAGjE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAQpC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrC,0BAA0B;IAC1B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AA0HD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CAgC1E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,iBAA0C,GACjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAY1B"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * HTTP client factory - eliminates HTTP setup duplication across services
3
+ * @file capsara.sdk/typescript/src/internal/http-factory.ts
4
+ */
5
+ import axios from 'axios';
6
+ import * as http from 'http';
7
+ import * as https from 'https';
8
+ import { SDK_VERSION, buildUserAgent } from './version.js';
9
+ /**
10
+ * Default timeout configuration
11
+ *
12
+ * CRITICAL: SDK timeouts must EXCEED server timeouts to prevent ECONNRESET errors
13
+ *
14
+ * vault.api server timeouts:
15
+ * - Server request timeout: 10 minutes
16
+ * - Server keepAlive: 11 minutes
17
+ * - MongoDB socket timeout: 30 seconds
18
+ * - Circuit breaker timeout: 30 seconds
19
+ */
20
+ export const DEFAULT_TIMEOUT_CONFIG = {
21
+ apiTimeout: 12 * 60 * 1000, // 12 minutes (exceeds server 10 min timeout)
22
+ uploadTimeout: 15 * 60 * 1000, // 15 minutes for multipart uploads
23
+ downloadTimeout: 60 * 1000, // 1 minute for file downloads
24
+ connectTimeout: 30 * 1000, // 30 seconds for socket connection
25
+ keepAliveInterval: 30 * 1000, // 30 seconds keep-alive probe interval
26
+ maxSockets: 50, // Max 50 concurrent sockets per host
27
+ maxFreeSockets: 10, // Keep 10 idle sockets alive
28
+ };
29
+ /**
30
+ * Create HTTP agent with keep-alive and timeout configuration
31
+ */
32
+ function createHttpAgent(config) {
33
+ return new http.Agent({
34
+ keepAlive: true,
35
+ keepAliveMsecs: config.keepAliveInterval,
36
+ timeout: config.apiTimeout,
37
+ maxSockets: config.maxSockets,
38
+ maxFreeSockets: config.maxFreeSockets,
39
+ });
40
+ }
41
+ /**
42
+ * Create HTTPS agent with keep-alive and timeout configuration
43
+ */
44
+ function createHttpsAgent(config) {
45
+ return new https.Agent({
46
+ keepAlive: true,
47
+ keepAliveMsecs: config.keepAliveInterval,
48
+ timeout: config.apiTimeout,
49
+ maxSockets: config.maxSockets,
50
+ maxFreeSockets: config.maxFreeSockets,
51
+ });
52
+ }
53
+ /**
54
+ * Default retry configuration
55
+ */
56
+ const DEFAULT_RETRY_CONFIG = {
57
+ maxRetries: 3,
58
+ baseDelay: 1000,
59
+ maxDelay: 30000,
60
+ enableLogging: false,
61
+ // eslint-disable-next-line no-console
62
+ logger: { log: (msg) => console.log(msg) },
63
+ };
64
+ /**
65
+ * Calculate retry delay using exponential backoff
66
+ */
67
+ function calculateExponentialBackoff(retryCount, baseDelay, maxDelay) {
68
+ const exponentialDelay = baseDelay * Math.pow(2, retryCount);
69
+ const jitter = Math.random() * 0.3 * exponentialDelay;
70
+ return Math.min(Math.floor(exponentialDelay + jitter), maxDelay);
71
+ }
72
+ /**
73
+ * Sleep for specified duration
74
+ */
75
+ function sleep(ms) {
76
+ return new Promise(resolve => globalThis.setTimeout(resolve, ms));
77
+ }
78
+ /**
79
+ * Check if error is retryable (503 or 429)
80
+ */
81
+ function isRetryableStatus(status) {
82
+ return status === 503 || status === 429;
83
+ }
84
+ /**
85
+ * Extract retry delay from server response
86
+ */
87
+ function getServerSuggestedDelay(response) {
88
+ // Check response body for retryAfter field
89
+ const data = response.data;
90
+ if (data?.error?.retryAfter && typeof data.error.retryAfter === 'number') {
91
+ return data.error.retryAfter * 1000;
92
+ }
93
+ // Check Retry-After header
94
+ const retryAfter = response.headers?.['retry-after'];
95
+ if (retryAfter) {
96
+ const seconds = parseInt(retryAfter, 10);
97
+ if (!isNaN(seconds)) {
98
+ return seconds * 1000;
99
+ }
100
+ const date = new Date(retryAfter);
101
+ if (!isNaN(date.getTime())) {
102
+ const delay = date.getTime() - Date.now();
103
+ return delay > 0 ? delay : 0;
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+ /**
109
+ * Add retry interceptor to axios instance
110
+ */
111
+ function addRetryInterceptor(axiosInstance, config = {}) {
112
+ const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
113
+ axiosInstance.interceptors.response.use((response) => response, async (error) => {
114
+ // Type guard for axios error structure
115
+ const axiosError = error;
116
+ const requestConfig = axiosError.config;
117
+ if (!requestConfig) {
118
+ return Promise.reject(error instanceof Error ? error : new Error(String(error)));
119
+ }
120
+ if (requestConfig.__retryCount === undefined) {
121
+ requestConfig.__retryCount = 0;
122
+ }
123
+ const status = axiosError.response?.status;
124
+ if (!status || !isRetryableStatus(status) || requestConfig.__retryCount >= retryConfig.maxRetries) {
125
+ return Promise.reject(error instanceof Error ? error : new Error(String(error)));
126
+ }
127
+ requestConfig.__retryCount++;
128
+ let retryDelay;
129
+ const serverDelay = axiosError.response ? getServerSuggestedDelay(axiosError.response) : null;
130
+ if (serverDelay !== null) {
131
+ retryDelay = Math.min(serverDelay, retryConfig.maxDelay);
132
+ if (retryConfig.enableLogging) {
133
+ retryConfig.logger.log(`[Capsara SDK] Retry ${requestConfig.__retryCount}/${retryConfig.maxRetries} for ${status} - waiting ${retryDelay}ms (server suggested)`);
134
+ }
135
+ }
136
+ else {
137
+ retryDelay = calculateExponentialBackoff(requestConfig.__retryCount - 1, retryConfig.baseDelay, retryConfig.maxDelay);
138
+ if (retryConfig.enableLogging) {
139
+ retryConfig.logger.log(`[Capsara SDK] Retry ${requestConfig.__retryCount}/${retryConfig.maxRetries} for ${status} - waiting ${retryDelay}ms (exponential backoff)`);
140
+ }
141
+ }
142
+ await sleep(retryDelay);
143
+ return axiosInstance.request(requestConfig);
144
+ });
145
+ }
146
+ /**
147
+ * Create a configured axios instance with retry and optional auth
148
+ *
149
+ * This factory eliminates the HTTP setup duplication found in AuthClient,
150
+ * KeyManager, LimitsManager, AccountClient, and CapsaraClient.
151
+ *
152
+ * @param options - HTTP client configuration
153
+ * @returns Configured axios instance
154
+ */
155
+ export function createHttpClient(options) {
156
+ const timeoutConfig = { ...DEFAULT_TIMEOUT_CONFIG, ...options.timeout };
157
+ const axiosConfig = {
158
+ baseURL: options.baseUrl,
159
+ timeout: timeoutConfig.apiTimeout,
160
+ httpAgent: createHttpAgent(timeoutConfig),
161
+ httpsAgent: createHttpsAgent(timeoutConfig),
162
+ headers: {
163
+ 'User-Agent': buildUserAgent(options.userAgent),
164
+ 'X-SDK-Version': SDK_VERSION,
165
+ },
166
+ };
167
+ const axiosInstance = axios.create(axiosConfig);
168
+ // Add retry interceptor
169
+ addRetryInterceptor(axiosInstance, options.retry);
170
+ // Add auth interceptor if token getter provided
171
+ if (options.getToken) {
172
+ const getToken = options.getToken;
173
+ axiosInstance.interceptors.request.use((config) => {
174
+ const token = getToken();
175
+ if (token) {
176
+ config.headers.Authorization = `Bearer ${token}`;
177
+ }
178
+ return config;
179
+ });
180
+ }
181
+ return axiosInstance;
182
+ }
183
+ /**
184
+ * Create HTTP/HTTPS agent for raw requests with custom timeout
185
+ * @param protocol - 'http:' or 'https:'
186
+ * @param timeout - Request timeout in milliseconds
187
+ * @param config - Timeout configuration
188
+ */
189
+ export function createAgentForProtocol(protocol, timeout, config = DEFAULT_TIMEOUT_CONFIG) {
190
+ const agentConfig = {
191
+ keepAlive: true,
192
+ keepAliveMsecs: config.keepAliveInterval,
193
+ timeout,
194
+ maxSockets: config.maxSockets,
195
+ maxFreeSockets: config.maxFreeSockets,
196
+ };
197
+ return protocol === 'https:'
198
+ ? new https.Agent(agentConfig)
199
+ : new http.Agent(agentConfig);
200
+ }
201
+ //# sourceMappingURL=http-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-factory.js","sourceRoot":"","sources":["../../src/internal/http-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Internal module exports. */
2
+ export { createHttpClient, createAgentForProtocol, DEFAULT_TIMEOUT_CONFIG, type HttpClientOptions, type HttpTimeoutConfig, type RetryLogger, } from './http-factory.js';
3
+ export { RetryExecutor, createRetryExecutor, type RetryConfig, type RawHttpOptions, type RawHttpResponse, } from './retry-executor.js';
4
+ export { DecryptedCapsaCache, createCapsaCache, type CachedCapsa, type CachedFileMetadata, type CapsaCacheConfig, } from './capsa-cache.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Internal module exports. */
2
+ export { createHttpClient, createAgentForProtocol, DEFAULT_TIMEOUT_CONFIG, } from './http-factory.js';
3
+ export { RetryExecutor, createRetryExecutor, } from './retry-executor.js';
4
+ export { DecryptedCapsaCache, createCapsaCache, } from './capsa-cache.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,GAIvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAIpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GAIjB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Unified retry executor - eliminates retry logic duplication
3
+ * @file capsara.sdk/typescript/src/internal/retry-executor.ts
4
+ *
5
+ * This module provides a unified retry mechanism that can be used for:
6
+ * - Axios HTTP requests (via interceptor in http-factory)
7
+ * - Raw HTTP/HTTPS requests (for multipart uploads)
8
+ * - Generic async operations
9
+ */
10
+ import * as http from 'http';
11
+ import { type HttpTimeoutConfig } from './http-factory.js';
12
+ /**
13
+ * Logger interface for retry operations
14
+ */
15
+ export interface RetryLogger {
16
+ log: (message: string) => void;
17
+ }
18
+ /**
19
+ * Retry configuration
20
+ */
21
+ export interface RetryConfig {
22
+ maxRetries?: number;
23
+ baseDelay?: number;
24
+ maxDelay?: number;
25
+ enableLogging?: boolean;
26
+ logger?: RetryLogger;
27
+ }
28
+ /**
29
+ * Options for raw HTTP requests
30
+ */
31
+ export interface RawHttpOptions {
32
+ url: string;
33
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
34
+ headers?: Record<string, string>;
35
+ body?: Buffer | string;
36
+ timeout?: number;
37
+ timeoutConfig?: HttpTimeoutConfig;
38
+ }
39
+ /**
40
+ * Response from raw HTTP request
41
+ */
42
+ export interface RawHttpResponse {
43
+ statusCode: number;
44
+ headers: http.IncomingHttpHeaders;
45
+ body: Buffer;
46
+ }
47
+ /**
48
+ * Unified retry executor for both axios and raw HTTP requests
49
+ */
50
+ export declare class RetryExecutor {
51
+ private config;
52
+ constructor(config?: RetryConfig);
53
+ /**
54
+ * Execute a generic async operation with retry
55
+ */
56
+ execute<T>(operation: () => Promise<T>, isRetryable?: (error: unknown) => boolean): Promise<T>;
57
+ /**
58
+ * Execute a raw HTTP request with retry (for multipart uploads)
59
+ *
60
+ * This replaces the duplicated retry logic in:
61
+ * - CapsaraClient#sendCapsasWithRetry (121 lines)
62
+ * - CapsaraClient#downloadFileWithRetry (54 lines)
63
+ */
64
+ executeRawHttp(options: RawHttpOptions): Promise<RawHttpResponse>;
65
+ /**
66
+ * Make a single raw HTTP request
67
+ */
68
+ private makeRawRequest;
69
+ }
70
+ /**
71
+ * Create a retry executor with default or custom configuration
72
+ */
73
+ export declare function createRetryExecutor(config?: RetryConfig): RetryExecutor;
74
+ //# sourceMappingURL=retry-executor.d.ts.map