"use strict";
/**
 * ISO27001AuditBot -- Automated ISO/IEC 27001:2022 ISMS auditing.
 *
 * Covers Annex A controls A.5 (Organizational) through A.8 (Technological),
 * ISMS clause compliance (Clauses 4-10), risk treatment tracking, internal
 * audit evidence, management review summary, and Statement of Applicability
 * generation. Does NOT call external APIs.
 *
 * Narrative writing is delegated to an injectable NarrativeWriter.
 *
 * P2A-07
 *
 * @connexum/ai-governance
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ISO27001AuditBot = exports.StubNarrativeWriter = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const scheduler_1 = require("./scheduler");
class StubNarrativeWriter {
    write(controlId, context) {
        return `[ISO 27001] Control ${controlId}: ${context.slice(0, 120)}`;
    }
}
exports.StubNarrativeWriter = StubNarrativeWriter;
class ISO27001AuditBot {
    logDir;
    governanceDir;
    narrativeWriter;
    constructor(config) {
        this.logDir = config.logDir;
        this.governanceDir = config.governanceDir;
        this.narrativeWriter = config.narrativeWriter ?? new StubNarrativeWriter();
    }
    runAudit() {
        const checks = [
            // Clause 4-6: Context and planning
            this.checkISMSContext(),
            this.checkRiskTreatmentPlan(),
            this.checkSecurityObjectives(),
            // Clause 7: Support
            this.checkDocumentedInformation(),
            // Clause 9: Performance evaluation
            this.checkInternalAudit(),
            this.checkManagementReview(),
            // Annex A.5: Organizational controls
            this.checkA5InfoSecPolicies(),
            this.checkA5ThreatIntelligence(),
            this.checkA5SupplierRelationships(),
            // Annex A.6: People controls
            this.checkA6AccessControl(),
            this.checkA6RemoteWorkPolicy(),
            // Annex A.7: Physical controls
            this.checkA7PhysicalSecurity(),
            // Annex A.8: Technological controls
            this.checkA8UserEndpointDevices(),
            this.checkA8LoggingMonitoring(),
            this.checkA8DataMasking(),
            this.checkA8DataLeakagePrevention(),
            this.checkA8TamperDetection(),
            this.checkA8EncryptionKeys(),
        ];
        const { score, passed, failed, warnings } = (0, scheduler_1.computeAuditScore)(checks);
        return {
            auditId: '',
            packId: 'iso27001',
            timestamp: new Date().toISOString(),
            checks,
            score,
            passed,
            failed,
            warnings,
        };
    }
    // --- Clause 4-6: Context and planning ---
    checkISMSContext() {
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(govFile);
        return {
            id: 'iso27001-clause4-context',
            title: 'Clause 4: ISMS context (governance.json)',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'ISMS governance configuration found per Clause 4'
                : 'No governance.json -- ISMS scope and context not documented',
            evidence: exists ? govFile : undefined,
        };
    }
    checkRiskTreatmentPlan() {
        const riskFile = path.join(this.governanceDir, 'risk-assessment.json');
        const anomalyFile = path.join(this.governanceDir, 'anomaly-detection.json');
        const exists = fs.existsSync(riskFile) || fs.existsSync(anomalyFile);
        return {
            id: 'iso27001-clause6-risk',
            title: 'Clause 6: Risk treatment plan',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Risk assessment or anomaly detection evidence found per Clause 6'
                : 'No risk-assessment.json or anomaly-detection.json -- risk treatment plan not evidenced',
            evidence: exists
                ? [riskFile, anomalyFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkSecurityObjectives() {
        const objectivesFile = path.join(this.governanceDir, 'security-objectives.json');
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(objectivesFile) || fs.existsSync(govFile);
        return {
            id: 'iso27001-clause6-objectives',
            title: 'Clause 6: Information security objectives',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Security objectives documented per Clause 6.2'
                : 'No security-objectives.json -- measurable security objectives not evidenced',
            evidence: exists
                ? [objectivesFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Clause 7: Support ---
    checkDocumentedInformation() {
        const hasConfigs = fs.existsSync(this.governanceDir) &&
            fs.readdirSync(this.governanceDir).filter((f) => f.endsWith('.json') || f.endsWith('.md'))
                .length >= 3;
        return {
            id: 'iso27001-clause7-docs',
            title: 'Clause 7: Documented information (3+ governance files)',
            status: hasConfigs ? 'pass' : 'warning',
            detail: hasConfigs
                ? 'Multiple governance documents found per Clause 7.5'
                : 'Fewer than 3 governance files -- documented information requirement may not be met',
            evidence: hasConfigs ? this.governanceDir : undefined,
        };
    }
    // --- Clause 9: Performance evaluation ---
    checkInternalAudit() {
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        return {
            id: 'iso27001-clause9-internal-audit',
            title: 'Clause 9: Internal audit evidence',
            status: hasLogs ? 'pass' : 'fail',
            detail: hasLogs
                ? 'Audit log evidence found per Clause 9.2'
                : 'No JSONL audit logs -- internal audit evidence not present',
            evidence: hasLogs ? this.logDir : undefined,
        };
    }
    checkManagementReview() {
        const reviewFile = path.join(this.governanceDir, 'management-review.json');
        const exists = fs.existsSync(reviewFile);
        return {
            id: 'iso27001-clause9-mgmt-review',
            title: 'Clause 9: Management review record',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Management review record found per Clause 9.3'
                : 'No management-review.json -- periodic management review not evidenced',
            evidence: exists ? reviewFile : undefined,
        };
    }
    // --- Annex A.5: Organizational controls ---
    checkA5InfoSecPolicies() {
        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: 'iso27001-a5-policies',
            title: 'A.5.1: Information security policies',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Security policy configuration found per A.5.1'
                : 'No security-policy.json or governance.json -- information security policy not documented',
            evidence: exists
                ? [policyFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA5ThreatIntelligence() {
        const threatFile = path.join(this.governanceDir, 'threat-intelligence.json');
        const anomalyFile = path.join(this.governanceDir, 'anomaly-detection.json');
        const exists = fs.existsSync(threatFile) || fs.existsSync(anomalyFile);
        return {
            id: 'iso27001-a5-threat-intel',
            title: 'A.5.7: Threat intelligence (2022 new control)',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Threat intelligence or anomaly detection configuration found per A.5.7'
                : 'No threat-intelligence.json or anomaly-detection.json -- A.5.7 new control gap',
            evidence: exists
                ? [threatFile, anomalyFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA5SupplierRelationships() {
        const vendorFile = path.join(this.governanceDir, 'vendor-registry.json');
        const exists = fs.existsSync(vendorFile);
        return {
            id: 'iso27001-a5-suppliers',
            title: 'A.5.19: Information security in supplier relationships',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Vendor registry found per A.5.19'
                : 'No vendor-registry.json -- third-party risk management not evidenced',
            evidence: exists ? vendorFile : undefined,
        };
    }
    // --- Annex A.6: People controls ---
    checkA6AccessControl() {
        const rolesFile = path.join(this.governanceDir, 'roles.json');
        const authFile = path.join(this.governanceDir, 'agent-auth.json');
        const exists = fs.existsSync(rolesFile) || fs.existsSync(authFile);
        return {
            id: 'iso27001-a6-access',
            title: 'A.6 / A.8.2: Access control',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Roles or authentication configuration found per A.6/A.8.2'
                : 'No roles.json or agent-auth.json -- access control not configured',
            evidence: exists
                ? [rolesFile, authFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA6RemoteWorkPolicy() {
        const remoteFile = path.join(this.governanceDir, 'remote-work-policy.json');
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const exists = fs.existsSync(remoteFile) || fs.existsSync(permFile);
        return {
            id: 'iso27001-a6-remote',
            title: 'A.6.7: Remote working policy',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Remote work or permission policy found per A.6.7'
                : 'No remote-work-policy.json -- remote working controls not documented',
            evidence: exists
                ? [remoteFile, permFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Annex A.7: Physical controls ---
    checkA7PhysicalSecurity() {
        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: 'iso27001-a7-physical',
            title: 'A.7: Physical security controls',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Physical security policy or governance found per A.7'
                : 'No physical-access.json -- physical security evidence not present',
            evidence: exists
                ? [physFile, govFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Annex A.8: Technological controls ---
    checkA8UserEndpointDevices() {
        const capFile = path.join(this.governanceDir, 'capability-bundles.json');
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const exists = fs.existsSync(capFile) || fs.existsSync(permFile);
        return {
            id: 'iso27001-a8-endpoints',
            title: 'A.8.1: User endpoint devices',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Capability bundles or permissions control endpoint scope per A.8.1'
                : 'No capability-bundles.json or permissions.json -- endpoint control not evidenced',
            evidence: exists
                ? [capFile, permFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA8LoggingMonitoring() {
        const monitorFile = path.join(this.governanceDir, 'monitoring.json');
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        const exists = fs.existsSync(monitorFile) || hasLogs;
        return {
            id: 'iso27001-a8-logging',
            title: 'A.8.15-16: Logging and monitoring activities',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Monitoring configuration and/or audit logs found per A.8.15-16'
                : 'No monitoring.json or JSONL audit logs -- logging and monitoring not configured',
            evidence: exists
                ? (fs.existsSync(monitorFile) ? monitorFile : this.logDir)
                : undefined,
        };
    }
    checkA8DataMasking() {
        const maskFile = path.join(this.governanceDir, 'data-masking.json');
        const classifierFile = path.join(this.governanceDir, 'data-classifier.json');
        const exists = fs.existsSync(maskFile) || fs.existsSync(classifierFile);
        return {
            id: 'iso27001-a8-masking',
            title: 'A.8.11: Data masking (2022 new control)',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Data masking or classifier configuration found per A.8.11'
                : 'No data-masking.json or data-classifier.json -- A.8.11 new control gap',
            evidence: exists
                ? [maskFile, classifierFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA8DataLeakagePrevention() {
        const dlpFile = path.join(this.governanceDir, 'data-leakage-prevention.json');
        const capFile = path.join(this.governanceDir, 'capability-bundles.json');
        const exists = fs.existsSync(dlpFile) || fs.existsSync(capFile);
        return {
            id: 'iso27001-a8-dlp',
            title: 'A.8.12: Data leakage prevention (2022 new control)',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'DLP or capability bundle configuration found per A.8.12'
                : 'No data-leakage-prevention.json -- A.8.12 new control gap',
            evidence: exists
                ? [dlpFile, capFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkA8TamperDetection() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const exists = fs.existsSync(hashFile);
        return {
            id: 'iso27001-a8-tamper',
            title: 'A.8.3 / A.8.16: Tamper detection and integrity monitoring',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Hash manifest enables integrity monitoring per A.8.3/A.8.16'
                : 'No hash-manifest.json -- integrity monitoring not configured',
            evidence: exists ? hashFile : undefined,
        };
    }
    checkA8EncryptionKeys() {
        const encFile = path.join(this.governanceDir, 'encryption.json');
        const exists = fs.existsSync(encFile);
        return {
            id: 'iso27001-a8-encryption',
            title: 'A.8.24: Use of cryptography',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Encryption configuration found per A.8.24'
                : 'No encryption.json -- cryptographic controls not configured',
            evidence: exists ? encFile : undefined,
        };
    }
    // ---------------------------------------------------------------------------
    // Gap analysis
    // ---------------------------------------------------------------------------
    analyzeGaps(result) {
        return result.checks
            .filter((c) => c.status === 'fail' || c.status === 'warning')
            .map((c) => ({
            control: c.id,
            title: c.title,
            detail: c.detail,
            annex: c.id.includes('a5') ? 'A.5 Organizational'
                : c.id.includes('a6') ? 'A.6 People'
                    : c.id.includes('a7') ? 'A.7 Physical'
                        : c.id.includes('a8') ? 'A.8 Technological'
                            : 'Clause',
        }));
    }
    // ---------------------------------------------------------------------------
    // Statement of Applicability generator
    // ---------------------------------------------------------------------------
    generateSoA(result) {
        const gaps = this.analyzeGaps(result);
        return {
            document: 'Statement of Applicability',
            standard: 'ISO/IEC 27001:2022',
            generatedAt: new Date().toISOString(),
            totalControls: result.checks.length,
            applicable: result.checks.length,
            implemented: result.passed,
            partiallyImplemented: result.warnings,
            notImplemented: result.failed,
            overallScore: result.score,
            gaps,
            narrative: this.narrativeWriter.write('SoA', `${result.passed}/${result.checks.length} controls implemented. Score: ${result.score}/100.`),
        };
    }
    // ---------------------------------------------------------------------------
    // Report generation
    // ---------------------------------------------------------------------------
    generateReport(result, outputDir) {
        if (!fs.existsSync(outputDir))
            fs.mkdirSync(outputDir, { recursive: true });
        const soa = this.generateSoA(result);
        const narrative = this.narrativeWriter.write('ISO-27001-2022', `Score: ${result.score}/100. ${result.passed} controls passed, ${result.failed} failed.`);
        const report = {
            framework: 'ISO/IEC 27001:2022',
            generatedAt: new Date().toISOString(),
            auditId: result.auditId,
            score: result.score,
            passed: result.passed,
            failed: result.failed,
            warnings: result.warnings,
            narrative,
            statementOfApplicability: soa,
            checks: result.checks,
        };
        const filename = `iso27001-report-${Date.now()}.json`;
        const filePath = path.join(outputDir, filename);
        fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
        return filePath;
    }
}
exports.ISO27001AuditBot = ISO27001AuditBot;
//# sourceMappingURL=iso27001.js.map