/**
 * Scanner Aggregator
 *
 * Orchestrates all deterministic scanners and aggregates results.
 * Runs scanners in parallel for performance.
 *
 * @module scanners
 */
export * from "./types.js";
export { runDependencyAudit, checkNpmAvailable } from "./dependencies.js";
export { runTypeScriptAnalysis, calculateTypeCoverage } from "./typescript.js";
export { runSecretsScanner, checkGitleaksAvailable } from "./secrets.js";
export { runSemgrep, checkSemgrepAvailable, generateSupabaseRules } from "./semgrep.js";
export { runBandit, checkBanditAvailable, detectPython } from "./bandit.js";
export { runGosec, checkGosecAvailable, detectGo } from "./gosec.js";
export { runTrivy, checkTrivyAvailable, detectIaC } from "./trivy.js";
export { runEslint, checkEslintAvailable, detectEslint } from "./eslint.js";
export { runBrakeman, checkBrakemanAvailable, detectRails } from "./brakeman.js";
// Mythos-class scanners
export { runBinaryAnalysis, checkBinaryAnalysisAvailable, detectNativeModules } from "./binary-analysis.js";
export { runMemorySafetyAnalysis, checkCppcheckAvailable, checkCargoGeigerAvailable, detectUnsafeLanguages } from "./memory-safety.js";
export { runRaceConditionAnalysis } from "./race-condition.js";
// Healthcare compliance scanner (HIPAA, 42 CFR Part 2)
export { runHealthcareScanner, isHealthcareProject } from "./healthcare.js";
// IaC scanners (Terraform, Pulumi, CloudFormation)
export { runTfsec, runCheckov, runTerraformScanners, checkTfsecAvailable, checkCheckovAvailable, detectTerraform } from "./terraform.js";
// OpenAPI/Swagger security scanner
export { runSpectral, runOpenAPIScan, checkSpectralAvailable, findOpenAPISpecs, detectOpenAPI } from "./openapi.js";
// Rust security scanner
export { runCargoAudit, runClippy, runRustScanners, checkCargoAuditAvailable, checkClippyAvailable, detectRust } from "./rust.js";
// DAST scanner (Nuclei)
export { runNuclei, runDASTScan, runQuickDASTScan, checkNucleiAvailable, generateDASTReport, formatDASTReport } from "./dast.js";
// Vaspera proprietary detection engine
export { runDetection, runDetectionWithCustomRules, listAvailableRules, getDetectionCategories, getBuiltinRules, BUILTIN_RULES, } from "./detection/index.js";
import { DEFAULT_SCANNER_OPTIONS } from "./types.js";
import { runDependencyAudit } from "./dependencies.js";
import { runTypeScriptAnalysis } from "./typescript.js";
import { runSecretsScanner } from "./secrets.js";
import { runSemgrep } from "./semgrep.js";
import { runBandit, detectPython } from "./bandit.js";
import { runGosec, detectGo } from "./gosec.js";
import { runTrivy } from "./trivy.js";
import { runEslint } from "./eslint.js";
import { runBrakeman } from "./brakeman.js";
import { detectTerraform } from "./terraform.js";
import { runDetection as runDetectionEngine } from "./detection/index.js";
import { logger } from "../logger.js";
import { access } from "fs/promises";
import { join } from "path";
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
/**
 * Run all enabled scanners and aggregate results
 */
