// engine/runtime-security/validator.ts — SPEC-084 AC-01
// Orchestrates all security checkers over tool inputs (OCP — add checkers without modifying).
import { readFileSync, existsSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { pathTraversalChecker } from './checkers/path-traversal.js';
import { promptInjectionChecker } from './checkers/prompt-injection.js';
import { commandInjectionChecker } from './checkers/command-injection.js';
import { inputSanitizerChecker, sanitizeString } from './checkers/input-sanitizer.js';
import { sensitiveDataChecker } from './checkers/sensitive-data.js';
import { filePermissionsChecker } from './checkers/file-permissions.js';
import { contentSecurityChecker } from './checkers/content-security.js';
import { dependencyVulnChecker } from './checkers/dependency-vuln.js';
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
const DEFAULT_CONFIG_PATH = resolve(MODULE_DIR, '../../config/security-runtime-config.json');
// Registry of all checkers (OCP — add new checkers here without modifying orchestration logic)
const defaultCheckers = [
    pathTraversalChecker,
    promptInjectionChecker,
    commandInjectionChecker,
    inputSanitizerChecker,
    sensitiveDataChecker,
    filePermissionsChecker,
    contentSecurityChecker,
    dependencyVulnChecker,
];
let cachedConfig = null;
export function loadSecurityConfig(configPath) {
    const path = configPath ?? DEFAULT_CONFIG_PATH;
    try {
        const raw = readFileSync(path, 'utf-8');
        return JSON.parse(raw);
    }
    catch {
        return {
            level: 'standard',
            rateLimits: {
                read: { maxTokens: 60, refillRatePerSecond: 1, burstMultiplier: 2, burstDurationMs: 5000 },
                write: {
                    maxTokens: 30,
                    refillRatePerSecond: 0.5,
                    burstMultiplier: 2,
                    burstDurationMs: 5000,
                },
                destructive: {
                    maxTokens: 10,
                    refillRatePerSecond: 0.167,
                    burstMultiplier: 2,
                    burstDurationMs: 5000,
                },
            },
            allowedDirectories: [],
            customInjectionPatterns: [],
            disabledCheckers: [],
        };
    }
}
export function getSecurityConfig() {
    cachedConfig ??= loadSecurityConfig();
    return cachedConfig;
}
/** Load project-level override config if it exists */
export function getProjectConfig(projectPath) {
    const projectConfigPath = resolve(projectPath, 'security-config.json');
    if (existsSync(projectConfigPath)) {
        return loadSecurityConfig(projectConfigPath);
    }
    return getSecurityConfig();
}
/** Reset cached config (for testing) */
export function resetConfigCache() {
    cachedConfig = null;
}
function sanitizeInputs(inputs) {
    const sanitized = {};
    for (const [key, value] of Object.entries(inputs)) {
        if (typeof value === 'string') {
            sanitized[key] = sanitizeString(value);
        }
        else {
            sanitized[key] = value;
        }
    }
    return sanitized;
}
export function validateToolInput(toolName, inputs, config) {
    const effectiveConfig = config ?? getSecurityConfig();
    const allThreats = [];
    // Run all enabled checkers
    for (const checker of defaultCheckers) {
        if (effectiveConfig.disabledCheckers.includes(checker.type)) {
            continue;
        }
        const threats = checker.check(toolName, inputs, effectiveConfig);
        allThreats.push(...threats);
    }
    // Determine safety based on security level
    const hasCritical = allThreats.some((t) => t.severity === 'critical');
    const hasWarning = allThreats.some((t) => t.severity === 'warning');
    let safe;
    switch (effectiveConfig.level) {
        case 'strict':
            safe = !hasCritical && !hasWarning;
            break;
        case 'standard':
            safe = !hasCritical;
            break;
        case 'permissive':
            safe = true;
            break;
    }
    return {
        safe,
        threats: allThreats,
        sanitizedInputs: sanitizeInputs(inputs),
    };
}
//# sourceMappingURL=validator.js.map