/** * EncryptedTypedStorage * * A storage wrapper that provides transparent encryption/decryption * with key rotation support on top of StorageAdapter. * * Uses AES-256-GCM for encryption with automatic JSON serialization. * * @example * ```typescript * import { createStorage, EncryptedTypedStorage, randomBytes } from '@frontmcp/utils'; * * interface Secret { * apiKey: string; * refreshToken: string; * } * * const storage = await createStorage({ type: 'memory' }); * const keys = [ * { kid: 'key-2024', key: randomBytes(32) }, * { kid: 'key-2023', key: oldKey }, // For decrypting old data * ]; * * const secrets = new EncryptedTypedStorage(storage, { keys }); * * // Data is encrypted before storage * await secrets.set('user:123', { apiKey: 'sk-...', refreshToken: 'rt-...' }); * * // Data is decrypted on retrieval * const secret = await secrets.get('user:123'); * ``` */ import type { StorageAdapter, NamespacedStorage, SetOptions } from './types'; import type { EncryptedTypedStorageOptions, EncryptedSetEntry, EncryptionKey } from './encrypted-typed-storage.types'; /** * EncryptedTypedStorage provides transparent encryption/decryption * on top of StorageAdapter. * * Features: * - AES-256-GCM encryption for all stored values * - Automatic JSON serialization/deserialization * - Key rotation support (multiple keys, first is active) * - Optional Zod schema validation after decryption * - Batch operations (mget/mset) */ export declare class EncryptedTypedStorage { private readonly storage; private activeKey; private readonly keyMap; private readonly schema?; private readonly throwOnError; private readonly onKeyRotationNeeded?; private readonly clientBinding?; constructor(storage: StorageAdapter | NamespacedStorage, options: EncryptedTypedStorageOptions); /** * Get a decrypted value by key. * * @param key - Storage key * @returns The decrypted value, or null if not found or decryption fails */ get(key: string): Promise; /** * Encrypt and store a value. * * @param key - Storage key * @param value - Value to encrypt and store * @param options - Optional TTL and conditional flags */ set(key: string, value: T, options?: SetOptions): Promise; /** * Delete a key. * * @param key - Storage key * @returns true if key existed and was deleted */ delete(key: string): Promise; /** * Check if a key exists. * * @param key - Storage key * @returns true if key exists */ exists(key: string): Promise; /** * Get multiple decrypted values. * * @param keys - Array of storage keys * @returns Array of decrypted values (null for missing/invalid keys) */ mget(keys: string[]): Promise<(T | null)[]>; /** * Encrypt and store multiple values. * * @param entries - Array of key-value-options entries */ mset(entries: EncryptedSetEntry[]): Promise; /** * Delete multiple keys. * * @param keys - Array of storage keys * @returns Number of keys actually deleted */ mdelete(keys: string[]): Promise; /** * Update TTL on an existing key. * * @param key - Storage key * @param ttlSeconds - New TTL in seconds * @returns true if key exists and TTL was set */ expire(key: string, ttlSeconds: number): Promise; /** * Get remaining TTL for a key. * * @param key - Storage key * @returns TTL in seconds, -1 if no TTL, or null if key doesn't exist */ ttl(key: string): Promise; /** * List keys matching a pattern. * * @param pattern - Glob pattern (default: '*' for all keys) * @returns Array of matching keys */ keys(pattern?: string): Promise; /** * Count keys matching a pattern. * * @param pattern - Glob pattern (default: '*' for all keys) * @returns Number of matching keys */ count(pattern?: string): Promise; /** * Re-encrypt a value with the active key. * Useful for key rotation - reads with old key, writes with new key. * * @param key - Storage key to re-encrypt * @param options - Optional TTL for the re-encrypted value * @returns true if value was re-encrypted, false if not found */ reencrypt(key: string, options?: SetOptions): Promise; /** * Rotate the active encryption key. * New encryptions will use the new key; old keys remain for decryption. * * @param newKey - New encryption key to use for writes */ rotateKey(newKey: EncryptionKey): void; /** * Get the active key ID. */ get activeKeyId(): string; /** * Get all known key IDs. */ get keyIds(): string[]; /** * Get the underlying storage adapter. * Use with caution - operations bypass encryption. */ get raw(): StorageAdapter | NamespacedStorage; /** * Check if client-side key binding is enabled. * When true, encryption keys are derived from both server key and client secret. */ get hasClientBinding(): boolean; /** * Derive the actual encryption key. * * If clientBinding is configured, combines server key with client secret * using HKDF-SHA256 (RFC 5869) to produce the actual encryption key. * Otherwise, returns the server key as-is. * * This provides zero-knowledge encryption where: * - Server cannot decrypt without client secret (sessionId) * - Client cannot decrypt without server key * - Key derivation is deterministic (same inputs -> same derived key) * * @param serverKey - The server-side encryption key * @returns The key to use for actual encryption/decryption */ private deriveKey; /** * Encrypt a value using the active key. * If client binding is configured, uses derived key from server key + client secret. */ private encryptValue; /** * Decrypt and parse a stored value. */ private decryptAndParse; /** * Validate blob structure. */ private isValidBlob; }