@frontmcp/utils 0.0.1 → 0.7.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.
- package/CHANGELOG.md +12 -0
- package/README.md +110 -0
- package/content/content.d.ts +43 -0
- package/content/index.d.ts +1 -0
- package/crypto/browser.d.ts +11 -0
- package/crypto/encrypted-blob.d.ts +157 -0
- package/crypto/index.d.ts +98 -0
- package/crypto/jwt-alg.d.ts +8 -0
- package/crypto/node.d.ts +59 -0
- package/crypto/pkce/index.d.ts +9 -0
- package/crypto/pkce/pkce.d.ts +140 -0
- package/crypto/runtime.d.ts +18 -0
- package/crypto/secret-persistence/index.d.ts +25 -0
- package/crypto/secret-persistence/persistence.d.ts +97 -0
- package/crypto/secret-persistence/schema.d.ts +34 -0
- package/crypto/secret-persistence/types.d.ts +65 -0
- package/crypto/types.d.ts +61 -0
- package/escape/escape.d.ts +101 -0
- package/escape/index.d.ts +1 -0
- package/esm/index.mjs +3264 -0
- package/esm/package.json +53 -0
- package/fs/fs.d.ts +254 -0
- package/fs/index.d.ts +1 -0
- package/http/http.d.ts +20 -0
- package/http/index.d.ts +1 -0
- package/index.d.ts +18 -0
- package/index.js +3425 -0
- package/naming/index.d.ts +1 -0
- package/naming/naming.d.ts +79 -0
- package/package.json +3 -2
- package/path/index.d.ts +1 -0
- package/path/path.d.ts +34 -0
- package/regex/index.d.ts +24 -0
- package/regex/patterns.d.ts +155 -0
- package/regex/safe-regex.d.ts +179 -0
- package/serialization/index.d.ts +1 -0
- package/serialization/serialization.d.ts +33 -0
- package/storage/adapters/base.d.ts +90 -0
- package/storage/adapters/index.d.ts +10 -0
- package/storage/adapters/memory.d.ts +99 -0
- package/storage/adapters/redis.d.ts +88 -0
- package/storage/adapters/upstash.d.ts +81 -0
- package/storage/adapters/vercel-kv.d.ts +69 -0
- package/storage/errors.d.ts +117 -0
- package/storage/factory.d.ts +70 -0
- package/storage/index.d.ts +13 -0
- package/storage/namespace.d.ts +88 -0
- package/storage/types.d.ts +428 -0
- package/storage/utils/index.d.ts +5 -0
- package/storage/utils/pattern.d.ts +71 -0
- package/storage/utils/ttl.d.ts +54 -0
- package/uri/index.d.ts +2 -0
- package/uri/uri-template.d.ts +92 -0
- package/uri/uri-validation.d.ts +46 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret persistence utilities for storing encryption secrets.
|
|
3
|
+
*
|
|
4
|
+
* Provides a secure way to persist secrets to disk for development environments.
|
|
5
|
+
* In production, use environment variables instead.
|
|
6
|
+
*
|
|
7
|
+
* @module @frontmcp/utils/secret-persistence
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { getOrCreateSecret } from '@frontmcp/utils';
|
|
12
|
+
*
|
|
13
|
+
* // Get or create a persisted secret
|
|
14
|
+
* const secret = await getOrCreateSecret({
|
|
15
|
+
* name: 'remember',
|
|
16
|
+
* secretPath: '.frontmcp/remember-secret.json',
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Use the secret for encryption
|
|
20
|
+
* const key = await deriveKey(secret);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type { SecretData, SecretPersistenceOptions, SecretValidationResult } from './types';
|
|
24
|
+
export { secretDataSchema, validateSecretData, parseSecretData } from './schema';
|
|
25
|
+
export { isSecretPersistenceEnabled, resolveSecretPath, loadSecret, saveSecret, deleteSecret, generateSecret, createSecretData, getOrCreateSecret, clearCachedSecret, isSecretCached, } from './persistence';
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret persistence utilities for storing encryption secrets.
|
|
3
|
+
*
|
|
4
|
+
* Follows the same pattern as OAuth JWK dev-key-persistence for consistency.
|
|
5
|
+
* Stores a random secret to a JSON file for use when no environment variable is set.
|
|
6
|
+
*
|
|
7
|
+
* This enables development environments to have consistent encryption keys
|
|
8
|
+
* without requiring manual configuration.
|
|
9
|
+
*
|
|
10
|
+
* @module @frontmcp/utils/secret-persistence
|
|
11
|
+
*/
|
|
12
|
+
import type { SecretData, SecretPersistenceOptions } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* Check if secret persistence is enabled based on environment and options.
|
|
15
|
+
*
|
|
16
|
+
* By default, persistence is:
|
|
17
|
+
* - Enabled in development (NODE_ENV !== 'production')
|
|
18
|
+
* - Disabled in production unless forceEnable is true
|
|
19
|
+
*
|
|
20
|
+
* @param options - Persistence options
|
|
21
|
+
* @returns true if persistence is enabled
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSecretPersistenceEnabled(options?: SecretPersistenceOptions): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the secret file path.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Persistence options
|
|
28
|
+
* @returns Absolute path to secret file
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveSecretPath(options?: SecretPersistenceOptions): string;
|
|
31
|
+
/**
|
|
32
|
+
* Load persisted secret from file.
|
|
33
|
+
*
|
|
34
|
+
* @param options - Persistence options
|
|
35
|
+
* @returns The loaded secret data or null if not found/invalid
|
|
36
|
+
*/
|
|
37
|
+
export declare function loadSecret(options?: SecretPersistenceOptions): Promise<SecretData | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Save secret to file.
|
|
40
|
+
*
|
|
41
|
+
* Uses atomic write (temp file + rename) to prevent corruption.
|
|
42
|
+
* Sets file permissions to 0o600 (owner read/write only) for security.
|
|
43
|
+
*
|
|
44
|
+
* @param secretData - Secret data to persist
|
|
45
|
+
* @param options - Persistence options
|
|
46
|
+
* @returns true if save succeeded, false otherwise
|
|
47
|
+
*/
|
|
48
|
+
export declare function saveSecret(secretData: SecretData, options?: SecretPersistenceOptions): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Delete persisted secret.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Persistence options
|
|
53
|
+
* @returns true if deleted or didn't exist, false on error
|
|
54
|
+
*/
|
|
55
|
+
export declare function deleteSecret(options?: SecretPersistenceOptions): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Generate a new random secret.
|
|
58
|
+
*
|
|
59
|
+
* @param bytes - Number of random bytes (default 32 = 256 bits)
|
|
60
|
+
* @returns Base64url-encoded random string
|
|
61
|
+
*/
|
|
62
|
+
export declare function generateSecret(bytes?: number): string;
|
|
63
|
+
/**
|
|
64
|
+
* Create a new secret data object with current timestamp.
|
|
65
|
+
*
|
|
66
|
+
* @param options - Options including secret bytes
|
|
67
|
+
* @returns New SecretData object
|
|
68
|
+
*/
|
|
69
|
+
export declare function createSecretData(options?: SecretPersistenceOptions): SecretData;
|
|
70
|
+
/**
|
|
71
|
+
* Get or create a persisted secret.
|
|
72
|
+
*
|
|
73
|
+
* This is the main entry point for getting a secret.
|
|
74
|
+
* It will:
|
|
75
|
+
* 1. Return cached secret if available (for this name)
|
|
76
|
+
* 2. Load from file if exists
|
|
77
|
+
* 3. Generate new secret and persist it
|
|
78
|
+
*
|
|
79
|
+
* Thread-safe: concurrent calls will share the same generation promise.
|
|
80
|
+
*
|
|
81
|
+
* @param options - Persistence options
|
|
82
|
+
* @returns The secret string
|
|
83
|
+
*/
|
|
84
|
+
export declare function getOrCreateSecret(options?: SecretPersistenceOptions): Promise<string>;
|
|
85
|
+
/**
|
|
86
|
+
* Clear the cached secret (for testing).
|
|
87
|
+
*
|
|
88
|
+
* @param options - Options to identify which secret to clear (by path)
|
|
89
|
+
*/
|
|
90
|
+
export declare function clearCachedSecret(options?: SecretPersistenceOptions): void;
|
|
91
|
+
/**
|
|
92
|
+
* Check if a secret is cached.
|
|
93
|
+
*
|
|
94
|
+
* @param options - Options to identify which secret to check
|
|
95
|
+
* @returns true if cached
|
|
96
|
+
*/
|
|
97
|
+
export declare function isSecretCached(options?: SecretPersistenceOptions): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation schema for secret data.
|
|
3
|
+
*
|
|
4
|
+
* @module @frontmcp/utils/secret-persistence
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import type { SecretData, SecretValidationResult } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Zod schema for SecretData.
|
|
10
|
+
*/
|
|
11
|
+
export declare const secretDataSchema: z.ZodObject<{
|
|
12
|
+
secret: z.ZodString;
|
|
13
|
+
createdAt: z.ZodNumber;
|
|
14
|
+
version: z.ZodNumber;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
/**
|
|
17
|
+
* Validate secret data structure.
|
|
18
|
+
*
|
|
19
|
+
* Checks:
|
|
20
|
+
* - Schema validation
|
|
21
|
+
* - createdAt is not in the future (with 1 minute drift allowance)
|
|
22
|
+
* - createdAt is not too old (100 years)
|
|
23
|
+
*
|
|
24
|
+
* @param data - Data to validate
|
|
25
|
+
* @returns Validation result
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateSecretData(data: unknown): SecretValidationResult;
|
|
28
|
+
/**
|
|
29
|
+
* Parse and validate secret data.
|
|
30
|
+
*
|
|
31
|
+
* @param data - Raw data to parse
|
|
32
|
+
* @returns Parsed secret data or null if invalid
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseSecretData(data: unknown): SecretData | null;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for secret persistence utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module @frontmcp/utils/secret-persistence
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Data structure for a persisted secret.
|
|
8
|
+
*/
|
|
9
|
+
export interface SecretData {
|
|
10
|
+
/** Random secret, base64url encoded (typically 32 bytes = 256 bits) */
|
|
11
|
+
secret: string;
|
|
12
|
+
/** Creation timestamp (ms since epoch) */
|
|
13
|
+
createdAt: number;
|
|
14
|
+
/** Version for future migrations */
|
|
15
|
+
version: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Options for secret persistence operations.
|
|
19
|
+
*/
|
|
20
|
+
export interface SecretPersistenceOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Path to store the secret file.
|
|
23
|
+
* If relative, resolved from current working directory.
|
|
24
|
+
* @default '.frontmcp/<name>-secret.json'
|
|
25
|
+
*/
|
|
26
|
+
secretPath?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Secret name used in default path and log messages.
|
|
29
|
+
* @default 'default'
|
|
30
|
+
*/
|
|
31
|
+
name?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Enable persistence in production (NOT RECOMMENDED for multi-server).
|
|
34
|
+
* In production, use environment variables instead.
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
forceEnable?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Number of bytes to generate for new secrets.
|
|
40
|
+
* @default 32 (256 bits)
|
|
41
|
+
*/
|
|
42
|
+
secretBytes?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Enable logging of persistence operations.
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
enableLogging?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Custom logger for persistence messages.
|
|
50
|
+
* Defaults to console.warn/console.error.
|
|
51
|
+
*/
|
|
52
|
+
logger?: {
|
|
53
|
+
warn: (message: string) => void;
|
|
54
|
+
error: (message: string) => void;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Result of validating secret data.
|
|
59
|
+
*/
|
|
60
|
+
export interface SecretValidationResult {
|
|
61
|
+
/** Whether the secret data is valid */
|
|
62
|
+
valid: boolean;
|
|
63
|
+
/** Error message if invalid */
|
|
64
|
+
error?: string;
|
|
65
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto Provider Types
|
|
3
|
+
*
|
|
4
|
+
* Defines the interface for cryptographic operations that work across
|
|
5
|
+
* Node.js and browser environments.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Encrypted blob structure for AES-256-GCM encryption.
|
|
9
|
+
* All fields are base64url encoded.
|
|
10
|
+
*/
|
|
11
|
+
export interface EncBlob {
|
|
12
|
+
alg: 'A256GCM';
|
|
13
|
+
iv: string;
|
|
14
|
+
tag: string;
|
|
15
|
+
data: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Crypto provider interface for cross-platform cryptographic operations.
|
|
19
|
+
* All operations are synchronous for consistency across platforms.
|
|
20
|
+
*/
|
|
21
|
+
export interface CryptoProvider {
|
|
22
|
+
/**
|
|
23
|
+
* Generate a UUID v4 string.
|
|
24
|
+
*/
|
|
25
|
+
randomUUID(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Generate cryptographically secure random bytes.
|
|
28
|
+
*/
|
|
29
|
+
randomBytes(length: number): Uint8Array;
|
|
30
|
+
/**
|
|
31
|
+
* Compute SHA-256 hash.
|
|
32
|
+
*/
|
|
33
|
+
sha256(data: string | Uint8Array): Uint8Array;
|
|
34
|
+
/**
|
|
35
|
+
* Compute SHA-256 hash and return as hex string.
|
|
36
|
+
*/
|
|
37
|
+
sha256Hex(data: string | Uint8Array): string;
|
|
38
|
+
/**
|
|
39
|
+
* Compute HMAC-SHA256.
|
|
40
|
+
*/
|
|
41
|
+
hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array;
|
|
42
|
+
/**
|
|
43
|
+
* HKDF-SHA256 key derivation (RFC 5869).
|
|
44
|
+
*/
|
|
45
|
+
hkdfSha256(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Uint8Array;
|
|
46
|
+
/**
|
|
47
|
+
* Encrypt using AES-256-GCM.
|
|
48
|
+
*/
|
|
49
|
+
encryptAesGcm(key: Uint8Array, plaintext: Uint8Array, iv: Uint8Array): {
|
|
50
|
+
ciphertext: Uint8Array;
|
|
51
|
+
tag: Uint8Array;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Decrypt using AES-256-GCM.
|
|
55
|
+
*/
|
|
56
|
+
decryptAesGcm(key: Uint8Array, ciphertext: Uint8Array, iv: Uint8Array, tag: Uint8Array): Uint8Array;
|
|
57
|
+
/**
|
|
58
|
+
* Constant-time comparison to prevent timing attacks.
|
|
59
|
+
*/
|
|
60
|
+
timingSafeEqual(a: Uint8Array, b: Uint8Array): boolean;
|
|
61
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML and JavaScript Escaping Utilities
|
|
3
|
+
*
|
|
4
|
+
* Functions for escaping strings to prevent XSS attacks in HTML output.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Escape HTML special characters to prevent XSS.
|
|
10
|
+
*
|
|
11
|
+
* Handles null/undefined by returning empty string.
|
|
12
|
+
* Converts non-string values to string before escaping.
|
|
13
|
+
*
|
|
14
|
+
* @param str - Value to escape (will be converted to string)
|
|
15
|
+
* @returns Escaped string safe for HTML content
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* escapeHtml('<script>alert("xss")</script>')
|
|
20
|
+
* // Returns: '<script>alert("xss")</script>'
|
|
21
|
+
*
|
|
22
|
+
* escapeHtml(null) // Returns: ''
|
|
23
|
+
* escapeHtml(123) // Returns: '123'
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function escapeHtml(str: unknown): string;
|
|
27
|
+
/**
|
|
28
|
+
* Escape string for use in HTML attributes.
|
|
29
|
+
*
|
|
30
|
+
* Lighter version that only escapes & and " characters,
|
|
31
|
+
* suitable for attribute values that are already quoted.
|
|
32
|
+
*
|
|
33
|
+
* @param str - String to escape
|
|
34
|
+
* @returns Escaped string safe for HTML attributes
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* escapeHtmlAttr('value with "quotes" & ampersand')
|
|
39
|
+
* // Returns: 'value with "quotes" & ampersand'
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function escapeHtmlAttr(str: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Escape string for use in JavaScript string literals.
|
|
45
|
+
*
|
|
46
|
+
* Escapes characters that could break out of a JS string context.
|
|
47
|
+
*
|
|
48
|
+
* @param str - String to escape
|
|
49
|
+
* @returns Escaped string safe for JS string literals
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* escapeJsString("it's a \"test\"")
|
|
54
|
+
* // Returns: "it\\'s a \\\"test\\\""
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function escapeJsString(str: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Escape script closing tags in JSON strings to prevent XSS.
|
|
60
|
+
*
|
|
61
|
+
* When embedding JSON in a <script> tag, the string `</script>` will
|
|
62
|
+
* prematurely close the script block. This function escapes the closing
|
|
63
|
+
* tag by replacing `</` with `<\/`.
|
|
64
|
+
*
|
|
65
|
+
* @param jsonString - JSON string (already passed through JSON.stringify)
|
|
66
|
+
* @returns Escaped JSON string safe for embedding in script tags
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const json = JSON.stringify({ html: '</script><script>alert(1)</script>' });
|
|
71
|
+
* escapeScriptClose(json);
|
|
72
|
+
* // Returns: '{"html":"<\\/script><script>alert(1)<\\/script>"}'
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function escapeScriptClose(jsonString: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Safely serialize a value to JSON for embedding in HTML <script> tags.
|
|
78
|
+
*
|
|
79
|
+
* Combines JSON.stringify with escapeScriptClose to prevent XSS attacks
|
|
80
|
+
* where malicious data contains `</script>` or other HTML-sensitive sequences.
|
|
81
|
+
*
|
|
82
|
+
* Handles edge cases:
|
|
83
|
+
* - undefined: Returns 'null' (since undefined is not valid JSON)
|
|
84
|
+
* - Circular references: Returns error placeholder
|
|
85
|
+
* - BigInt: Converted to string representation
|
|
86
|
+
* - Functions/Symbols: Omitted (standard JSON.stringify behavior)
|
|
87
|
+
*
|
|
88
|
+
* @param value - Value to serialize
|
|
89
|
+
* @returns Escaped JSON string safe for embedding in script tags
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const data = { html: '</script><script>alert("xss")</script>' };
|
|
94
|
+
* const safe = safeJsonForScript(data);
|
|
95
|
+
* // Returns: '{"html":"<\\/script><script>alert(\\"xss\\")<\\/script>"}'
|
|
96
|
+
*
|
|
97
|
+
* // Safe to use in:
|
|
98
|
+
* // <script>const data = ${safeJsonForScript(data)};</script>
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function safeJsonForScript(value: unknown): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { escapeHtml, escapeHtmlAttr, escapeJsString, escapeScriptClose, safeJsonForScript } from './escape';
|