@frontmcp/utils 0.7.2 → 0.8.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.
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Generic HMAC Signing Utilities
3
+ *
4
+ * Provides HMAC-SHA256 signing and verification for any JSON-serializable data.
5
+ * Protects against data tampering when stored in external systems.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { signData, verifyData } from '@frontmcp/utils';
10
+ *
11
+ * // Sign any data
12
+ * const signed = signData({ userId: '123', role: 'admin' }, { secret: 'my-secret' });
13
+ *
14
+ * // Verify and extract
15
+ * const data = verifyData(signed, { secret: 'my-secret' });
16
+ * if (data) {
17
+ * console.log(data.userId); // '123'
18
+ * }
19
+ * ```
20
+ */
21
+ /**
22
+ * Signed data wrapper structure.
23
+ * Contains the data and its HMAC signature.
24
+ */
25
+ export interface SignedData<T> {
26
+ /** The signed data */
27
+ data: T;
28
+ /** HMAC-SHA256 signature in base64url format */
29
+ sig: string;
30
+ /** Signature version for future algorithm changes */
31
+ v: 1;
32
+ }
33
+ /**
34
+ * Configuration for HMAC signing operations.
35
+ */
36
+ export interface HmacSigningConfig {
37
+ /**
38
+ * The secret key used for HMAC signing.
39
+ * Should be at least 32 bytes for security.
40
+ */
41
+ secret: string;
42
+ }
43
+ /**
44
+ * Sign data with HMAC-SHA256.
45
+ *
46
+ * Creates a tamper-evident wrapper around the data.
47
+ * Any modification to the data will invalidate the signature.
48
+ *
49
+ * @param data - The data to sign (must be JSON-serializable)
50
+ * @param config - Signing configuration with secret
51
+ * @returns JSON string containing signed data
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const signed = signData({ key: 'value' }, { secret: 'my-secret' });
56
+ * await redis.set('mykey', signed);
57
+ * ```
58
+ */
59
+ export declare function signData<T>(data: T, config: HmacSigningConfig): string;
60
+ /**
61
+ * Verify and extract signed data.
62
+ *
63
+ * Validates the HMAC signature and returns the data if valid.
64
+ * Returns null if the signature is invalid or the data is corrupted.
65
+ *
66
+ * @param signedJson - JSON string from signData()
67
+ * @param config - Signing configuration with secret
68
+ * @returns The verified data or null if invalid
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const raw = await redis.get('mykey');
73
+ * const data = verifyData<MyType>(raw, { secret: 'my-secret' });
74
+ * if (!data) {
75
+ * // Data was tampered with or corrupted
76
+ * }
77
+ * ```
78
+ */
79
+ export declare function verifyData<T>(signedJson: string, config: HmacSigningConfig): T | null;
80
+ /**
81
+ * Check if a stored value is signed data.
82
+ * Useful for migrating from unsigned to signed data.
83
+ *
84
+ * @param json - Raw JSON string from storage
85
+ * @returns true if the data appears to be signed
86
+ */
87
+ export declare function isSignedData(json: string): boolean;
88
+ /**
89
+ * Verify or parse data, supporting both signed and unsigned formats.
90
+ * Useful for backwards compatibility during migration.
91
+ *
92
+ * @param json - Raw JSON string from storage
93
+ * @param config - Signing configuration with secret
94
+ * @returns The data (verified if signed, parsed if unsigned) or null
95
+ */
96
+ export declare function verifyOrParseData<T>(json: string, config: HmacSigningConfig): T | null;
package/crypto/index.d.ts CHANGED
@@ -86,6 +86,15 @@ export declare function base64urlEncode(data: Uint8Array): string;
86
86
  * Decode a base64url string to Uint8Array.
87
87
  */
88
88
  export declare function base64urlDecode(data: string): Uint8Array;
