/**
 * PCIDSSAuditBot -- Automated PCI DSS v4.0.1 compliance auditing.
 *
 * Requirements 1-12: cardholder data environment controls, encryption,
 * network segmentation, access management, logging, and vulnerability
 * management. Does NOT call external APIs.
 *
 * Narrative writing is delegated to an injectable NarrativeWriter
 * interface so callers can swap in a real LLM implementation. The
 * default stub returns deterministic text suitable for tests.
 *
 * P2A-05
 *
 * @connexum/ai-governance
 */
import * as fs from 'fs';
import * as path from 'path';
import { computeAuditScore, } from './scheduler.js';
export class StubNarrativeWriter {
    write(controlId, context) {
        return `[PCI DSS] Control ${controlId} narrative: ${context.slice(0, 120)}`;
    }
}
// ---------------------------------------------------------------------------
// Main bot
// ---------------------------------------------------------------------------
export class PCIDSSAuditBot {
    logDir;
    governanceDir;
    narrativeWriter;
    constructor(config) {
        this.logDir = config.logDir;
        this.governanceDir = config.governanceDir;
        this.narrativeWriter = config.narrativeWriter ?? new StubNarrativeWriter();
    }
    runAudit() {
        const checks = [
            // Req 1-2: Network security controls
            this.checkNetworkSegmentation(),
            this.checkDefaultPasswords(),
            // Req 3-4: Protect account data
            this.checkPANDetector(),
            this.checkEncryption(),
            // Req 5-6: Vulnerability management
            this.checkVulnerabilityScans(),
            this.checkSecureDevelopment(),
            // Req 7-8: Access control
            this.checkAccessControl(),
            this.checkUserAuthentication(),
            // Req 9: Physical access
            this.checkPhysicalAccessPolicy(),
            // Req 10: Logging and monitoring
            this.checkAuditLogging(),
            this.checkLogIntegrity(),
            // Req 11: Testing security systems
            this.checkPenetrationTestEvidence(),
            this.checkASVScanEvidence(),
            // Req 12: Policies
            this.checkSecurityPolicy(),
            this.checkIncidentResponse(),
        ];
        const { score, passed, failed, warnings } = computeAuditScore(checks);
        return {
            auditId: '',
            packId: 'pcidss',
            timestamp: new Date().toISOString(),
            checks,
            score,
            passed,
            failed,
            warnings,
        };
    }
    // --- Req 1: Network segmentation ---
    checkNetworkSegmentation() {
        const segFile = path.join(this.governanceDir, 'network-segmentation.json');
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const exists = fs.existsSync(segFile) || fs.existsSync(permFile);
        return {
            id: 'pcidss-req1-segmentation',
            title: 'Req 1: Network security controls / segmentation',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Network segmentation or permissions configuration found'
                : 'No network-segmentation.json or permissions.json -- CDE isolation not documented',
            evidence: exists
                ? [segFile, permFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Req 2: Default passwords ---
    checkDefaultPasswords() {
        const authFile = path.join(this.governanceDir, 'agent-auth.json');
        const exists = fs.existsSync(authFile);
        return {
            id: 'pcidss-req2-credentials',
            title: 'Req 2: No vendor-supplied defaults',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Authentication configuration found; default credentials policy implied'
                : 'No agent-auth.json -- default credential management not configured',
            evidence: exists ? authFile : undefined,
        };
    }
    // --- Req 3: PAN detection ---
    checkPANDetector() {
        const classifierFile = path.join(this.governanceDir, 'data-classifier.json');
        const exists = fs.existsSync(classifierFile);
        if (!exists) {
            return {
                id: 'pcidss-req3-pan',
                title: 'Req 3: PAN / cardholder data detection',
                status: 'fail',
                detail: 'No data-classifier.json -- PAN detection not configured (Luhn / BIN classifier required)',
            };
        }
        try {
            const cfg = JSON.parse(fs.readFileSync(classifierFile, 'utf-8'));
            const hasPAN = cfg.patterns?.includes('PAN') || cfg.patterns?.includes('TRACK_DATA');
            return {
                id: 'pcidss-req3-pan',
                title: 'Req 3: PAN / cardholder data detection',
                status: hasPAN ? 'pass' : 'warning',
                detail: hasPAN
                    ? 'PAN / cardholder data classifier configured per Req 3.4'
                    : 'data-classifier.json exists but PAN pattern not listed',
                evidence: classifierFile,
            };
        }
        catch {
            return {
                id: 'pcidss-req3-pan',
                title: 'Req 3: PAN / cardholder data detection',
                status: 'fail',
                detail: 'data-classifier.json is invalid JSON',
                evidence: classifierFile,
            };
        }
    }
    // --- Req 4: Encryption ---
    checkEncryption() {
        const encFile = path.join(this.governanceDir, 'encryption.json');
        const exists = fs.existsSync(encFile);
        return {
            id: 'pcidss-req4-encryption',
            title: 'Req 4: Encryption in transit and at rest',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Encryption configuration found per Req 4'
                : 'No encryption.json -- cardholder data encryption not configured',
            evidence: exists ? encFile : undefined,
        };
    }
    // --- Req 5-6: Vulnerability management ---
    checkVulnerabilityScans() {
        const scanDir = this.logDir;
        const hasScanLogs = fs.existsSync(scanDir) &&
            fs.readdirSync(scanDir).some((f) => f.includes('scan') || f.includes('vuln'));
        const anomalyFile = path.join(this.governanceDir, 'anomaly-detection.json');
        const exists = hasScanLogs || fs.existsSync(anomalyFile);
        return {
            id: 'pcidss-req5-vuln-scans',
            title: 'Req 5-6: Vulnerability scanning evidence',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Vulnerability scan or anomaly detection evidence found'
                : 'No scan logs or anomaly-detection.json -- quarterly ASV scans not evidenced',
            evidence: exists
                ? [anomalyFile].filter((f) => fs.existsSync(f)).join(', ') || scanDir
                : undefined,
        };
    }
    checkSecureDevelopment() {
        const sdlcFile = path.join(this.governanceDir, 'sdlc-policy.json');
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(sdlcFile) || fs.existsSync(govFile);
        return {
            id: 'pcidss-req6-sdlc',
            title: 'Req 6: Secure development practices',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Governance / SDLC policy found per Req 6'
                : 'No sdlc-policy.json or governance.json -- secure coding policy not documented',
            evidence: exists
                ? [sdlcFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Req 7-8: Access control ---
    checkAccessControl() {
        const rolesFile = path.join(this.governanceDir, 'roles.json');
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const exists = fs.existsSync(rolesFile) || fs.existsSync(permFile);
        return {
            id: 'pcidss-req7-access',
            title: 'Req 7: Restrict access by business need',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Role / permission definitions enforce least-privilege per Req 7'
                : 'No roles.json or permissions.json -- need-to-know access not defined',
            evidence: exists
                ? [rolesFile, permFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkUserAuthentication() {
        const authFile = path.join(this.governanceDir, 'agent-auth.json');
        const exists = fs.existsSync(authFile);
        return {
            id: 'pcidss-req8-auth',
            title: 'Req 8: User identification and authentication (MFA)',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Agent authentication configuration found per Req 8'
                : 'No agent-auth.json -- MFA / unique ID enforcement not configured',
            evidence: exists ? authFile : undefined,
        };
    }
    // --- Req 9: Physical ---
    checkPhysicalAccessPolicy() {
        const physFile = path.join(this.governanceDir, 'physical-access.json');
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(physFile) || fs.existsSync(govFile);
        return {
            id: 'pcidss-req9-physical',
            title: 'Req 9: Physical access restrictions',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Physical access policy or governance file found'
                : 'No physical-access.json -- physical CDE access controls not documented',
            evidence: exists
                ? [physFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Req 10: Logging ---
    checkAuditLogging() {
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        return {
            id: 'pcidss-req10-logging',
            title: 'Req 10: Log and monitor all CDE access',
            status: hasLogs ? 'pass' : 'fail',
            detail: hasLogs
                ? 'JSONL audit logs present per Req 10'
                : 'No JSONL audit logs -- CDE access logging not operational',
            evidence: hasLogs ? this.logDir : undefined,
        };
    }
    checkLogIntegrity() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const exists = fs.existsSync(hashFile);
        return {
            id: 'pcidss-req10-log-integrity',
            title: 'Req 10: Audit log integrity protection',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Hash manifest provides log integrity per Req 10.5'
                : 'No hash-manifest.json -- log tampering prevention not configured',
            evidence: exists ? hashFile : undefined,
        };
    }
    // --- Req 11: Testing ---
    checkPenetrationTestEvidence() {
        const penTestFile = path.join(this.governanceDir, 'pentest-results.json');
        const hasLog = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.includes('pentest') || f.includes('pen-test'));
        const exists = fs.existsSync(penTestFile) || hasLog;
        return {
            id: 'pcidss-req11-pentest',
            title: 'Req 11: Penetration testing evidence',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Penetration test evidence found per Req 11.3'
                : 'No pentest evidence -- annual penetration test not documented',
            evidence: exists ? (fs.existsSync(penTestFile) ? penTestFile : this.logDir) : undefined,
        };
    }
    checkASVScanEvidence() {
        const asvFile = path.join(this.governanceDir, 'asv-scan.json');
        const exists = fs.existsSync(asvFile);
        return {
            id: 'pcidss-req11-asv',
            title: 'Req 11: ASV scan results',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'ASV scan results file found per Req 11.2'
                : 'No asv-scan.json -- quarterly ASV scan results not recorded',
            evidence: exists ? asvFile : undefined,
        };
    }
    // --- Req 12: Policy ---
    checkSecurityPolicy() {
        const policyFile = path.join(this.governanceDir, 'security-policy.json');
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(policyFile) || fs.existsSync(govFile);
        return {
            id: 'pcidss-req12-policy',
            title: 'Req 12: Information security policy',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Security policy or governance configuration found per Req 12'
                : 'No security-policy.json or governance.json -- information security policy not documented',
            evidence: exists
                ? [policyFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkIncidentResponse() {
        const irFile = path.join(this.governanceDir, 'incident-response.json');
        const exists = fs.existsSync(irFile);
        return {
            id: 'pcidss-req12-ir',
            title: 'Req 12: Incident response plan',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Incident response plan found per Req 12.10'
                : 'No incident-response.json -- incident response plan not configured',
            evidence: exists ? irFile : undefined,
        };
    }
    // ---------------------------------------------------------------------------
    // Gap analysis
    // ---------------------------------------------------------------------------
    analyzeGaps(result) {
        return result.checks
            .filter((c) => c.status === 'fail' || c.status === 'warning')
            .map((c) => ({
            requirement: c.id,
            title: c.title,
            detail: c.detail,
        }));
    }
    // ---------------------------------------------------------------------------
    // Report generation
    // ---------------------------------------------------------------------------
    generateReport(result, outputDir) {
        if (!fs.existsSync(outputDir))
            fs.mkdirSync(outputDir, { recursive: true });
        const gaps = this.analyzeGaps(result);
        const narrative = this.narrativeWriter.write('PCI-DSS-4.0.1', `Score: ${result.score}/100. ${result.passed} controls passed, ${result.failed} failed, ${result.warnings} warnings.`);
        const report = {
            framework: 'PCI DSS v4.0.1',
            generatedAt: new Date().toISOString(),
            auditId: result.auditId,
            score: result.score,
            passed: result.passed,
            failed: result.failed,
            warnings: result.warnings,
            narrative,
            gaps,
            checks: result.checks,
            saqIndicator: result.score >= 80 ? 'SAQ-A eligible (review scope)' : 'Full ROC may be required',
        };
        const filename = `pcidss-report-${Date.now()}.json`;
        const filePath = path.join(outputDir, filename);
        fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
        return filePath;
    }
}
//# sourceMappingURL=pcidss.js.map