"use strict";
/**
 * Smart Auto-Dismiss Rules
 *
 * Instant filtering rules that don't require AI validation.
 * These rules catch obvious false positives before sending to AI.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyAutoDismissRules = applyAutoDismissRules;
const context_helpers_1 = require("../../utils/context-helpers");
const tiers_1 = require("../../tiers");
// ============================================================================
// Auto-Dismiss Rules
// ============================================================================
const AUTO_DISMISS_RULES = [
    // Test files - often contain intentional "vulnerable" patterns for testing
    {
        name: 'test_file',
        check: (finding) => (0, context_helpers_1.isTestOrMockFile)(finding.filePath),
        reason: 'Finding in test/mock file',
    },
    // Example/demo code - not production code
    {
        name: 'example_file',
        check: (finding) => (0, context_helpers_1.isExampleFile)(finding.filePath),
        reason: 'Finding in example/demo file',
    },
    // Documentation files
    {
        name: 'documentation_file',
        check: (finding) => /\.(md|mdx|txt|rst)$/i.test(finding.filePath),
        reason: 'Finding in documentation file',
    },
    // Scanner/security tool code itself
    {
        name: 'scanner_code',
        check: (finding) => (0, context_helpers_1.isScannerOrFixtureFile)(finding.filePath),
        reason: 'Finding in scanner/fixture code',
    },
    // Environment variable references (not hardcoded secrets)
    {
        name: 'env_var_reference',
        check: (finding) => {
            if (finding.category !== 'hardcoded_secret' && finding.category !== 'high_entropy_string') {
                return false;
            }
            return (0, context_helpers_1.isEnvVarReference)(finding.lineContent);
        },
        reason: 'Uses environment variable (not hardcoded)',
    },
    // Public health check endpoints don't need auth
    {
        name: 'health_check_endpoint',
        check: (finding) => {
            if (finding.category !== 'missing_auth')
                return false;
            return (0, context_helpers_1.isPublicEndpoint)(finding.lineContent, finding.filePath);
        },
        reason: 'Public health check endpoint (auth not required)',
    },
    // CSS/Tailwind classes flagged as high entropy
    {
        name: 'css_classes',
        check: (finding) => {
            if (finding.category !== 'high_entropy_string')
                return false;
            const cssIndicators = ['flex', 'grid', 'text-', 'bg-', 'px-', 'py-', 'rounded', 'shadow', 'hover:', 'dark:'];
            const lowerLine = finding.lineContent.toLowerCase();
            const matchCount = cssIndicators.filter(ind => lowerLine.includes(ind)).length;
            return matchCount >= 2;
        },
        reason: 'CSS/Tailwind classes (not a secret)',
    },
    // Comment lines shouldn't be flagged for most categories
    {
        name: 'comment_line',
        check: (finding) => {
            // Some categories are valid in comments (e.g., TODO security)
            if (finding.category === 'ai_pattern')
                return false;
            return (0, context_helpers_1.isComment)(finding.lineContent);
        },
        reason: 'Code comment (not executable)',
    },
    // Info severity already - no need to validate
    // BUT: Only auto-dismiss info-severity for Tier A (core) findings
    // Tier B (ai_assisted) findings MUST go through AI validation even at info severity
    // because detectors may have pre-downgraded them based on partial context
    {
        name: 'info_severity_core_only',
        check: (finding) => {
            if (finding.severity !== 'info')
                return false;
            // Only auto-dismiss info-severity for Tier A (core) findings
            // Tier B should always go through AI for proper validation
            const tier = (0, tiers_1.getTierForCategory)(finding.category, finding.layer);
            return tier === 'core';
        },
        reason: 'Already info severity for core detector (low priority)',
    },
    // Generic success/error messages in ai_pattern
    {
        name: 'generic_message',
        check: (finding) => {
            if (finding.category !== 'ai_pattern')
                return false;
            const genericPatterns = [
                /['"`](success|done|ok|completed|finished|saved|updated|deleted|created)['"`]/i,
                /['"`]something went wrong['"`]/i,
                /['"`]an error occurred['"`]/i,
                /console\.(log|info|debug)\s*\(\s*['"`][^'"]+['"`]\s*\)/i,
            ];
            return genericPatterns.some(p => p.test(finding.lineContent));
        },
        reason: 'Generic UI message (not security-relevant)',
    },
    // Type definitions with 'any' - often necessary for third-party libs
    {
        name: 'type_definition_any',
        check: (finding) => {
            if (finding.category !== 'ai_pattern')
                return false;
            if (!finding.title.toLowerCase().includes('any'))
                return false;
            // Check if it's in a .d.ts file or type definition context
            if (finding.filePath.includes('.d.ts'))
                return true;
            const typeDefPatterns = [/^type\s+\w+\s*=/, /^interface\s+\w+/, /declare\s+(const|let|var|function|class)/];
            return typeDefPatterns.some(p => p.test(finding.lineContent.trim()));
        },
        reason: 'Type definition (not runtime code)',
    },
    // setTimeout/setInterval magic numbers - code style, not security
    {
        name: 'timeout_magic_number',
        check: (finding) => {
            if (finding.category !== 'ai_pattern')
                return false;
            return /set(Timeout|Interval)\s*\([^,]+,\s*\d+\s*\)/.test(finding.lineContent);
        },
        reason: 'Timeout value (code style, not security)',
    },
    // Low-value AI pattern findings - code quality, not security
    {
        name: 'low_severity_ai_pattern',
        check: (finding) => {
            if (finding.category !== 'ai_pattern')
                return false;
            return finding.severity === 'info' || finding.severity === 'low';
        },
        reason: 'Low-severity AI pattern (code quality, not security vulnerability)',
    },
];
// ============================================================================
// Apply Auto-Dismiss Rules
// ============================================================================
/**
 * Rules that should NOT be applied to direct-surface findings.
 * These rules are designed to reduce AI validation costs, not to suppress findings entirely.
 */
const VALIDATION_ONLY_RULES = new Set([
    'info_severity_core_only', // Info findings should surface, just not go through expensive AI validation
    'low_severity_ai_pattern', // Low/info AI patterns are code quality, not security — skip AI validation
]);
/**
 * Apply smart auto-dismiss rules to filter obvious false positives
 * Returns findings that should be sent to AI validation
 *
 * @param findings - Array of vulnerabilities to filter
 * @param mode - 'validation' applies all rules (for AI validation candidates),
 *               'surface' excludes cost-saving rules (for direct-surface findings)
 */
function applyAutoDismissRules(findings, mode = 'validation') {
    const toValidate = [];
    const dismissed = [];
    // Filter rules based on mode
    const applicableRules = mode === 'surface'
        ? AUTO_DISMISS_RULES.filter(rule => !VALIDATION_ONLY_RULES.has(rule.name))
        : AUTO_DISMISS_RULES;
    for (const finding of findings) {
        let wasDismissed = false;
        for (const rule of applicableRules) {
            if (rule.check(finding)) {
                dismissed.push({
                    finding,
                    rule: rule.name,
                    reason: rule.reason,
                });
                wasDismissed = true;
                break;
            }
        }
        if (!wasDismissed) {
            toValidate.push(finding);
        }
    }
    return { toValidate, dismissed };
}
//# sourceMappingURL=auto-dismiss.js.map