/** * File Organizer MCP Server v3.4.2 * Rate Limited Reader * * Wrapper that applies rate limiting to all file read operations. * SECURITY: All file reads MUST pass through rate limiting. * * @module readers/security/rate-limited-reader * @security Shepherd-Gamma Approved */ import { RateLimiter } from "../../services/security/rate-limiter.service.js"; import { FileOrganizerError } from "../../errors.js"; import { IAuditLogger } from "./audit-logger.service.js"; /** * Error thrown when rate limit is exceeded. * Includes reset time for client handling. * * @extends FileOrganizerError */ export declare class RateLimitError extends FileOrganizerError { readonly identifier: string; readonly resetIn: number; readonly limitType: "minute" | "hour"; constructor(identifier: string, resetIn: number, limitType?: "minute" | "hour"); } /** * Configuration options for RateLimitedReader. */ export interface RateLimitedReaderOptions { /** Maximum requests per minute (default: 100) */ maxRequestsPerMinute?: number; /** Maximum requests per hour (default: 500) */ maxRequestsPerHour?: number; /** Custom rate limiter instance (optional) */ rateLimiter?: RateLimiter; /** Custom audit logger instance (optional) */ auditLogger?: IAuditLogger; /** Component name for logging (default: 'RateLimitedReader') */ component?: string; } /** * Rate Limited Reader wrapper. * Applies token bucket rate limiting to all file operations. * * SECURITY: This wrapper MUST be used for all file read operations * to enforce rate limiting policies. * * @example * ```typescript * const reader = new RateLimitedReader({ * maxRequestsPerMinute: 100, * maxRequestsPerHour: 500 * }); * * // Apply rate limiting to a file read operation * const content = await reader.execute('user123', async () => { * return fs.readFile('/path/to/file.txt'); * }); * ``` */ export declare class RateLimitedReader { private readonly rateLimiter; private readonly auditLogger; private readonly component; constructor(options?: RateLimitedReaderOptions); /** * Check rate limit for an identifier without recording a request. * Useful for pre-flight checks. * * @param identifier - User or session identifier * @returns Object with allowed status and reset time if limited */ checkLimit(identifier: string): { allowed: boolean; resetIn?: number; }; /** * Execute a function with rate limiting. * The function will only execute if rate limit is not exceeded. * * SECURITY: The operation callback should only contain pre-validated operations. * Path validation is performed by callers (e.g., PathValidatorService) before * passing paths to this method. * * @param identifier - User or session identifier for rate limiting * @param operation - Async function to execute if allowed * @param context - Additional context for audit logging * @returns Result of the operation * @throws RateLimitError if rate limit is exceeded * * @example * ```typescript * const result = await reader.execute( * 'user123', * async () => fs.readFile('file.txt'), * { path: 'file.txt', operation: 'FILE_READ' } * ); * ``` */ execute(identifier: string, operation: () => Promise | T, context?: { path?: string; operation?: string; userId?: string; }): Promise; /** * Execute a file read operation with comprehensive rate limiting and audit logging. * This is the primary method for rate-limited file reads. * * SECURITY: Path validation is performed by callers (e.g., PathValidatorService) * before being passed to this method. The filePath parameter is logged but not * directly used for file operations - the readOperation callback handles that. * * TYPE SAFETY: The generic type parameter T is used solely for return type inference. * It does not involve external deserialization or user-controlled type parsing, * making it safe from type confusion attacks. The caller provides both the type * annotation and the implementation via readOperation. * * @param identifier - User or session identifier * @param filePath - Path of file being read (validated by callers) * @param readOperation - Function that performs the actual read * @param userId - Optional user ID override * @returns File read result * @throws RateLimitError if rate limit exceeded * * @example * ```typescript * const content = await reader.readFile( * 'session-123', * '/docs/file.txt', * async () => fs.readFile('/docs/file.txt') * ); * ``` */ readFile(identifier: string, filePath: string, readOperation: () => Promise, userId?: string): Promise; /** * Create a wrapped version of a function that applies rate limiting. * The wrapped function will check rate limits before executing. * * SECURITY: The wrapped function should only be used with pre-validated operations. * Path validation is performed by callers before invoking the wrapped function. * * @param fn - Function to wrap with rate limiting * @param getIdentifier - Function to extract identifier from arguments * @returns Rate-limited wrapper function * * @example * ```typescript * const readFile = reader.wrap( * (path: string) => fs.readFile(path), * (path) => getUserFromPath(path) * ); * * const content = await readFile('/docs/file.txt'); // Rate limited * ``` */ wrap(fn: (...args: T) => Promise, getIdentifier?: (...args: T) => string): (...args: T) => Promise; /** * Create a session-specific rate limited reader. * All operations will use the same session identifier. * * TYPE SAFETY: Generic type parameters are used solely for return type inference. * No external deserialization occurs - the type is only used to infer the return * type from the operation callback provided by the caller. * * @param sessionId - Session identifier for all operations * @param userId - Optional user ID for audit logging * @returns Session-bound rate limited operations */ forSession(sessionId: string, userId?: string): { execute: (operation: () => Promise, context?: { path?: string; operation?: string; }) => Promise; readFile: (filePath: string, readOperation: () => Promise) => Promise; checkLimit: () => { allowed: boolean; resetIn?: number; }; }; /** * Get current rate limit status for an identifier. * * @param identifier - User or session identifier * @returns Current rate limit status */ getStatus(identifier: string): { allowed: boolean; resetIn?: number; remaining?: number; }; /** * Detect which rate limit (minute or hour) was exceeded based on reset time. */ private detectLimitType; /** * Log successful operation to audit logger. */ private logSuccess; /** * Log failed operation to audit logger. */ private logFailure; } /** * Default rate limited reader instance. * Uses default rate limits: 100 req/min, 500 req/hour */ export declare const defaultRateLimitedReader: RateLimitedReader; /** * Factory function for creating configured rate limited readers. * * @param options - Configuration options * @returns Configured RateLimitedReader instance */ export declare function createRateLimitedReader(options?: RateLimitedReaderOptions): RateLimitedReader; /** * Higher-order function for applying rate limiting to any async function. * * @param fn - Function to rate limit * @param options - Rate limiting options * @returns Rate-limited version of the function * * @example * ```typescript * const readFile = withRateLimit( * fs.promises.readFile, * { maxRequestsPerMinute: 50 } * ); * * const content = await readFile('file.txt'); * ``` */ export declare function withRateLimit(fn: (...args: T) => Promise, options?: RateLimitedReaderOptions & { getIdentifier?: (...args: T) => string; }): (...args: T) => Promise; //# sourceMappingURL=rate-limited-reader.d.ts.map