"use strict";
/**
 * Layer 1: Surface Scan
 * Fast, deterministic scanning using entropy, patterns, config auditing,
 * file flags, comment analysis, URL detection, and weak crypto detection
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectAgentSkillInjection = exports.detectMCPConfigIssues = exports.detectWeakCrypto = exports.detectSensitiveURLs = exports.detectAICommentPatterns = exports.detectDangerousFiles = exports.auditConfiguration = exports.detectKnownPatterns = exports.detectHighEntropyStrings = void 0;
exports.runLayer1Scan = runLayer1Scan;
const entropy_1 = require("./entropy");
const patterns_1 = require("./patterns");
const config_audit_1 = require("./config-audit");
const file_flags_1 = require("../config/file-flags");
const comments_1 = require("../config/comments");
const urls_1 = require("../config/urls");
const weak_crypto_1 = require("./weak-crypto");
const config_mcp_audit_1 = require("./config-mcp-audit");
const agent_skill_injection_1 = require("../config/agent-skill-injection");
// Tier system removed in Phase 2B — confidence scoring handles routing
const path_exclusions_1 = require("../../parse/path-exclusions");
const parsed_file_1 = require("../../shared/parsed-file");
const parsed_file_2 = require("../../shared/parsed-file");
// Process a single file through all Layer 1 detectors
function processFileLayer1(file) {
    const stats = {
        known_secrets: 0,
        weak_crypto: 0,
        sensitive_urls: 0,
        entropy: 0,
        config_audit: 0,
        file_flags: 0,
        ai_comments: 0,
        mcp_config: 0,
        agent_skill: 0,
    };
    // Create ParsedFile once for all detectors to share
    const parsed = parsed_file_2.ParsedFile.from(file);
    const entropyFindings = (0, entropy_1.detectHighEntropyStrings)(file.content, file.path, { parsed });
    const patternFindings = (0, patterns_1.detectKnownPatterns)(file.content, file.path, { parsed });
    const configFindings = (0, config_audit_1.auditConfiguration)(file.content, file.path, { parsed });
    const fileFlags = (0, file_flags_1.detectDangerousFiles)(file.content, file.path, { parsed });
    const commentFindings = (0, comments_1.detectAICommentPatterns)(file.content, file.path, { parsed });
    const urlFindings = (0, urls_1.detectSensitiveURLs)(file.content, file.path, { parsed });
    const cryptoFindings = (0, weak_crypto_1.detectWeakCrypto)(file.content, file.path, { parsed });
    const mcpConfigFindings = (0, config_mcp_audit_1.detectMCPConfigIssues)(file.content, file.path, { parsed });
    const agentSkillFindings = (0, agent_skill_injection_1.detectAgentSkillInjection)(file.content, file.path, { parsed });
    stats.entropy = entropyFindings.length;
    stats.known_secrets = patternFindings.length;
    stats.config_audit = configFindings.length;
    stats.file_flags = fileFlags.length;
    stats.ai_comments = commentFindings.length;
    stats.sensitive_urls = urlFindings.length;
    stats.weak_crypto = cryptoFindings.length;
    stats.mcp_config = mcpConfigFindings.length;
    stats.agent_skill = agentSkillFindings.length;
    return {
        findings: [
            ...entropyFindings,
            ...patternFindings,
            ...configFindings,
            ...fileFlags,
            ...commentFindings,
            ...urlFindings,
            ...cryptoFindings,
            ...mcpConfigFindings,
            ...agentSkillFindings,
        ],
        stats,
    };
}
// Parallel batch size for Layer 1 processing (larger batches for performance)
const LAYER1_PARALLEL_BATCH_SIZE = 50;
// Progress update interval (report every N files for better UX)
const PROGRESS_UPDATE_INTERVAL = 10;
async function runLayer1Scan(files, onProgress, cancellationToken) {
    const startTime = Date.now();
    const vulnerabilities = [];
    // Track raw counts per detector (before dedupe)
    const rawStats = {
        known_secrets: 0,
        weak_crypto: 0,
        sensitive_urls: 0,
        entropy: 0,
        config_audit: 0,
        file_flags: 0,
        ai_comments: 0,
        mcp_config: 0,
        agent_skill: 0,
    };
    // Track progress for frequent updates
    let filesProcessed = 0;
    let lastProgressUpdate = 0;
    // Process files in parallel batches for better performance on large codebases
    for (let i = 0; i < files.length; i += LAYER1_PARALLEL_BATCH_SIZE) {
        // Check for cancellation before processing batch
        if (cancellationToken?.cancelled)
            break;
        const batch = files.slice(i, i + LAYER1_PARALLEL_BATCH_SIZE);
        const results = await Promise.all(batch.map(file => Promise.resolve(processFileLayer1(file))));
        for (const result of results) {
            vulnerabilities.push(...result.findings);
            // Accumulate stats
            for (const [key, value] of Object.entries(result.stats)) {
                rawStats[key] += value;
            }
        }
        filesProcessed = Math.min(i + LAYER1_PARALLEL_BATCH_SIZE, files.length);
        // Report progress every PROGRESS_UPDATE_INTERVAL files for better UX
        if (onProgress && (filesProcessed - lastProgressUpdate >= PROGRESS_UPDATE_INTERVAL || filesProcessed === files.length)) {
            onProgress({
                status: 'layer1',
                message: 'Running surface scan (patterns, entropy, config)...',
                filesProcessed,
                totalFiles: files.length,
                vulnerabilitiesFound: vulnerabilities.length,
            });
            lastProgressUpdate = filesProcessed;
        }
    }
    // Deduplicate findings (same line might be caught by multiple detectors)
    const dedupedVulnerabilities = deduplicateFindings(vulnerabilities);
    // Apply path exclusions to filter out findings in test/seed/example files
    const { kept: uniqueVulnerabilities, suppressed } = (0, path_exclusions_1.filterFindingsByPath)(dedupedVulnerabilities);
    // Track suppressed findings (debug info available in stats)
    // Compute deduped counts per category
    const dedupedStats = {};
    for (const vuln of uniqueVulnerabilities) {
        const cat = vuln.category;
        dedupedStats[cat] = (dedupedStats[cat] || 0) + 1;
    }
    return {
        vulnerabilities: uniqueVulnerabilities,
        filesScanned: files.length,
        duration: Date.now() - startTime,
        stats: {
            raw: rawStats,
            deduped: dedupedStats,
            suppressedByPath: suppressed.length,
        },
    };
}
// Remove duplicate findings on the same line
function deduplicateFindings(vulnerabilities) {
    const seen = new Map();
    for (const vuln of vulnerabilities) {
        const key = `${vuln.filePath}:${vuln.lineNumber}:${vuln.category}`;
        const existing = seen.get(key);
        // Keep the higher severity finding
        if (!existing || (0, parsed_file_1.severityRank)(vuln.severity) > (0, parsed_file_1.severityRank)(existing.severity)) {
            seen.set(key, vuln);
        }
    }
    return Array.from(seen.values());
}
// severityRank imported from utils/parsed-file
var entropy_2 = require("./entropy");
Object.defineProperty(exports, "detectHighEntropyStrings", { enumerable: true, get: function () { return entropy_2.detectHighEntropyStrings; } });
var patterns_2 = require("./patterns");
Object.defineProperty(exports, "detectKnownPatterns", { enumerable: true, get: function () { return patterns_2.detectKnownPatterns; } });
var config_audit_2 = require("./config-audit");
Object.defineProperty(exports, "auditConfiguration", { enumerable: true, get: function () { return config_audit_2.auditConfiguration; } });
var file_flags_2 = require("../config/file-flags");
Object.defineProperty(exports, "detectDangerousFiles", { enumerable: true, get: function () { return file_flags_2.detectDangerousFiles; } });
var comments_2 = require("../config/comments");
Object.defineProperty(exports, "detectAICommentPatterns", { enumerable: true, get: function () { return comments_2.detectAICommentPatterns; } });
var urls_2 = require("../config/urls");
Object.defineProperty(exports, "detectSensitiveURLs", { enumerable: true, get: function () { return urls_2.detectSensitiveURLs; } });
var weak_crypto_2 = require("./weak-crypto");
Object.defineProperty(exports, "detectWeakCrypto", { enumerable: true, get: function () { return weak_crypto_2.detectWeakCrypto; } });
var config_mcp_audit_2 = require("./config-mcp-audit");
Object.defineProperty(exports, "detectMCPConfigIssues", { enumerable: true, get: function () { return config_mcp_audit_2.detectMCPConfigIssues; } });
var agent_skill_injection_2 = require("../config/agent-skill-injection");
Object.defineProperty(exports, "detectAgentSkillInjection", { enumerable: true, get: function () { return agent_skill_injection_2.detectAgentSkillInjection; } });
//# sourceMappingURL=index.js.map