/** * Types for unified key persistence. * * Supports both symmetric secrets and asymmetric key pairs * with a unified storage interface. * * @module @frontmcp/utils/key-persistence */ import type { StorageAdapter } from '../../storage/types'; /** * Base interface for all key data types. */ export interface BaseKeyData { /** Unique key identifier */ kid: string; /** Creation timestamp (ms since epoch) */ createdAt: number; /** Schema version for migrations */ version: number; } /** * Symmetric secret key data. * Used for encryption, HMAC, and other symmetric operations. */ export interface SecretKeyData extends BaseKeyData { type: 'secret'; /** Base64url-encoded secret bytes */ secret: string; /** Number of bytes in the secret */ bytes: number; } /** * Asymmetric key pair data (RSA or EC). * Used for JWT signing and verification. */ export interface AsymmetricKeyData extends BaseKeyData { type: 'asymmetric'; /** Algorithm identifier (RS256, RS384, RS512, ES256, ES384, ES512) */ alg: 'RS256' | 'RS384' | 'RS512' | 'ES256' | 'ES384' | 'ES512'; /** Private key in JWK format */ privateKey: JsonWebKey; /** Public JWKS for verification (contains keys array) */ publicJwk: { keys: JsonWebKey[]; }; } /** * Union of all key types. */ export type AnyKeyData = SecretKeyData | AsymmetricKeyData; /** * Options for KeyPersistence constructor. */ export interface KeyPersistenceOptions { /** * Storage adapter for key data. * Can be MemoryStorageAdapter, FileSystemStorageAdapter, or any StorageAdapter. */ storage: StorageAdapter; /** * Whether to throw an error on invalid key data. * If false, invalid data is silently ignored (returns null). * @default false */ throwOnInvalid?: boolean; /** * Enable in-memory caching for faster reads. * @default true */ enableCache?: boolean; } /** * Options for creating a KeyPersistence instance. */ export interface CreateKeyPersistenceOptions { /** * Storage type. * - 'auto': Auto-detect based on environment (filesystem in Node.js, indexeddb in browser) * - 'memory': Always use memory (keys lost on restart) * - 'filesystem': Always use filesystem (Node.js only) * - 'indexeddb': Use IndexedDB (browser only, persistent) * - 'localstorage': Use localStorage (browser only, persistent, ~5MB limit) * @default 'auto' */ type?: 'auto' | 'memory' | 'filesystem' | 'indexeddb' | 'localstorage'; /** * Base directory for filesystem storage. * Only used when type is 'filesystem' or 'auto' in Node.js. * @default '.frontmcp/keys' */ baseDir?: string; /** * Whether to throw on invalid key data. * @default false */ throwOnInvalid?: boolean; /** * Enable in-memory caching. * @default true */ enableCache?: boolean; /** * Optional 32-byte AES-256-GCM key for encrypting values at rest in localStorage. * Only used when type is 'localstorage' or 'auto' with localStorage fallback. * If not provided, HKDF-SHA256 derives a key from a fixed IKM using the page origin. */ encryptionKey?: Uint8Array; } /** * Options for creating a secret key. */ export interface CreateSecretOptions { /** * Number of bytes to generate. * @default 32 (256 bits) */ bytes?: number; } /** * Options for creating an asymmetric key. */ export interface CreateAsymmetricOptions { /** * Algorithm to use. * @default 'RS256' */ alg?: AsymmetricKeyData['alg']; }