export async function runAllScanners(projectPath, options) {
    const opts = { ...DEFAULT_SCANNER_OPTIONS, ...options };
    const startTime = Date.now();
    const timestamp = new Date().toISOString();
    logger.info("scanners.aggregator_starting", {
        projectPath,
        scanners: {
            semgrep: opts.semgrep,
            dependencies: opts.dependencies,
            secrets: opts.secrets,
            typescript: opts.typescript,
        },
    });
    // Run enabled scanners in parallel
    const scannerPromises = [];
    const scannerNames = [];
    if (opts.semgrep) {
        scannerPromises.push(runSemgrep(projectPath, {
            customRulesDir: opts.semgrepRulesDir,
            timeout: opts.timeout,
        }));
        scannerNames.push("semgrep");
    }
    if (opts.dependencies) {
        scannerPromises.push(runDependencyAudit(projectPath));
        scannerNames.push("npm-audit");
    }
    if (opts.secrets) {
        scannerPromises.push(runSecretsScanner(projectPath));
        scannerNames.push("gitleaks");
    }
    if (opts.typescript) {
        scannerPromises.push(runTypeScriptAnalysis(projectPath));
        scannerNames.push("tsc");
    }
    if (opts.eslint) {
        scannerPromises.push(runEslint(projectPath, { timeout: opts.timeout }));
        scannerNames.push("eslint");
    }
    // Wait for all scanners to complete
    const results = await Promise.all(scannerPromises);
    // Build result map
    const scannerResults = results;
    // Deduplicate findings (same file:line from multiple scanners)
    const allFindings = deduplicateFindings(results.flatMap((r) => r.findings));
    // Calculate severity counts
    const bySeverity = {
        critical: 0,
        high: 0,
        medium: 0,
        low: 0,
        info: 0,
    };
    for (const finding of allFindings) {
        bySeverity[finding.severity]++;
    }
    // Calculate per-scanner counts
    const byScanner = {
        semgrep: 0,
        "npm-audit": 0,
        gitleaks: 0,
        tsc: 0,
        eslint: 0,
        bandit: 0,
        gosec: 0,
        brakeman: 0,
        trivy: 0,
        "binary-analysis": 0,
        "memory-safety": 0,
        "race-condition": 0,
        healthcare: 0,
        logic: 0,
        dast: 0,
        zap: 0,
        nuclei: 0,
        terraform: 0,
        tfsec: 0,
        checkov: 0,
        openapi: 0,
        spectral: 0,
        rust: 0,
        "cargo-audit": 0,
        clippy: 0,
        detection: 0,
        plugin: 0,
    };
    for (const finding of allFindings) {
        if (finding.scanner in byScanner) {
            byScanner[finding.scanner]++;
        }
    }
    // Identify failed scanners
    const failedScanners = scannerResults
        .filter((r) => !r.success)
        .map((r) => r.scanner);
    const result = {
        timestamp,
        projectPath,
        scanners: scannerResults,
        totalFindings: allFindings.length,
        bySeverity,
        byScanner,
        totalDuration: Date.now() - startTime,
        allSucceeded: failedScanners.length === 0,
        failedScanners,
    };
    logger.info("scanners.aggregator_complete", {
        totalFindings: result.totalFindings,
        bySeverity: result.bySeverity,
        duration: result.totalDuration,
        failedScanners: result.failedScanners,
    });
    return result;
}
/**
 * Run Vaspera proprietary detection engine as a scanner
 */
export async function runDetectionScanner(projectPath, options) {
    const startTime = Date.now();
    try {
        const result = await runDetectionEngine({
            projectPath,
            timeout: options?.timeout,
        });
        const findings = result.matches.map((match) => ({
            scanner: "detection",
            ruleId: match.ruleId,
            file: match.file,
            line: match.line,
            column: match.column,
            endLine: match.endLine,
            endColumn: match.endColumn,
            message: match.message,
            severity: match.severity,
            confidence: match.confidence,
            category: match.category,
            cweIds: match.cweIds,
            evidence: match.evidence,
            fixAvailable: !!match.autofixPatternId,
            metadata: match.taintPath ? { taintPath: match.taintPath } : undefined,
        }));
        return {
            scanner: "detection",
            findings,
            duration: result.duration,
            success: result.success,
            error: result.errors?.join("; "),
            filesScanned: result.filesAnalyzed,
            rulesUsed: result.matches.map((m) => m.ruleId).filter((v, i, a) => a.indexOf(v) === i),
        };
    }
    catch (error) {
        return {
            scanner: "detection",
            findings: [],
            duration: Date.now() - startTime,
            success: false,
            error: error instanceof Error ? error.message : "Unknown error",
        };
    }
}
/**
 * Detect if project uses JavaScript/TypeScript
 */
export async function detectJavaScript(projectPath) {
    try {
        await access(join(projectPath, "package.json"));
        return true;
    }
    catch {
        // Check for JS/TS files
        try {
            const { stdout } = await execAsync(`find "${projectPath}" -maxdepth 3 \\( -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" \\) | head -1`, { timeout: 5000 });
            return stdout.trim().length > 0;
        }
        catch {
            return false;
        }
    }
}
/**
 * Detect if project uses Ruby
 */
export async function detectRuby(projectPath) {
    try {
        await access(join(projectPath, "Gemfile"));
        return true;
    }
    catch {
        try {
            await access(join(projectPath, "Rakefile"));
            return true;
        }
        catch {
            // Check for .rb files
            try {
                const { stdout } = await execAsync(`find "${projectPath}" -maxdepth 3 -name "*.rb" | head -1`, { timeout: 5000 });
                return stdout.trim().length > 0;
            }
            catch {
                return false;
            }
        }
    }
}
/**
 * Detect if project uses Java
 */
