// tools/security-check.ts — Security analysis tool handler for SPEC-029
// Analyzes specs against OWASP Top 10, scans code for insecure patterns, generates security score
import { specStore, knowledgeStore } from '../storage/index.js';
import { ti } from '../i18n/index.js';
import { detectSecurityProfiles, generateOwaspCriteria, scanCodeForViolations, calculateSecurityScore, detectSecurityDrift, buildSecurityReport, } from '../engine/security-analyzer.js';
import { readFile } from 'node:fs/promises';
export async function handleSecurityCheck(args) {
    const { specId, projectId, subcommand = 'analyze', codeFiles = [] } = args;
    // 1. Load spec
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec) {
        return {
            content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
            isError: true,
        };
    }
    // 2. Load project knowledge
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge) {
        return {
            content: [{ type: 'text', text: ti('project.notFound', {}) }],
            isError: true,
        };
    }
    // 3. Detect feature security profiles
    const profiles = detectSecurityProfiles(spec.title, '', spec.tags);
    try {
        switch (subcommand) {
            case 'analyze':
                return await handleAnalyze(specId, profiles, codeFiles);
            case 'score':
                return await handleScore(specId, profiles, codeFiles);
            case 'drift':
                return await handleDrift(specId, spec.specPath, profiles);
            /* v8 ignore next 2 */
            default:
                return await handleAnalyze(specId, profiles, codeFiles);
        }
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: ti('errors.internalError', { message }) }],
            isError: true,
        };
    }
}
async function handleAnalyze(specId, profiles, codeFiles) {
    const report = await buildSecurityReport(specId, '', profiles, codeFiles);
    const output = {
        specId,
        subcommand: 'analyze',
        profiles,
        owaspGaps: report.gaps.map((g) => ({
            category: g.owasp,
            description: g.description,
            rationale: g.rationale,
            status: g.verificationStatus,
        })),
        codeViolations: report.violations.map((v) => ({
            pattern: v.patternId,
            file: v.file,
            line: v.line,
            severity: v.severity,
            remediation: v.remediation,
        })),
        score: report.score,
        recommendations: report.recommendations,
    };
    return {
        content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
    };
}
async function handleScore(specId, profiles, codeFiles) {
    const gaps = await generateOwaspCriteria(profiles);
    const violations = codeFiles.length > 0 ? await scanCodeForViolations(codeFiles) : [];
    const score = calculateSecurityScore(gaps, violations);
    const output = {
        specId,
        subcommand: 'score',
        score: score.score,
        grade: score.grade,
        breakdown: score.breakdown,
        interpretation: interpretGrade(score.grade),
    };
    return {
        content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
    };
}
async function handleDrift(specId, specFilePath, profiles) {
    let specContent = '';
    if (specFilePath) {
        try {
            specContent = await readFile(specFilePath, 'utf-8');
        }
        catch {
            specContent = '';
        }
    }
    // Generate what security criteria SHOULD be present
    const expectedCriteria = await generateOwaspCriteria(profiles);
    const approvedDescriptions = expectedCriteria.map((c) => c.description);
    const removedCriteria = detectSecurityDrift(specContent, approvedDescriptions);
    const output = {
        specId,
        subcommand: 'drift',
        hasSecurityDrift: removedCriteria.length > 0,
        removedSecurityCriteria: removedCriteria,
        totalExpected: approvedDescriptions.length,
        totalFound: approvedDescriptions.length - removedCriteria.length,
        recommendation: removedCriteria.length > 0
            ? `Security drift detected: ${removedCriteria.length} criteria removed from approved spec. Restore or explicitly override.`
            : 'No security drift detected — spec aligns with expected security criteria.',
    };
    return {
        content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
    };
}
function interpretGrade(grade) {
    switch (grade) {
        case 'A':
            return 'Excellent security posture — minimal gaps and no critical violations';
        case 'B':
            return 'Good security posture — minor gaps; address before release';
        case 'C':
            return 'Acceptable but needs improvement — several security gaps present';
        case 'D':
            return 'Poor security posture — significant gaps and/or high-severity violations';
        case 'F':
            return 'Critical security failures — must be addressed immediately before any deployment';
        default:
            return 'Security grade unknown';
    }
}
//# sourceMappingURL=security-check.js.map