@faizahmed/secret-keystore 1.1.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/src/index.d.ts ADDED
@@ -0,0 +1,641 @@
1
+ /**
2
+ * @faizahmed/secret-keystore - TypeScript Definitions
3
+ *
4
+ * Version 4.0
5
+ */
6
+
7
+ // Declare Buffer for environments without @types/node
8
+ declare global {
9
+ interface BufferConstructor {
10
+ from(data: string | ArrayBuffer | SharedArrayBuffer | Uint8Array, encoding?: string): Buffer;
11
+ }
12
+ interface Buffer extends Uint8Array {
13
+ toString(encoding?: string): string;
14
+ }
15
+ // eslint-disable-next-line no-var
16
+ var Buffer: BufferConstructor;
17
+ }
18
+
19
+ // ═══════════════════════════════════════════════════════════════════════════
20
+ // AWS OPTIONS
21
+ // ═══════════════════════════════════════════════════════════════════════════
22
+
23
+ export interface AwsCredentials {
24
+ accessKeyId: string;
25
+ secretAccessKey: string;
26
+ sessionToken?: string;
27
+ }
28
+
29
+ export interface AwsOptions {
30
+ credentials?: AwsCredentials;
31
+ region?: string;
32
+ }
33
+
34
+ // ═══════════════════════════════════════════════════════════════════════════
35
+ // ATTESTATION OPTIONS
36
+ // ═══════════════════════════════════════════════════════════════════════════
37
+
38
+ export type AttestationDocument = Buffer | (() => Buffer) | (() => Promise<Buffer>);
39
+
40
+ export interface AttestationOptions {
41
+ enabled?: boolean;
42
+ required?: boolean;
43
+ fallbackToStandard?: boolean;
44
+ document?: AttestationDocument;
45
+ }
46
+
47
+ // ═══════════════════════════════════════════════════════════════════════════
48
+ // LOGGER
49
+ // ═══════════════════════════════════════════════════════════════════════════
50
+
51
+ export interface Logger {
52
+ debug(message: string, ...args: unknown[]): void;
53
+ info(message: string, ...args: unknown[]): void;
54
+ warn(message: string, ...args: unknown[]): void;
55
+ error(message: string, ...args: unknown[]): void;
56
+ }
57
+
58
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
59
+
60
+ // ═══════════════════════════════════════════════════════════════════════════
61
+ // COMMON OPTIONS
62
+ // ═══════════════════════════════════════════════════════════════════════════
63
+
64
+ export interface CommonOptions {
65
+ aws?: AwsOptions;
66
+ attestation?: AttestationOptions;
67
+ logger?: Logger;
68
+ logLevel?: LogLevel;
69
+ }
70
+
71
+ // ═══════════════════════════════════════════════════════════════════════════
72
+ // ENCRYPT OPTIONS
73
+ // ═══════════════════════════════════════════════════════════════════════════
74
+
75
+ export type OutputFormat = 'base64' | 'buffer' | 'prefixed';
76
+
77
+ export interface EncryptOptions extends CommonOptions {
78
+ output?: {
79
+ format?: OutputFormat;
80
+ };
81
+ skip?: {
82
+ empty?: boolean;
83
+ alreadyEncrypted?: boolean;
84
+ };
85
+ continueOnError?: boolean;
86
+ }
87
+
88
+ // ═══════════════════════════════════════════════════════════════════════════
89
+ // DECRYPT OPTIONS
90
+ // ═══════════════════════════════════════════════════════════════════════════
91
+
92
+ export type InputFormat = 'auto' | 'base64' | 'buffer' | 'prefixed';
93
+
94
+ export interface DecryptOptions extends CommonOptions {
95
+ input?: {
96
+ format?: InputFormat;
97
+ };
98
+ skip?: {
99
+ unencrypted?: boolean;
100
+ };
101
+ validation?: {
102
+ format?: boolean;
103
+ kmsKeyMatch?: boolean;
104
+ };
105
+ continueOnError?: boolean;
106
+ }
107
+
108
+ // ═══════════════════════════════════════════════════════════════════════════
109
+ // PATH SELECTION OPTIONS
110
+ // ═══════════════════════════════════════════════════════════════════════════
111
+
112
+ export interface PathSelectionOptions {
113
+ paths?: string[];
114
+ patterns?: string[];
115
+ exclude?: {
116
+ paths?: string[];
117
+ patterns?: string[];
118
+ };
119
+ }
120
+
121
+ // ═══════════════════════════════════════════════════════════════════════════
122
+ // CONTENT OPTIONS
123
+ // ═══════════════════════════════════════════════════════════════════════════
124
+
125
+ export interface ContentOptions {
126
+ preserve?: {
127
+ comments?: boolean;
128
+ formatting?: boolean;
129
+ anchors?: boolean;
130
+ };
131
+ }
132
+
133
+ // ═══════════════════════════════════════════════════════════════════════════
134
+ // KEYSTORE OPTIONS
135
+ // ═══════════════════════════════════════════════════════════════════════════
136
+
137
+ export interface KeystoreValidationOptions {
138
+ noProcessEnvLeak?: boolean;
139
+ throwOnMissingKey?: boolean;
140
+ }
141
+
142
+ export interface KeystoreOptions extends Omit<DecryptOptions, 'validation'>, PathSelectionOptions {
143
+ security?: {
144
+ inMemoryEncryption?: boolean;
145
+ secureWipe?: boolean;
146
+ };
147
+ access?: {
148
+ ttl?: number | null;
149
+ autoRefresh?: boolean;
150
+ accessLimit?: number | null;
151
+ clearOnAccess?: boolean;
152
+ };
153
+ validation?: KeystoreValidationOptions;
154
+ retry?: {
155
+ attempts?: number;
156
+ delay?: number;
157
+ backoff?: 'linear' | 'exponential';
158
+ };
159
+ }
160
+
161
+ // ═══════════════════════════════════════════════════════════════════════════
162
+ // RESULT TYPES
163
+ // ═══════════════════════════════════════════════════════════════════════════
164
+
165
+ export interface FailedItem {
166
+ key: string;
167
+ error: Error;
168
+ }
169
+
170
+ export interface FailedPath {
171
+ path: string;
172
+ error: Error;
173
+ }
174
+
175
+ export interface ValuesResult {
176
+ values: Record<string, string>;
177
+ encrypted?: string[];
178
+ decrypted?: string[];
179
+ skipped: string[];
180
+ failed: FailedItem[];
181
+ }
182
+
183
+ export interface ObjectResult {
184
+ object: Record<string, unknown>;
185
+ encrypted?: string[];
186
+ decrypted?: string[];
187
+ skipped: string[];
188
+ failed: FailedPath[];
189
+ }
190
+
191
+ export interface ContentResult {
192
+ content: string;
193
+ encrypted?: string[];
194
+ decrypted?: string[];
195
+ skipped: string[];
196
+ failed: FailedItem[];
197
+ }
198
+
199
+ // ═══════════════════════════════════════════════════════════════════════════
200
+ // PARSED ENV ENTRY
201
+ // ═══════════════════════════════════════════════════════════════════════════
202
+
203
+ export interface ParsedEnvEntry {
204
+ type: 'empty' | 'comment' | 'keyvalue' | 'other';
205
+ key?: string;
206
+ value?: string;
207
+ inlineComment?: string;
208
+ raw: string;
209
+ }
210
+
211
+ // ═══════════════════════════════════════════════════════════════════════════
212
+ // CORE KMS OPERATIONS
213
+ // ═══════════════════════════════════════════════════════════════════════════
214
+
215
+ /** Encrypt a single value using AWS KMS */
216
+ export function encryptKMSValue(
217
+ plaintext: string,
218
+ kmsKeyId: string,
219
+ options?: EncryptOptions
220
+ ): Promise<string | Buffer>;
221
+
222
+ /** Decrypt a single value using AWS KMS */
223
+ export function decryptKMSValue(
224
+ ciphertext: string | Buffer,
225
+ kmsKeyId: string,
226
+ options?: DecryptOptions
227
+ ): Promise<string>;
228
+
229
+ /** Encrypt multiple key-value pairs using AWS KMS */
230
+ export function encryptKMSValues(
231
+ values: Record<string, string>,
232
+ kmsKeyId: string,
233
+ options?: EncryptOptions
234
+ ): Promise<ValuesResult>;
235
+
236
+ /** Decrypt multiple key-value pairs using AWS KMS */
237
+ export function decryptKMSValues(
238
+ values: Record<string, string>,
239
+ kmsKeyId: string,
240
+ options?: DecryptOptions
241
+ ): Promise<ValuesResult>;
242
+
243
+ // ═══════════════════════════════════════════════════════════════════════════
244
+ // FORMAT HELPERS
245
+ // ═══════════════════════════════════════════════════════════════════════════
246
+
247
+ export function isEncryptedFormat(value: string): boolean;
248
+ export function isKmsCiphertext(value: string): boolean;
249
+ export function isAlreadyEncrypted(value: string): boolean;
250
+ export function isEnvelopeFormat(buf: Buffer): boolean;
251
+ export function wrapCiphertext(ciphertext: string): string;
252
+ export function unwrapCiphertext(value: string): string;
253
+ export function maskKmsKeyId(keyId: string): string;
254
+
255
+ export const ENCRYPTED_PREFIX: string;
256
+ export const ENCRYPTED_SUFFIX: string;
257
+
258
+ // ═══════════════════════════════════════════════════════════════════════════
259
+ // PATH MATCHING
260
+ // ═══════════════════════════════════════════════════════════════════════════
261
+
262
+ export function getByPath<T = unknown>(obj: Record<string, unknown>, path: string): T | undefined;
263
+ export function setByPath<T extends Record<string, unknown>>(obj: T, path: string, value: unknown): T;
264
+ export function getAllPaths(obj: Record<string, unknown>, prefix?: string): string[];
265
+ export function matchesPattern(path: string, pattern: string): boolean;
266
+ export function filterPaths(allPaths: string[], options?: PathSelectionOptions): string[];
267
+ export function transformAtPaths(
268
+ obj: Record<string, unknown>,
269
+ paths: string[],
270
+ transformer: (value: unknown, path: string) => Promise<unknown>,
271
+ options?: { continueOnError?: boolean }
272
+ ): Promise<{
273
+ object: Record<string, unknown>;
274
+ transformed: string[];
275
+ skipped: string[];
276
+ failed: FailedPath[];
277
+ }>;
278
+
279
+ // ═══════════════════════════════════════════════════════════════════════════
280
+ // OBJECT-BASED OPERATIONS
281
+ // ═══════════════════════════════════════════════════════════════════════════
282
+
283
+ export interface EncryptObjectOptions extends EncryptOptions, PathSelectionOptions {}
284
+ export interface DecryptObjectOptions extends DecryptOptions, PathSelectionOptions {}
285
+
286
+ /** Encrypt values at selected paths in a nested object using AWS KMS */
287
+ export function encryptKMSObject(
288
+ obj: Record<string, unknown>,
289
+ kmsKeyId: string,
290
+ options?: EncryptObjectOptions
291
+ ): Promise<ObjectResult>;
292
+
293
+ /** Decrypt values at selected paths in a nested object using AWS KMS */
294
+ export function decryptKMSObject(
295
+ obj: Record<string, unknown>,
296
+ kmsKeyId: string,
297
+ options?: DecryptObjectOptions
298
+ ): Promise<ObjectResult>;
299
+
300
+ // ═══════════════════════════════════════════════════════════════════════════
301
+ // CONTENT-BASED OPERATIONS
302
+ // ═══════════════════════════════════════════════════════════════════════════
303
+
304
+ export interface EncryptContentOptions extends EncryptOptions, PathSelectionOptions, ContentOptions {}
305
+ export interface DecryptContentOptions extends DecryptOptions, PathSelectionOptions, ContentOptions {}
306
+
307
+ /** Encrypt .env content string using AWS KMS */
308
+ export function encryptKMSEnvContent(
309
+ content: string,
310
+ kmsKeyId: string,
311
+ options?: EncryptContentOptions
312
+ ): Promise<ContentResult>;
313
+
314
+ /** Decrypt .env content string using AWS KMS */
315
+ export function decryptKMSEnvContent(
316
+ content: string,
317
+ kmsKeyId: string,
318
+ options?: DecryptContentOptions
319
+ ): Promise<ContentResult>;
320
+
321
+ export function parseEnvContent(content: string): ParsedEnvEntry[];
322
+ export function reconstructEnvContent(parsed: ParsedEnvEntry[]): string;
323
+
324
+ /** Encrypt JSON content string using AWS KMS */
325
+ export function encryptKMSJsonContent(
326
+ content: string,
327
+ kmsKeyId: string,
328
+ options?: EncryptContentOptions
329
+ ): Promise<ContentResult>;
330
+
331
+ /** Decrypt JSON content string using AWS KMS */
332
+ export function decryptKMSJsonContent(
333
+ content: string,
334
+ kmsKeyId: string,
335
+ options?: DecryptContentOptions
336
+ ): Promise<ContentResult>;
337
+
338
+ /** Encrypt YAML content string using AWS KMS */
339
+ export function encryptKMSYamlContent(
340
+ content: string,
341
+ kmsKeyId: string,
342
+ options?: EncryptContentOptions
343
+ ): Promise<ContentResult>;
344
+
345
+ /** Decrypt YAML content string using AWS KMS */
346
+ export function decryptKMSYamlContent(
347
+ content: string,
348
+ kmsKeyId: string,
349
+ options?: DecryptContentOptions
350
+ ): Promise<ContentResult>;
351
+
352
+ // ═══════════════════════════════════════════════════════════════════════════
353
+ // YAML UTILITIES
354
+ // ═══════════════════════════════════════════════════════════════════════════
355
+
356
+ /** Check if js-yaml is installed (for complex YAML support) */
357
+ export function isJsYamlAvailable(): boolean;
358
+
359
+ /** Parse YAML content to object (uses js-yaml if available, falls back to simple parser) */
360
+ export function parseYaml(content: string): Record<string, unknown>;
361
+
362
+ /** Serialize object to YAML string (uses js-yaml if available) */
363
+ export function serializeYaml(obj: Record<string, unknown>): string;
364
+
365
+ // ═══════════════════════════════════════════════════════════════════════════
366
+ // OPTIONS & DEFAULTS
367
+ // ═══════════════════════════════════════════════════════════════════════════
368
+
369
+ export const RESERVED_KEYS: string[];
370
+ export const DEFAULT_AWS_OPTIONS: AwsOptions;
371
+ export const DEFAULT_ATTESTATION_OPTIONS: AttestationOptions;
372
+ export const DEFAULT_COMMON_OPTIONS: CommonOptions;
373
+ export const DEFAULT_ENCRYPT_OPTIONS: EncryptOptions;
374
+ export const DEFAULT_DECRYPT_OPTIONS: DecryptOptions;
375
+ export const DEFAULT_PATH_SELECTION_OPTIONS: PathSelectionOptions;
376
+ export const DEFAULT_CONTENT_OPTIONS: ContentOptions;
377
+ export const DEFAULT_KEYSTORE_OPTIONS: KeystoreOptions;
378
+
379
+ export function validateKmsKeyId(kmsKeyId: string): void;
380
+ export function validateAwsOptions(aws: AwsOptions): void;
381
+ export function validateAttestationOptions(attestation: AttestationOptions): void;
382
+ export function validatePathSelectionOptions(options: PathSelectionOptions): void;
383
+ export function validateCommonOptions(options: CommonOptions): void;
384
+
385
+ export function buildCommonOptions(options?: CommonOptions): CommonOptions;
386
+ export function buildEncryptOptions(options?: EncryptOptions): EncryptOptions;
387
+ export function buildDecryptOptions(options?: DecryptOptions): DecryptOptions;
388
+ export function buildPathSelectionOptions(options?: PathSelectionOptions): PathSelectionOptions;
389
+ export function buildContentOptions(options?: ContentOptions): ContentOptions;
390
+ export function buildKeystoreOptions(options?: KeystoreOptions): KeystoreOptions;
391
+ export function buildAwsSdkOptions(options?: { aws?: AwsOptions }): Record<string, unknown>;
392
+
393
+ export function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T;
394
+ export function createLogger(baseLogger: Logger | null, logLevel?: LogLevel): Logger;
395
+
396
+ // ═══════════════════════════════════════════════════════════════════════════
397
+ // ERROR CLASSES
398
+ // ═══════════════════════════════════════════════════════════════════════════
399
+
400
+ export class SecretKeyStoreError extends Error {
401
+ code: string;
402
+ cause?: Error;
403
+ timestamp: Date;
404
+ constructor(message: string, code: string, cause?: Error);
405
+ toJSON(): Record<string, unknown>;
406
+ }
407
+
408
+ export class KmsError extends SecretKeyStoreError {
409
+ kmsKeyId: string;
410
+ awsRequestId?: string;
411
+ constructor(message: string, code: string, kmsKeyId: string, cause?: Error);
412
+ }
413
+
414
+ export class AttestationError extends SecretKeyStoreError {
415
+ constructor(message: string, code: string, cause?: Error);
416
+ }
417
+
418
+ export class ContentError extends SecretKeyStoreError {
419
+ format?: string;
420
+ constructor(message: string, code: string, format?: string, cause?: Error);
421
+ }
422
+
423
+ export class PathError extends SecretKeyStoreError {
424
+ path?: string;
425
+ constructor(message: string, code: string, path?: string, cause?: Error);
426
+ }
427
+
428
+ export class EncryptionError extends SecretKeyStoreError {
429
+ key?: string;
430
+ constructor(message: string, code: string, key?: string, cause?: Error);
431
+ }
432
+
433
+ export class DecryptionError extends SecretKeyStoreError {
434
+ key?: string;
435
+ constructor(message: string, code: string, key?: string, cause?: Error);
436
+ }
437
+
438
+ export class KeystoreError extends SecretKeyStoreError {
439
+ constructor(message: string, code: string, cause?: Error);
440
+ }
441
+
442
+ export class ValidationError extends SecretKeyStoreError {
443
+ field?: string;
444
+ constructor(message: string, code: string, field?: string, cause?: Error);
445
+ }
446
+
447
+ // ═══════════════════════════════════════════════════════════════════════════
448
+ // ERROR CODES
449
+ // ═══════════════════════════════════════════════════════════════════════════
450
+
451
+ export const KMS_ERROR_CODES: {
452
+ KEY_NOT_FOUND: 'KMS_KEY_NOT_FOUND';
453
+ KEY_DISABLED: 'KMS_KEY_DISABLED';
454
+ ACCESS_DENIED: 'KMS_ACCESS_DENIED';
455
+ INVALID_CIPHERTEXT: 'KMS_INVALID_CIPHERTEXT';
456
+ THROTTLED: 'KMS_THROTTLED';
457
+ ENCRYPT_FAILED: 'KMS_ENCRYPT_FAILED';
458
+ DECRYPT_FAILED: 'KMS_DECRYPT_FAILED';
459
+ CONNECTION_ERROR: 'KMS_CONNECTION_ERROR';
460
+ };
461
+
462
+ export const ATTESTATION_ERROR_CODES: {
463
+ DOCUMENT_MISSING: 'ATTESTATION_DOCUMENT_MISSING';
464
+ DOCUMENT_INVALID: 'ATTESTATION_DOCUMENT_INVALID';
465
+ DOCUMENT_EXPIRED: 'ATTESTATION_DOCUMENT_EXPIRED';
466
+ GETTER_FAILED: 'ATTESTATION_GETTER_FAILED';
467
+ NOT_AVAILABLE: 'ATTESTATION_NOT_AVAILABLE';
468
+ RETRY_FAILED: 'ATTESTATION_RETRY_FAILED';
469
+ INIT_FAILED: 'ATTESTATION_INIT_FAILED';
470
+ CMS_UNWRAP_FAILED: 'ATTESTATION_CMS_UNWRAP_FAILED';
471
+ KEYPAIR_GENERATION_FAILED: 'ATTESTATION_KEYPAIR_GENERATION_FAILED';
472
+ ENDPOINT_UNREACHABLE: 'ATTESTATION_ENDPOINT_UNREACHABLE';
473
+ };
474
+
475
+ export const CONTENT_ERROR_CODES: {
476
+ PARSE_FAILED: 'CONTENT_PARSE_FAILED';
477
+ INVALID_FORMAT: 'CONTENT_INVALID_FORMAT';
478
+ EMPTY_CONTENT: 'CONTENT_EMPTY';
479
+ SERIALIZATION_FAILED: 'CONTENT_SERIALIZATION_FAILED';
480
+ };
481
+
482
+ export const PATH_ERROR_CODES: {
483
+ NOT_FOUND: 'PATH_NOT_FOUND';
484
+ INVALID_PATTERN: 'PATH_INVALID_PATTERN';
485
+ ACCESS_DENIED: 'PATH_ACCESS_DENIED';
486
+ };
487
+
488
+ export const ENCRYPTION_ERROR_CODES: {
489
+ FAILED: 'ENCRYPTION_FAILED';
490
+ INVALID_VALUE: 'ENCRYPTION_INVALID_VALUE';
491
+ ALREADY_ENCRYPTED: 'ENCRYPTION_ALREADY_ENCRYPTED';
492
+ };
493
+
494
+ export const DECRYPTION_ERROR_CODES: {
495
+ FAILED: 'DECRYPTION_FAILED';
496
+ INVALID_CIPHERTEXT: 'DECRYPTION_INVALID_CIPHERTEXT';
497
+ NOT_ENCRYPTED: 'DECRYPTION_NOT_ENCRYPTED';
498
+ };
499
+
500
+ export const KEYSTORE_ERROR_CODES: {
501
+ NOT_INITIALIZED: 'KEYSTORE_NOT_INITIALIZED';
502
+ ALREADY_INITIALIZED: 'KEYSTORE_ALREADY_INITIALIZED';
503
+ DESTROYED: 'KEYSTORE_DESTROYED';
504
+ SECRET_NOT_FOUND: 'SECRET_NOT_FOUND';
505
+ SECRET_EXPIRED: 'SECRET_EXPIRED';
506
+ ACCESS_LIMIT_EXCEEDED: 'SECRET_ACCESS_LIMIT_EXCEEDED';
507
+ INITIALIZATION_FAILED: 'KEYSTORE_INITIALIZATION_FAILED';
508
+ REFRESH_FAILED: 'KEYSTORE_REFRESH_FAILED';
509
+ };
510
+
511
+ export const VALIDATION_ERROR_CODES: {
512
+ REQUIRED_FIELD: 'VALIDATION_REQUIRED_FIELD';
513
+ INVALID_TYPE: 'VALIDATION_INVALID_TYPE';
514
+ INVALID_VALUE: 'VALIDATION_INVALID_VALUE';
515
+ INVALID_OPTIONS: 'VALIDATION_INVALID_OPTIONS';
516
+ KMS_KEY_REQUIRED: 'VALIDATION_KMS_KEY_REQUIRED';
517
+ PROCESS_ENV_LEAK: 'VALIDATION_PROCESS_ENV_LEAK';
518
+ };
519
+
520
+ export function isRecoverableError(error: Error): boolean;
521
+ export function createKmsErrorFromAws(awsError: Error, kmsKeyId: string, operation?: string): KmsError;
522
+
523
+ // ═══════════════════════════════════════════════════════════════════════════
524
+ // RUNTIME KEYSTORE
525
+ // ═══════════════════════════════════════════════════════════════════════════
526
+
527
+ export type KeystoreSourceType = 'env' | 'json' | 'yaml' | 'object' | 'values';
528
+
529
+ export interface KeystoreSource {
530
+ type: KeystoreSourceType;
531
+ content?: string;
532
+ object?: Record<string, unknown>;
533
+ values?: Record<string, string>;
534
+ }
535
+
536
+ export interface KeystoreMetadata {
537
+ initialized: boolean;
538
+ destroyed: boolean;
539
+ secretCount: number;
540
+ sourceType: KeystoreSourceType;
541
+ hasTTL: boolean;
542
+ ttl: number | null;
543
+ autoRefresh: boolean;
544
+ inMemoryEncryption: boolean;
545
+ }
546
+
547
+ export interface AccessStats {
548
+ createdAt: Date;
549
+ lastAccessedAt: Date | null;
550
+ accessCount: number;
551
+ expiresAt: Date | null;
552
+ isExpired: boolean;
553
+ }
554
+
555
+ export class SecretKeyStore {
556
+ constructor(source: KeystoreSource, kmsKeyId: string, options?: KeystoreOptions);
557
+ initialize(): Promise<void>;
558
+ get(key: string): string | undefined;
559
+ getSection(prefix: string): Record<string, string> | undefined;
560
+ getAll(): Record<string, string>;
561
+ has(key: string): boolean;
562
+ keys(): string[];
563
+ isInitialized(): boolean;
564
+ getMetadata(): KeystoreMetadata;
565
+ getAccessStats(key: string): AccessStats | null;
566
+ refresh(): Promise<void>;
567
+ clear(): void;
568
+ clearKey(key: string): void;
569
+ destroy(): void;
570
+ }
571
+
572
+ export function createSecretKeyStore(
573
+ source: KeystoreSource,
574
+ kmsKeyId: string,
575
+ options?: KeystoreOptions
576
+ ): Promise<SecretKeyStore>;
577
+
578
+ // ═══════════════════════════════════════════════════════════════════════════
579
+ // RUNTIME CONFIG LOADER
580
+ // ═══════════════════════════════════════════════════════════════════════════
581
+
582
+ export interface ConfigOptions extends KeystoreOptions {
583
+ /** REQUIRED KMS Key ID (explicit; no environment fallback). */
584
+ kmsKeyId: string;
585
+ /** Base directory for file discovery (default: process.cwd()). */
586
+ cwd?: string;
587
+ /** Explicit file path(s); when set, the cascade is skipped. */
588
+ path?: string | string[];
589
+ /** Environment name for the cascade (default: process.env.NODE_ENV). */
590
+ nodeEnv?: string;
591
+ /**
592
+ * Opt-in: also copy decrypted values into process.env (override).
593
+ * Discouraged — widens the RCE blast radius. Default: false.
594
+ */
595
+ populateProcessEnv?: boolean;
596
+ /** Target object for populateProcessEnv (default: process.env). */
597
+ processEnv?: Record<string, string | undefined>;
598
+ }
599
+
600
+ /**
601
+ * Discover and cascade .env files, decrypt their ENC[...] values via KMS, and
602
+ * load everything into an in-memory SecretKeyStore.
603
+ *
604
+ * Cascade order (later overrides earlier):
605
+ * .env → .env.local → .env.<NODE_ENV> → .env.<NODE_ENV>.local
606
+ *
607
+ * Decrypted values live only in the returned store — never on disk, and never
608
+ * in process.env unless populateProcessEnv is explicitly enabled.
609
+ */
610
+ export function config(options: ConfigOptions): Promise<SecretKeyStore>;
611
+
612
+ /** Resolve the ordered list of existing .env files for the cascade. */
613
+ export function resolveEnvFiles(options?: {
614
+ cwd?: string;
615
+ path?: string | string[];
616
+ nodeEnv?: string;
617
+ }): string[];
618
+
619
+ /** Merge parsed .env files into a single key→value map (later files win). */
620
+ export function mergeEnvFiles(files: string[]): {
621
+ merged: Record<string, string>;
622
+ used: string[];
623
+ };
624
+
625
+ // ═══════════════════════════════════════════════════════════════════════════
626
+ // KEY ROTATION
627
+ // ═══════════════════════════════════════════════════════════════════════════
628
+
629
+ export type ContentFormat = 'env' | 'json' | 'yaml';
630
+
631
+ /**
632
+ * Re-encrypt the already-encrypted values in a config file under a new KMS Key
633
+ * ID (decrypting with the old key first). Plaintext values are left untouched.
634
+ */
635
+ export function rotateKMSContent(
636
+ content: string,
637
+ format: ContentFormat,
638
+ oldKmsKeyId: string,
639
+ newKmsKeyId: string,
640
+ options?: EncryptContentOptions & DecryptContentOptions
641
+ ): Promise<{ content: string; rotated: string[] }>;