export async function detectJava(projectPath) {
    try {
        await access(join(projectPath, "pom.xml"));
        return true;
    }
    catch {
        try {
            await access(join(projectPath, "build.gradle"));
            return true;
        }
        catch {
            try {
                await access(join(projectPath, "build.gradle.kts"));
                return true;
            }
            catch {
                // Check for .java files
                try {
                    const { stdout } = await execAsync(`find "${projectPath}" -maxdepth 3 -name "*.java" | head -1`, { timeout: 5000 });
                    return stdout.trim().length > 0;
                }
                catch {
                    return false;
                }
            }
        }
    }
}
/**
 * Detect if project uses Docker
 */
export async function detectDocker(projectPath) {
    try {
        const { stdout } = await execAsync(`find "${projectPath}" -maxdepth 2 \\( -name "Dockerfile*" -o -name "docker-compose*.yml" -o -name "docker-compose*.yaml" \\) | head -1`, { timeout: 5000 });
        return stdout.trim().length > 0;
    }
    catch {
        return false;
    }
}
/**
 * Detect all project languages and technologies
 */
export async function detectProjectLanguages(projectPath) {
    const [javascript, python, go, ruby, java, docker, terraform] = await Promise.all([
        detectJavaScript(projectPath),
        detectPython(projectPath),
        detectGo(projectPath),
        detectRuby(projectPath),
        detectJava(projectPath),
        detectDocker(projectPath),
        detectTerraform(projectPath),
    ]);
    return {
        javascript,
        python,
        go,
        ruby,
        java,
        docker,
        terraform,
    };
}
/**
 * Run all scanners with automatic language detection
 *
 * Automatically enables language-specific scanners based on project files:
 * - JavaScript/TypeScript → npm-audit, tsc, eslint
 * - Python → bandit
 * - Go → gosec
 * - Ruby → brakeman (when implemented)
 * - Docker/Terraform → trivy
 *
 * Always runs: semgrep, gitleaks (if available)
 */
export async function runAllScannersWithAutoDetect(projectPath, options) {
    const startTime = Date.now();
    // Detect languages
    const languages = await detectProjectLanguages(projectPath);
    logger.info("scanners.auto_detect_languages", {
        projectPath,
        languages,
    });
    // Build scanner options based on detected languages
    const scannerOptions = {
        // Always enabled
        semgrep: true,
        secrets: true,
        // JavaScript/TypeScript
        dependencies: languages.javascript,
        typescript: languages.javascript,
        eslint: languages.javascript,
        // Python
        bandit: languages.python,
        // Go
        gosec: languages.go,
        // Ruby (when implemented)
        brakeman: languages.ruby,
        // Container/IaC
        trivy: languages.docker || languages.terraform,
        // Timeout
        timeout: options?.timeout,
        semgrepRulesDir: options?.semgrepRulesDir,
    };
    // Apply force enable overrides
    if (options?.forceEnable) {
        for (const scanner of options.forceEnable) {
            if (scanner === "npm-audit")
                scannerOptions.dependencies = true;
            else if (scanner === "tsc")
                scannerOptions.typescript = true;
            else if (scanner === "gitleaks")
                scannerOptions.secrets = true;
            else if (scanner in scannerOptions) {
                scannerOptions[scanner] = true;
            }
        }
    }
    // Apply force disable overrides
    if (options?.forceDisable) {
        for (const scanner of options.forceDisable) {
            if (scanner === "npm-audit")
                scannerOptions.dependencies = false;
            else if (scanner === "tsc")
                scannerOptions.typescript = false;
            else if (scanner === "gitleaks")
                scannerOptions.secrets = false;
            else if (scanner in scannerOptions) {
                scannerOptions[scanner] = false;
            }
        }
    }
    logger.info("scanners.auto_detect_options", {
        scannerOptions,
        forceEnable: options?.forceEnable,
        forceDisable: options?.forceDisable,
    });
    // Run scanners with auto-detected options
    const result = await runAllScannersExtended(projectPath, scannerOptions);
    return {
        ...result,
        detectedLanguages: languages,
    };
}
/**
 * Extended version of runAllScanners that includes all language-specific scanners
 */