89
+ /**
90
+ * Encode a Uint8Array to standard base64 string.
91
+ * RFC 4648 Section 4: Uses +/= characters, suitable for HTTP Basic auth.
92
+ */
93
+ export declare function base64Encode(data: Uint8Array): string;
94
+ /**
95
+ * Decode a standard base64 string to Uint8Array.
96
+ */
97
+ export declare function base64Decode(data: string): Uint8Array;
89
98
  /**
90
99
  * Compute SHA-256 hash and return as base64url string.
91
100
  * Commonly used for PKCE code_challenge (S256 method).
@@ -96,3 +105,5 @@ export { isNode, isBrowser, assertNode } from './runtime';
96
105
  export { type EncryptedBlob, EncryptedBlobError, encryptValue, decryptValue, tryDecryptValue, serializeBlob, deserializeBlob, tryDeserializeBlob, isValidEncryptedBlob, encryptAndSerialize, deserializeAndDecrypt, tryDeserializeAndDecrypt, } from './encrypted-blob';
97
106
  export { MIN_CODE_VERIFIER_LENGTH, MAX_CODE_VERIFIER_LENGTH, DEFAULT_CODE_VERIFIER_LENGTH, PkceError, generateCodeVerifier, generateCodeChallenge, verifyCodeChallenge, generatePkcePair, isValidCodeVerifier, isValidCodeChallenge, type PkcePair, } from './pkce';
98
107
  export { type SecretData, type SecretPersistenceOptions, type SecretValidationResult, secretDataSchema, validateSecretData, parseSecretData, isSecretPersistenceEnabled, resolveSecretPath, loadSecret, saveSecret, deleteSecret, generateSecret, createSecretData, getOrCreateSecret, clearCachedSecret, isSecretCached, } from './secret-persistence';
108
+ export { type SignedData, type HmacSigningConfig, signData, verifyData, isSignedData, verifyOrParseData, } from './hmac-signing';
109
+ export { type BaseKeyData, type SecretKeyData, type AsymmetricKeyData, type AnyKeyData, type KeyPersistenceOptions, type CreateKeyPersistenceOptions, type CreateSecretOptions, type CreateAsymmetricOptions, type KeyValidationResult, asymmetricAlgSchema, secretKeyDataSchema, asymmetricKeyDataSchema, anyKeyDataSchema, validateKeyData, parseKeyData, isSecretKeyData, isAsymmetricKeyData, KeyPersistence, createKeyPersistence, createKeyPersistenceWithStorage, } from './key-persistence';
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Factory functions for KeyPersistence.
3
+ *
4
+ * Provides convenient ways to create KeyPersistence instances
5
+ * with auto-detection of storage backend.
6
+ *
7
+ * @module @frontmcp/utils/key-persistence
8
+ */
9
+ import type { StorageAdapter } from '../../storage/types';
10
+ import { KeyPersistence } from './key-persistence';
11
+ import type { CreateKeyPersistenceOptions } from './types';
12
+ /**
13
+ * Create a KeyPersistence instance with auto-detected storage.
14
+ *
15
+ * In Node.js: Uses filesystem storage at `.frontmcp/keys/` by default
16
+ * In browser: Uses memory storage (keys lost on refresh)
17
+ *
18
+ * @param options - Configuration options
19
+ * @returns KeyPersistence instance (storage already connected)
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Auto-detect storage
24
+ * const keys = await createKeyPersistence();
25
+ *
26
+ * // Force memory storage
27
+ * const memKeys = await createKeyPersistence({ type: 'memory' });
28
+ *
29
+ * // Custom directory for filesystem
30
+ * const fsKeys = await createKeyPersistence({
31
+ * type: 'filesystem',
32
+ * baseDir: '.my-app/keys',
33
+ * });
34
+ * ```
35
+ */
36
+ export declare function createKeyPersistence(options?: CreateKeyPersistenceOptions): Promise<KeyPersistence>;
37
+ /**
38
+ * Create a KeyPersistence instance with an explicit storage adapter.
39
+ *
40
+ * Use this when you want to provide your own storage backend
41
+ * (e.g., Redis, custom adapter).
42
+ *
43
+ * Note: The storage adapter must already be connected.
44
+ *
45
+ * @param storage - Connected storage adapter
46
+ * @param options - Additional options
47
+ * @returns KeyPersistence instance
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * import { createStorage } from '@frontmcp/utils';
52
+ *
53
+ * // Use Redis for distributed key storage
54
+ * const redis = await createStorage({ type: 'redis' });
55
+ * const keys = createKeyPersistenceWithStorage(redis);
56
+ * ```
57
+ */
58
+ export declare function createKeyPersistenceWithStorage(storage: StorageAdapter, options?: Pick<CreateKeyPersistenceOptions, 'throwOnInvalid' | 'enableCache'>): KeyPersistence;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * KeyPersistence Module
3
+ *
4
+ * Unified key persistence for browser and Node.js environments.
5
+ * Uses StorageAdapter abstraction to support both memory (browser)
6
+ * and filesystem (Node.js) backends.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createKeyPersistence } from '@frontmcp/utils';
11
+ *
12
+ * // Auto-detect storage (filesystem in Node.js, memory in browser)
13
+ * const keys = await createKeyPersistence();
14
+ *
15
+ * // Get or create a secret
16
+ * const secret = await keys.getOrCreateSecret('encryption-key');
17
+ * console.log(secret.secret); // base64url-encoded secret
18
+ *
19
+ * // Store a custom key
20
+ * await keys.set({
21
+ * type: 'secret',
22
+ * kid: 'my-key',
23
+ * secret: 'abc...',
24
+ * bytes: 32,
25
+ * createdAt: Date.now(),
26
+ * version: 1,
27
+ * });
28
+ * ```
29
+ *
30
+ * @module @frontmcp/utils/key-persistence
31
+ */
32
+ export type { BaseKeyData, SecretKeyData, AsymmetricKeyData, AnyKeyData, KeyPersistenceOptions, CreateKeyPersistenceOptions, CreateSecretOptions, CreateAsymmetricOptions, } from './types';
33
+ export { asymmetricAlgSchema, secretKeyDataSchema, asymmetricKeyDataSchema, anyKeyDataSchema, validateKeyData, parseKeyData, isSecretKeyData, isAsymmetricKeyData, type KeyValidationResult, } from './schemas';
34
+ export { KeyPersistence } from './key-persistence';
35
+ export { createKeyPersistence, createKeyPersistenceWithStorage } from './factory';
@@ -0,0 +1,143 @@
1
+ /**
2
+ * KeyPersistence - Unified key management with storage abstraction.
3
+ *
4
+ * Provides a high-level API for storing and retrieving cryptographic keys
5
+ * with any storage backend (memory, filesystem, Redis, etc.).
6
+ *
7
+ * @module @frontmcp/utils/key-persistence
8
+ */
9
+ import type { StorageAdapter } from '../../storage/types';
10
+ import type { AnyKeyData, SecretKeyData, AsymmetricKeyData, KeyPersistenceOptions, CreateSecretOptions } from './types';
11
+ /**
12
+ * KeyPersistence provides a unified API for storing and retrieving
13
+ * cryptographic keys with any storage backend.
14
+ *
15
+ * Features:
16
+ * - Type-safe key storage with Zod validation
17
+ * - In-memory caching for fast reads
18
+ * - Support for symmetric secrets and asymmetric key pairs
19
+ * - Works with any StorageAdapter (Memory, FileSystem, Redis, etc.)
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { KeyPersistence, MemoryStorageAdapter } from '@frontmcp/utils';
24
+ *
25
+ * const storage = new MemoryStorageAdapter();
26
+ * await storage.connect();
27
+ *
28
+ * const keys = new KeyPersistence({ storage });
29
+ *
30
+ * // Get or create a secret
31
+ * const secret = await keys.getOrCreateSecret('encryption-key');
32
+ * console.log(secret.secret); // base64url string
33
+ *
34
+ * // Store a custom key
35
+ * await keys.set({
36
+ * type: 'secret',
37
+ * kid: 'my-key',
38
+ * secret: 'abc...',
39
+ * bytes: 32,
40
+ * createdAt: Date.now(),
41
+ * version: 1,
42
+ * });
43
+ *
44
+ * // List all keys
45
+ * const kids = await keys.list();
46
+ * ```
47
+ */
48
+ export declare class KeyPersistence {
49
+ private readonly storage;
50
+ private readonly cache;
51
+ private readonly enableCache;
52
+ private readonly throwOnInvalid;
53
+ constructor(options: KeyPersistenceOptions);
54
+ /**
55
+ * Get a key by ID.
56
+ *
57
+ * @param kid - Key identifier
58
+ * @returns Key data or null if not found
59
+ */
60
+ get<T extends AnyKeyData = AnyKeyData>(kid: string): Promise<T | null>;
61
+ /**
62
+ * Get a secret key by ID.
63
+ *
64
+ * @param kid - Key identifier
65
+ * @returns Secret key data or null if not found or wrong type
66
+ */
67
+ getSecret(kid: string): Promise<SecretKeyData | null>;
68
+ /**
69
+ * Get an asymmetric key by ID.
70
+ *
71
+ * @param kid - Key identifier
72
+ * @returns Asymmetric key data or null if not found or wrong type
73
+ */
74
+ getAsymmetric(kid: string): Promise<AsymmetricKeyData | null>;
75
+ /**
76
+ * Store a key.
77
+ *
78
+ * @param key - Key data to store
79
+ */
80
+ set(key: AnyKeyData): Promise<void>;
81
+ /**
82
+ * Delete a key.
83
+ *
84
+ * @param kid - Key identifier
85
+ * @returns true if key existed and was deleted
86
+ */
87
+ delete(kid: string): Promise<boolean>;
88
+ /**
89
+ * Check if a key exists.
90
+ *
91
+ * @param kid - Key identifier
92
+ * @returns true if key exists
93
+ */
94
+ has(kid: string): Promise<boolean>;
95
+ /**
96
+ * List all key IDs.
97
+ *
98
+ * @returns Array of key identifiers
99
+ */
100
+ list(): Promise<string[]>;
101
+ /**
102
+ * Get or create a secret key.
103
+ *
104
+ * If a key with the given ID exists and is a valid secret key,
105
+ * it is returned. Otherwise, a new secret key is generated.
106
+ *
107
+ * @param kid - Key identifier
108
+ * @param options - Options for key creation
109
+ * @returns Secret key data
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const secret = await keys.getOrCreateSecret('encryption-key');
114
+ * const bytes = base64urlDecode(secret.secret);
115
+ * ```
116
+ */
117
+ getOrCreateSecret(kid: string, options?: CreateSecretOptions): Promise<SecretKeyData>;
118
+ /**
119
+ * Clear the in-memory cache.
120
+ *
121
+ * Useful when you want to force a reload from storage.
122
+ */
123
+ clearCache(): void;
124
+ /**
125
+ * Clear cache for a specific key.
126
+ *
127
+ * @param kid - Key identifier
128
+ */
129
+ clearCacheFor(kid: string): void;
130
+ /**
131
+ * Check if a key is in the cache.
132
+ *
133
+ * @param kid - Key identifier
134
+ * @returns true if key is cached
135
+ */
136
+ isCached(kid: string): boolean;
137
+ /**
138
+ * Get the underlying storage adapter.
139
+ *
140
+ * Use with caution - direct storage access bypasses validation.
141
+ */
142
+ getAdapter(): StorageAdapter;
143
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Zod schemas for key persistence validation.
3
+ *
4
+ * @module @frontmcp/utils/key-persistence
5
+ */
6
+ import { z } from 'zod';
7
+ import type { AnyKeyData, SecretKeyData, AsymmetricKeyData } from './types';
8
+ /**
9
+ * Supported asymmetric algorithms.
10
+ */
11
+ export declare const asymmetricAlgSchema: z.ZodEnum<{
12
+ RS256: "RS256";
13
+ RS384: "RS384";
14
+ RS512: "RS512";
15
+ ES256: "ES256";
16
+ ES384: "ES384";
17
+ ES512: "ES512";
18
+ }>;
19
+ /**
20
+ * Zod schema for SecretKeyData.
21
+ */
22
+ export declare const secretKeyDataSchema: z.ZodObject<{
23
+ kid: z.ZodString;
24
+ createdAt: z.ZodNumber;
25
+ version: z.ZodNumber;
26
+ type: z.ZodLiteral<"secret">;
27
+ secret: z.ZodString;
28
+ bytes: z.ZodNumber;
29
+ }, z.core.$strip>;
30
+ /**
31
+ * Zod schema for AsymmetricKeyData.
32
+ */
33
+ export declare const asymmetricKeyDataSchema: z.ZodObject<{
34
+ kid: z.ZodString;
35
+ createdAt: z.ZodNumber;
36
+ version: z.ZodNumber;
37
+ type: z.ZodLiteral<"asymmetric">;
38
+ alg: z.ZodEnum<{
39
+ RS256: "RS256";
40
+ RS384: "RS384";
41
+ RS512: "RS512";
42
+ ES256: "ES256";
43
+ ES384: "ES384";
44
+ ES512: "ES512";
45
+ }>;
46
+ privateKey: z.ZodObject<{
47
+ kty: z.ZodOptional<z.ZodString>;
48
+ use: z.ZodOptional<z.ZodString>;
49
+ alg: z.ZodOptional<z.ZodString>;
50
+ kid: z.ZodOptional<z.ZodString>;
51
+ n: z.ZodOptional<z.ZodString>;
52
+ e: z.ZodOptional<z.ZodString>;
53
+ d: z.ZodOptional<z.ZodString>;
54
+ p: z.ZodOptional<z.ZodString>;
55
+ q: z.ZodOptional<z.ZodString>;
56
+ dp: z.ZodOptional<z.ZodString>;
57
+ dq: z.ZodOptional<z.ZodString>;
58
+ qi: z.ZodOptional<z.ZodString>;
59
+ x: z.ZodOptional<z.ZodString>;
60
+ y: z.ZodOptional<z.ZodString>;
61
+ crv: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$loose>;
63
+ publicJwk: z.ZodObject<{
64
+ keys: z.ZodArray<z.ZodObject<{
65
+ kty: z.ZodOptional<z.ZodString>;
66
+ use: z.ZodOptional<z.ZodString>;
67
+ alg: z.ZodOptional<z.ZodString>;
68
+ kid: z.ZodOptional<z.ZodString>;
69
+ n: z.ZodOptional<z.ZodString>;
70
+ e: z.ZodOptional<z.ZodString>;
71
+ d: z.ZodOptional<z.ZodString>;
72
+ p: z.ZodOptional<z.ZodString>;
73
+ q: z.ZodOptional<z.ZodString>;
74
+ dp: z.ZodOptional<z.ZodString>;
75
+ dq: z.ZodOptional<z.ZodString>;
76
+ qi: z.ZodOptional<z.ZodString>;
77
+ x: z.ZodOptional<z.ZodString>;
78
+ y: z.ZodOptional<z.ZodString>;
79
+ crv: z.ZodOptional<z.ZodString>;
80
+ }, z.core.$loose>>;
81
+ }, z.core.$strip>;
82
+ }, z.core.$strip>;
83
+ /**
84
+ * Zod schema for AnyKeyData (discriminated union).
85
+ */
86
+ export declare const anyKeyDataSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
87
+ kid: z.ZodString;
88
+ createdAt: z.ZodNumber;
89
+ version: z.ZodNumber;
90
+ type: z.ZodLiteral<"secret">;
91
+ secret: z.ZodString;
92
+ bytes: z.ZodNumber;
93
+ }, z.core.$strip>, z.ZodObject<{
94
+ kid: z.ZodString;
95
+ createdAt: z.ZodNumber;
96
+ version: z.ZodNumber;
97
+ type: z.ZodLiteral<"asymmetric">;
98
+ alg: z.ZodEnum<{
99
+ RS256: "RS256";
100
+ RS384: "RS384";
101
+ RS512: "RS512";
102
+ ES256: "ES256";
103
+ ES384: "ES384";
104
+ ES512: "ES512";
105
+ }>;
106
+ privateKey: z.ZodObject<{
107
+ kty: z.ZodOptional<z.ZodString>;
108
+ use: z.ZodOptional<z.ZodString>;
109
+ alg: z.ZodOptional<z.ZodString>;
110
+ kid: z.ZodOptional<z.ZodString>;
111
+ n: z.ZodOptional<z.ZodString>;
112
+ e: z.ZodOptional<z.ZodString>;
113
+ d: z.ZodOptional<z.ZodString>;
114
+ p: z.ZodOptional<z.ZodString>;
115
+ q: z.ZodOptional<z.ZodString>;
116
+ dp: z.ZodOptional<z.ZodString>;
117
+ dq: z.ZodOptional<z.ZodString>;
118
+ qi: z.ZodOptional<z.ZodString>;
119
+ x: z.ZodOptional<z.ZodString>;
120
+ y: z.ZodOptional<z.ZodString>;
121
+ crv: z.ZodOptional<z.ZodString>;
122
+ }, z.core.$loose>;
123
+ publicJwk: z.ZodObject<{
124
+ keys: z.ZodArray<z.ZodObject<{
125
+ kty: z.ZodOptional<z.ZodString>;
126
+ use: z.ZodOptional<z.ZodString>;
127
+ alg: z.ZodOptional<z.ZodString>;
128
+ kid: z.ZodOptional<z.ZodString>;
129
+ n: z.ZodOptional<z.ZodString>;
130
+ e: z.ZodOptional<z.ZodString>;
131
+ d: z.ZodOptional<z.ZodString>;
132
+ p: z.ZodOptional<z.ZodString>;
133
+ q: z.ZodOptional<z.ZodString>;
134
+ dp: z.ZodOptional<z.ZodString>;
135
+ dq: z.ZodOptional<z.ZodString>;
136
+ qi: z.ZodOptional<z.ZodString>;
137
+ x: z.ZodOptional<z.ZodString>;
138
+ y: z.ZodOptional<z.ZodString>;
139
+ crv: z.ZodOptional<z.ZodString>;
140
+ }, z.core.$loose>>;
141
+ }, z.core.$strip>;
142
+ }, z.core.$strip>], "type">;
143
+ /**
144
+ * Result of validating key data.
145
+ */
146
+ export interface KeyValidationResult {
147
+ /** Whether the key data is valid */
148
+ valid: boolean;
149
+ /** Parsed key data if valid */
150
+ data?: AnyKeyData;
151
+ /** Error message if invalid */
152
+ error?: string;
153
+ }
154
+ /**
155
+ * Validate key data structure and timestamps.
156
+ *
157
+ * Checks:
158
+ * - Schema validation
159
+ * - createdAt is not in the future (with 1 minute drift allowance)
160
+ * - createdAt is not too old (100 years)
161
+ *
162
+ * @param data - Data to validate
163
+ * @returns Validation result
164
+ */
165
+ export declare function validateKeyData(data: unknown): KeyValidationResult;
166
+ /**
167
+ * Parse and validate key data.
168
+ *
169
+ * @param data - Raw data to parse
170
+ * @returns Parsed key data or null if invalid
171
+ */
172
+ export declare function parseKeyData(data: unknown): AnyKeyData | null;
173
+ /**
174
+ * Check if key data is a secret key.
175
+ */
176
+ export declare function isSecretKeyData(data: AnyKeyData): data is SecretKeyData;
177
+ /**
178
+ * Check if key data is an asymmetric key.
179
+ */
180
+ export declare function isAsymmetricKeyData(data: AnyKeyData): data is AsymmetricKeyData;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Types for unified key persistence.
3
+ *
4
+ * Supports both symmetric secrets and asymmetric key pairs
5
+ * with a unified storage interface.
6
+ *
7
+ * @module @frontmcp/utils/key-persistence
8
+ */
9
+ import type { StorageAdapter } from '../../storage/types';
10
+ /**
11
+ * Base interface for all key data types.
12
+ */
13
+ export interface BaseKeyData {
14
+ /** Unique key identifier */
15
+ kid: string;
16
+ /** Creation timestamp (ms since epoch) */
17
+ createdAt: number;
18
+ /** Schema version for migrations */
19
+ version: number;
20
+ }
21
+ /**
22
+ * Symmetric secret key data.
23
+ * Used for encryption, HMAC, and other symmetric operations.
24
+ */
25
+ export interface SecretKeyData extends BaseKeyData {
26
+ type: 'secret';
27
+ /** Base64url-encoded secret bytes */
28
+ secret: string;
29
+ /** Number of bytes in the secret */
30
+ bytes: number;
31
+ }
32
+ /**
33
+ * Asymmetric key pair data (RSA or EC).
34
+ * Used for JWT signing and verification.
35
+ */
36
+ export interface AsymmetricKeyData extends BaseKeyData {
37
+ type: 'asymmetric';
38
+ /** Algorithm identifier (RS256, RS384, RS512, ES256, ES384, ES512) */
39
+ alg: 'RS256' | 'RS384' | 'RS512' | 'ES256' | 'ES384' | 'ES512';
40
+ /** Private key in JWK format */
41
+ privateKey: JsonWebKey;
42
+ /** Public JWKS for verification (contains keys array) */
43
+ publicJwk: {
44
+ keys: JsonWebKey[];
45
+ };
46
+ }
47
+ /**
48
+ * Union of all key types.
49
+ */
50
+ export type AnyKeyData = SecretKeyData | AsymmetricKeyData;
51
+ /**
52
+ * Options for KeyPersistence constructor.
53
+ */
54
+ export interface KeyPersistenceOptions {
55
+ /**
56
+ * Storage adapter for key data.
57
+ * Can be MemoryStorageAdapter, FileSystemStorageAdapter, or any StorageAdapter.
58
+ */
59
+ storage: StorageAdapter;
60
+ /**
61
+ * Whether to throw an error on invalid key data.
62
+ * If false, invalid data is silently ignored (returns null).
63
+ * @default false
64
+ */
65
+ throwOnInvalid?: boolean;
66
+ /**
67
+ * Enable in-memory caching for faster reads.
68
+ * @default true
69
+ */
70
+ enableCache?: boolean;
71
+ }
72
+ /**
73
+ * Options for creating a KeyPersistence instance.
74
+ */
75
+ export interface CreateKeyPersistenceOptions {
76
+ /**
77
+ * Storage type.
78
+ * - 'auto': Auto-detect based on environment (filesystem in Node.js, memory in browser)
79
+ * - 'memory': Always use memory (keys lost on restart)
80
+ * - 'filesystem': Always use filesystem (Node.js only)
81
+ * @default 'auto'
82
+ */
83
+ type?: 'auto' | 'memory' | 'filesystem';
84
+ /**
85
+ * Base directory for filesystem storage.
86
+ * Only used when type is 'filesystem' or 'auto' in Node.js.
87
+ * @default '.frontmcp/keys'
88
+ */
89
+ baseDir?: string;
90
+ /**
91
+ * Whether to throw on invalid key data.
92
+ * @default false
93
+ */
94
+ throwOnInvalid?: boolean;
95
+ /**
96
+ * Enable in-memory caching.
97
+ * @default true
98
+ */
99
+ enableCache?: boolean;
100
+ }
101
+ /**
102
+ * Options for creating a secret key.
103
+ */
104
+ export interface CreateSecretOptions {
105
+ /**
106
+ * Number of bytes to generate.
107
+ * @default 32 (256 bits)
108
+ */
109
+ bytes?: number;
110
+ }
111
+ /**
112
+ * Options for creating an asymmetric key.
113
+ */
114
+ export interface CreateAsymmetricOptions {
115
+ /**
116
+ * Algorithm to use.
117
+ * @default 'RS256'
118
+ */
119
+ alg?: AsymmetricKeyData['alg'];
120
+ }