async function runAllScannersExtended(projectPath, options) {
    const startTime = Date.now();
    const timestamp = new Date().toISOString();
    logger.info("scanners.extended_aggregator_starting", {
        projectPath,
        scanners: options,
    });
    // Run enabled scanners in parallel
    const scannerPromises = [];
    const scannerNames = [];
    if (options.semgrep) {
        scannerPromises.push(runSemgrep(projectPath, {
            customRulesDir: options.semgrepRulesDir,
            timeout: options.timeout,
        }));
        scannerNames.push("semgrep");
    }
    if (options.dependencies) {
        scannerPromises.push(runDependencyAudit(projectPath));
        scannerNames.push("npm-audit");
    }
    if (options.secrets) {
        scannerPromises.push(runSecretsScanner(projectPath));
        scannerNames.push("gitleaks");
    }
    if (options.typescript) {
        scannerPromises.push(runTypeScriptAnalysis(projectPath));
        scannerNames.push("tsc");
    }
    if (options.eslint) {
        scannerPromises.push(runEslint(projectPath, { timeout: options.timeout }));
        scannerNames.push("eslint");
    }
    if (options.bandit) {
        scannerPromises.push(runBandit(projectPath, { timeout: options.timeout }));
        scannerNames.push("bandit");
    }
    if (options.gosec) {
        scannerPromises.push(runGosec(projectPath, { timeout: options.timeout }));
        scannerNames.push("gosec");
    }
    if (options.trivy) {
        scannerPromises.push(runTrivy(projectPath, { timeout: options.timeout }));
        scannerNames.push("trivy");
    }
    if (options.brakeman) {
        scannerPromises.push(runBrakeman(projectPath, { timeout: options.timeout }));
        scannerNames.push("brakeman");
    }
    // Wait for all scanners to complete
    const results = await Promise.all(scannerPromises);
    // Deduplicate findings
    const allFindings = deduplicateFindings(results.flatMap((r) => r.findings));
    // Calculate severity counts
    const bySeverity = {
        critical: 0,
        high: 0,
        medium: 0,
        low: 0,
        info: 0,
    };
    for (const finding of allFindings) {
        bySeverity[finding.severity]++;
    }
    // Calculate per-scanner counts
    const byScanner = {
        semgrep: 0,
        "npm-audit": 0,
        gitleaks: 0,
        tsc: 0,
        eslint: 0,
        bandit: 0,
        gosec: 0,
        brakeman: 0,
        trivy: 0,
        "binary-analysis": 0,
        "memory-safety": 0,
        "race-condition": 0,
        healthcare: 0,
        logic: 0,
        dast: 0,
        zap: 0,
        nuclei: 0,
        terraform: 0,
        tfsec: 0,
        checkov: 0,
        openapi: 0,
        spectral: 0,
        rust: 0,
        "cargo-audit": 0,
        clippy: 0,
        detection: 0,
        plugin: 0,
    };
    for (const finding of allFindings) {
        if (finding.scanner in byScanner) {
            byScanner[finding.scanner]++;
        }
    }
    // Identify failed scanners
    const failedScanners = results
        .filter((r) => !r.success)
        .map((r) => r.scanner);
    const result = {
        timestamp,
        projectPath,
        scanners: results,
        totalFindings: allFindings.length,
        bySeverity,
        byScanner,
        totalDuration: Date.now() - startTime,
        allSucceeded: failedScanners.length === 0,
        failedScanners,
    };
    logger.info("scanners.extended_aggregator_complete", {
        totalFindings: result.totalFindings,
        bySeverity: result.bySeverity,
        duration: result.totalDuration,
        failedScanners: result.failedScanners,
        scannersRun: scannerNames,
    });
    return result;
}
/**
 * Deduplicate findings that have the same file:line:message
 */
function deduplicateFindings(findings) {
    const seen = new Map();
    for (const finding of findings) {
        const key = `${finding.file}:${finding.line}:${finding.message.slice(0, 100)}`;
        if (!seen.has(key)) {
            seen.set(key, finding);
        }
        else {
            // Keep the finding with higher severity or more information
            const existing = seen.get(key);
            const severityOrder = {
                critical: 5,
                high: 4,
                medium: 3,
                low: 2,
                info: 1,
            };
            if (severityOrder[finding.severity] > severityOrder[existing.severity]) {
                seen.set(key, finding);
            }
            else if (severityOrder[finding.severity] === severityOrder[existing.severity] &&
                (finding.cweIds?.length || 0) > (existing.cweIds?.length || 0)) {
                seen.set(key, finding);
            }
        }
    }
    return Array.from(seen.values());
}
/**
 * Check which scanners are available
 */
export async function checkScannersAvailable() {
    const [npm, semgrep, gitleaks, bandit, gosec, trivy, eslint, brakeman, binaryTools, tfsec, checkov, spectral, cargoAudit, clippy, nuclei] = await Promise.all([
        import("./dependencies.js").then((m) => m.checkNpmAvailable()),
        import("./semgrep.js").then((m) => m.checkSemgrepAvailable()),
        import("./secrets.js").then((m) => m.checkGitleaksAvailable()),
        import("./bandit.js").then((m) => m.checkBanditAvailable()),
        import("./gosec.js").then((m) => m.checkGosecAvailable()),
        import("./trivy.js").then((m) => m.checkTrivyAvailable()),
        import("./eslint.js").then((m) => m.checkEslintAvailable()),
        import("./brakeman.js").then((m) => m.checkBrakemanAvailable()),
        import("./binary-analysis.js").then((m) => m.checkBinaryAnalysisAvailable()),
        import("./terraform.js").then((m) => m.checkTfsecAvailable()),
        import("./terraform.js").then((m) => m.checkCheckovAvailable()),
        import("./openapi.js").then((m) => m.checkSpectralAvailable()),
        import("./rust.js").then((m) => m.checkCargoAuditAvailable()),
        import("./rust.js").then((m) => m.checkClippyAvailable()),
        import("./dast.js").then((m) => m.checkNucleiAvailable()),
    ]);
    // Binary analysis is available if any of its tools are available
    const binaryAvailable = binaryTools.checksec || binaryTools.nm || binaryTools.file;
    return {
        "npm-audit": { available: npm.available, version: npm.version, error: npm.error },
        semgrep: { available: semgrep.available, version: semgrep.version, error: semgrep.error },
        gitleaks: { available: gitleaks.available, version: gitleaks.version, error: gitleaks.error },
        tsc: { available: true, version: "5.0+" }, // TypeScript is always available (dev dep)
        eslint: { available: eslint.available, version: eslint.version, error: eslint.error },
        bandit: { available: bandit.available, version: bandit.version, error: bandit.error },
        gosec: { available: gosec.available, version: gosec.version, error: gosec.error },
        brakeman: { available: brakeman.available, version: brakeman.version, error: brakeman.error },
        trivy: { available: trivy.available, version: trivy.version, error: trivy.error },
        "binary-analysis": { available: binaryAvailable, version: "1.0.0" },
        "memory-safety": { available: true, version: "1.0.0" }, // Pattern-based analysis always available
        "race-condition": { available: true, version: "1.0.0" }, // Pattern-based analysis always available
        healthcare: { available: true, version: "1.0.0" }, // Pattern-based PHI/consent analysis always available
        logic: { available: true, version: "1.0.0" }, // Logic flow analysis always available
        dast: { available: nuclei.available, version: nuclei.version, error: nuclei.error },
        zap: { available: false, version: undefined, error: "ZAP not installed" },
        nuclei: { available: nuclei.available, version: nuclei.version, error: nuclei.error },
        terraform: { available: tfsec.available || checkov.available, version: tfsec.version || checkov.version },
        tfsec: { available: tfsec.available, version: tfsec.version, error: tfsec.error },
        checkov: { available: checkov.available, version: checkov.version, error: checkov.error },
        openapi: { available: spectral.available, version: spectral.version, error: spectral.error },
        spectral: { available: spectral.available, version: spectral.version, error: spectral.error },
        rust: { available: cargoAudit.available || clippy.available, version: cargoAudit.version || clippy.version },
        "cargo-audit": { available: cargoAudit.available, version: cargoAudit.version, error: cargoAudit.error },
        clippy: { available: clippy.available, version: clippy.version, error: clippy.error },
        detection: { available: true, version: "1.0.0" }, // Vaspera detection engine always available
        plugin: { available: true, version: "1.0.0" }, // Plugin loader is always available
    };
}
/**
 * Get installation commands for missing scanners
 */
export function getScannerInstallCommands() {
    return {
        semgrep: {
            name: "Semgrep",
            description: "Fast, open-source static analysis for security and code quality",
            installCommands: {
                macos: "brew install semgrep",
                linux: "pip install semgrep",
                windows: "pip install semgrep",
                pip: "pip install semgrep",
            },
            documentation: "https://semgrep.dev/docs/getting-started/",
        },
        "npm-audit": {
            name: "npm audit",
            description: "Built-in npm security audit for dependency vulnerabilities",
            installCommands: {
                macos: "npm install -g npm@latest",
                linux: "npm install -g npm@latest",
                windows: "npm install -g npm@latest",
                npm: "npm install -g npm@latest",
            },
            documentation: "https://docs.npmjs.com/cli/audit",
        },
        gitleaks: {
            name: "Gitleaks",
            description: "Detect hardcoded secrets like passwords and API keys",
            installCommands: {
                macos: "brew install gitleaks",
                linux: "brew install gitleaks",
                windows: "choco install gitleaks",
            },
            documentation: "https://github.com/gitleaks/gitleaks",
        },
        tsc: {
            name: "TypeScript Compiler",
            description: "TypeScript type checking and analysis",
            installCommands: {
                macos: "npm install -D typescript",
                linux: "npm install -D typescript",
                windows: "npm install -D typescript",
                npm: "npm install -D typescript",
            },
            documentation: "https://www.typescriptlang.org/docs/",
        },
        eslint: {
            name: "ESLint",
            description: "Pluggable JavaScript/TypeScript linter for code quality",
            installCommands: {
                macos: "npm install -D eslint && npx eslint --init",
                linux: "npm install -D eslint && npx eslint --init",
                windows: "npm install -D eslint && npx eslint --init",
                npm: "npm install -D eslint",
            },
            documentation: "https://eslint.org/docs/latest/use/getting-started",
        },
        bandit: {
            name: "Bandit",
            description: "Python security linter for common vulnerabilities",
            installCommands: {
                macos: "pip install bandit",
                linux: "pip install bandit",
                windows: "pip install bandit",
                pip: "pip install bandit",
            },
            documentation: "https://bandit.readthedocs.io/",
        },
        gosec: {
            name: "Gosec",
            description: "Go security checker for common vulnerabilities",
            installCommands: {
                macos: "brew install gosec",
                linux: "go install github.com/securego/gosec/v2/cmd/gosec@latest",
                windows: "go install github.com/securego/gosec/v2/cmd/gosec@latest",
            },
            documentation: "https://github.com/securego/gosec",
        },
        brakeman: {
            name: "Brakeman",
            description: "Ruby on Rails security scanner",
            installCommands: {
                macos: "gem install brakeman",
                linux: "gem install brakeman",
                windows: "gem install brakeman",
            },
            documentation: "https://brakemanscanner.org/docs/",
        },
        trivy: {
            name: "Trivy",
            description: "Comprehensive vulnerability scanner for containers and IaC",
            installCommands: {
                macos: "brew install trivy",
                linux: "curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin",
                windows: "choco install trivy",
            },
            documentation: "https://aquasecurity.github.io/trivy/",
        },
        "binary-analysis": {
            name: "Binary Analysis",
            description: "Detect vulnerabilities in compiled code and native modules (checksec, nm)",
            installCommands: {
                macos: "brew install checksec",
                linux: "pip install checksec.py",
                windows: "pip install checksec.py",
                pip: "pip install checksec.py",
            },
            documentation: "https://github.com/slimm609/checksec.sh",
        },
        "memory-safety": {
            name: "Memory Safety",
            description: "Detect memory corruption vulnerabilities in C/C++/Rust code (cppcheck, cargo-geiger)",
            installCommands: {
                macos: "brew install cppcheck",
                linux: "apt-get install cppcheck",
                windows: "choco install cppcheck",
            },
            documentation: "https://cppcheck.sourceforge.io/",
        },
        "race-condition": {
            name: "Race Condition",
            description: "Detect concurrency bugs and TOCTOU vulnerabilities (go vet, pattern analysis)",
            installCommands: {
                macos: "Built-in pattern analysis + go vet (if Go installed)",
                linux: "Built-in pattern analysis + go vet (if Go installed)",
                windows: "Built-in pattern analysis + go vet (if Go installed)",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#race-condition",
        },
        healthcare: {
            name: "Healthcare Scanner",
            description: "HIPAA/42 CFR Part 2 compliance scanner for PHI exposure, consent validation, and audit gaps",
            installCommands: {
                macos: "Built-in pattern analysis (no installation required)",
                linux: "Built-in pattern analysis (no installation required)",
                windows: "Built-in pattern analysis (no installation required)",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#healthcare",
        },
        logic: {
            name: "Logic Flow Analyzer",
            description: "Endpoint and auth flow analysis for API security issues",
            installCommands: {
                macos: "Built-in pattern analysis (no installation required)",
                linux: "Built-in pattern analysis (no installation required)",
                windows: "Built-in pattern analysis (no installation required)",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#logic",
        },
        dast: {
            name: "DAST Scanner",
            description: "Dynamic Application Security Testing orchestrator",
            installCommands: {
                macos: "Install ZAP or Nuclei (see individual scanner docs)",
                linux: "Install ZAP or Nuclei (see individual scanner docs)",
                windows: "Install ZAP or Nuclei (see individual scanner docs)",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#dast",
        },
        zap: {
            name: "OWASP ZAP",
            description: "OWASP Zed Attack Proxy for dynamic security testing",
            installCommands: {
                macos: "brew install --cask owasp-zap",
                linux: "snap install zaproxy --classic",
                windows: "choco install zap",
            },
            documentation: "https://www.zaproxy.org/docs/",
        },
        nuclei: {
            name: "Nuclei",
            description: "Fast vulnerability scanner with template-based detection",
            installCommands: {
                macos: "brew install nuclei",
                linux: "go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest",
                windows: "go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest",
            },
            documentation: "https://nuclei.projectdiscovery.io/",
        },
        terraform: {
            name: "Terraform Scanner",
            description: "Combined IaC security scanner (tfsec + checkov)",
            installCommands: {
                macos: "brew install tfsec && pip install checkov",
                linux: "brew install tfsec && pip install checkov",
                windows: "choco install tfsec && pip install checkov",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#terraform",
        },
        tfsec: {
            name: "tfsec",
            description: "Terraform static analysis security scanner",
            installCommands: {
                macos: "brew install tfsec",
                linux: "brew install tfsec",
                windows: "choco install tfsec",
            },
            documentation: "https://aquasecurity.github.io/tfsec/",
        },
        checkov: {
            name: "Checkov",
            description: "IaC static analysis for Terraform, CloudFormation, Pulumi",
            installCommands: {
                macos: "pip install checkov",
                linux: "pip install checkov",
                windows: "pip install checkov",
                pip: "pip install checkov",
            },
            documentation: "https://www.checkov.io/",
        },
        openapi: {
            name: "OpenAPI Scanner",
            description: "OpenAPI/Swagger security validation using Spectral",
            installCommands: {
                macos: "npm install -g @stoplight/spectral-cli",
                linux: "npm install -g @stoplight/spectral-cli",
                windows: "npm install -g @stoplight/spectral-cli",
                npm: "npm install -g @stoplight/spectral-cli",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#openapi",
        },
        spectral: {
            name: "Spectral",
            description: "OpenAPI/AsyncAPI linting with custom rulesets",
            installCommands: {
                macos: "npm install -g @stoplight/spectral-cli",
                linux: "npm install -g @stoplight/spectral-cli",
                windows: "npm install -g @stoplight/spectral-cli",
                npm: "npm install -g @stoplight/spectral-cli",
            },
            documentation: "https://stoplight.io/open-source/spectral",
        },
        rust: {
            name: "Rust Scanner",
            description: "Combined Rust security scanner (cargo-audit + clippy)",
            installCommands: {
                macos: "cargo install cargo-audit && rustup component add clippy",
                linux: "cargo install cargo-audit && rustup component add clippy",
                windows: "cargo install cargo-audit && rustup component add clippy",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#rust",
        },
        "cargo-audit": {
            name: "cargo-audit",
            description: "Audit Rust dependencies for security vulnerabilities",
            installCommands: {
                macos: "cargo install cargo-audit",
                linux: "cargo install cargo-audit",
                windows: "cargo install cargo-audit",
            },
            documentation: "https://github.com/rustsec/rustsec",
        },
        clippy: {
            name: "Clippy",
            description: "Rust linter with security-relevant checks",
            installCommands: {
                macos: "rustup component add clippy",
                linux: "rustup component add clippy",
                windows: "rustup component add clippy",
            },
            documentation: "https://github.com/rust-lang/rust-clippy",
        },
        detection: {
            name: "Vaspera Detection Engine",
            description: "Proprietary taint tracking and pattern detection engine",
            installCommands: {
                macos: "Built-in - no installation required",
                linux: "Built-in - no installation required",
                windows: "Built-in - no installation required",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#detection",
        },
        plugin: {
            name: "Custom Plugin",
            description: "Custom scanner plugin loaded from .vaspera/plugins/",
            installCommands: {
                macos: "Create .vaspera/plugins/<name>.ts",
                linux: "Create .vaspera/plugins/<name>.ts",
                windows: "Create .vaspera/plugins/<name>.ts",
            },
            documentation: "https://github.com/vaspera/hardening-mcp#plugins",
        },
    };
}
/**
 * Convert aggregated scanner results to certification findings format
 */
export function scannerFindingsToCertificationFindings(scanResult) {
    const findings = [];
    // Group findings by scanner for ID generation
    const byScannerType = new Map();
    for (const result of scanResult.scanners) {
        for (const finding of result.findings) {
            if (!byScannerType.has(finding.scanner)) {
                byScannerType.set(finding.scanner, []);
            }
            byScannerType.get(finding.scanner).push(finding);
        }
    }
    // Generate IDs and convert
    for (const [scanner, scannerFindings] of byScannerType) {
        const prefixMap = {
            semgrep: "sem",
            "npm-audit": "dep",
            gitleaks: "sec",
            tsc: "tsc",
            eslint: "lint",
            bandit: "py",
            gosec: "go",
            brakeman: "rb",
            trivy: "trv",
            "binary-analysis": "bin",
            "memory-safety": "mem",
            "race-condition": "rac",
            healthcare: "hc",
            plugin: "plg",
            logic: "log",
            dast: "dst",
            zap: "zap",
            nuclei: "nuc",
            terraform: "tf",
            tfsec: "tfs",
            checkov: "chk",
            openapi: "api",
            spectral: "spc",
            rust: "rs",
            "cargo-audit": "cra",
            clippy: "clp",
            detection: "det",
        };
        const prefix = prefixMap[scanner];
        for (let i = 0; i < scannerFindings.length; i++) {
            const f = scannerFindings[i];
            findings.push({
                id: `${prefix}-${String(i + 1).padStart(3, "0")}`,
                severity: f.severity,
                category: getCategoryFromScanner(f),
                file: f.file,
                line: f.line,
                description: f.message,
                evidence: f.evidence || `Rule: ${f.ruleId}`,
                confidence: 100,
                scanner_source: f.scanner,
                scanner_rule_id: f.ruleId,
            });
        }
    }
    return findings;
}
/**
 * Determine category from scanner finding
 */
function getCategoryFromScanner(finding) {
    // Try to extract from rule ID or CWE
    const ruleId = finding.ruleId.toLowerCase();
    if (finding.cweIds?.some((cwe) => ["CWE-89", "CWE-564"].includes(cwe)) || ruleId.includes("sql")) {
        return "sql-injection";
    }
    if (finding.cweIds?.some((cwe) => cwe === "CWE-79") || ruleId.includes("xss")) {
        return "xss";
    }
    if (finding.scanner === "gitleaks" || ruleId.includes("secret") || ruleId.includes("key")) {
        return "secrets";
    }
    if (finding.scanner === "npm-audit") {
        return "dependency-vulnerability";
    }
    if (finding.scanner === "tsc") {
        if (ruleId.includes("any"))
            return "type-safety";
        if (ruleId.includes("return"))
            return "type-safety";
        return "typescript";
    }
    if (finding.scanner === "bandit") {
        return "python-security";
    }
    if (finding.scanner === "gosec") {
        return "go-security";
    }
    if (finding.scanner === "trivy") {
        if (ruleId.includes("misconfig"))
            return "misconfiguration";
        if (ruleId.includes("secret"))
            return "secrets";
        return "container-vulnerability";
    }
    if (finding.scanner === "brakeman") {
        return "ruby-security";
    }
    if (finding.scanner === "healthcare") {
        // Return the finding's category directly if set
        if (finding.category)
            return finding.category;
        // Otherwise infer from rule ID
        if (ruleId.includes("phi"))
            return "phi-exposure";
        if (ruleId.includes("sud"))
            return "sud-disclosure";
        if (ruleId.includes("consent"))
            return "consent-bypass";
        if (ruleId.includes("audit"))
            return "audit-gap";
        if (ruleId.includes("qsoa"))
            return "qsoa-violation";
        return "phi-exposure";
    }
    if (ruleId.includes("auth")) {
        return "authentication";
    }
    if (ruleId.includes("rls") || ruleId.includes("access")) {
        return "authorization";
    }
    // Default to scanner name
    return finding.scanner;
}
/**
 * Generate a summary report of scanner results
 */
export function generateScannerSummary(result) {
    const lines = [
        "# Deterministic Scanner Results",
        "",
        `**Scanned**: ${result.projectPath}`,
        `**Timestamp**: ${result.timestamp}`,
        `**Duration**: ${result.totalDuration}ms`,
        "",
        "## Summary",
        "",
        `| Severity | Count |`,
        `|----------|-------|`,
        `| Critical | ${result.bySeverity.critical} |`,
        `| High | ${result.bySeverity.high} |`,
        `| Medium | ${result.bySeverity.medium} |`,
        `| Low | ${result.bySeverity.low} |`,
        `| Info | ${result.bySeverity.info} |`,
        `| **Total** | **${result.totalFindings}** |`,
        "",
        "## By Scanner",
        "",
        `| Scanner | Findings | Status |`,
        `|---------|----------|--------|`,
    ];
    for (const scanner of result.scanners) {
        const status = scanner.success ? "✅" : `❌ ${scanner.error?.slice(0, 50)}`;
        lines.push(`| ${scanner.scanner} | ${scanner.findings.length} | ${status} |`);
    }
    if (result.totalFindings > 0) {
        lines.push("");
        lines.push("## Top Findings");
        lines.push("");
        // Show top 10 critical/high findings
        const topFindings = result.scanners
            .flatMap((s) => s.findings)
            .filter((f) => f.severity === "critical" || f.severity === "high")
            .slice(0, 10);
        for (const finding of topFindings) {
            lines.push(`- **[${finding.severity.toUpperCase()}]** ${finding.file}:${finding.line} - ${finding.message.slice(0, 80)}`);
        }
    }
    return lines.join("\n");
}
//# sourceMappingURL=index.js.map