"use strict";
/**
 * SOC1AuditBot -- Automated SOC 1 / SSAE 18 ICFR auditing.
 *
 * Covers financial-reporting controls, transaction processing controls,
 * input/output controls, data integrity tracking, control objective per
 * financial assertion, and SOC 1 Type II narrative generation.
 * Does NOT call external APIs.
 *
 * Narrative writing is delegated to an injectable NarrativeWriter.
 *
 * P2A-11
 *
 * @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.SOC1AuditBot = 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 `[SOC 1] Control ${controlId}: ${context.slice(0, 120)}`;
    }
}
exports.StubNarrativeWriter = StubNarrativeWriter;
class SOC1AuditBot {
    logDir;
    governanceDir;
    narrativeWriter;
    constructor(config) {
        this.logDir = config.logDir;
        this.governanceDir = config.governanceDir;
        this.narrativeWriter = config.narrativeWriter ?? new StubNarrativeWriter();
    }
    runAudit() {
        const checks = [
            // Control environment
            this.checkControlEnvironment(),
            this.checkRiskAssessmentICFR(),
            // Logical access (AT-C 320 CC6 equivalent)
            this.checkLogicalAccessControls(),
            this.checkPrivilegedAccessManagement(),
            this.checkMFAForFinancialSystems(),
            // Transaction processing controls
            this.checkTransactionCompleteness(),
            this.checkTransactionAccuracy(),
            this.checkTransactionValidity(),
            // Input/output controls
            this.checkInputValidation(),
            this.checkOutputReconciliation(),
            // Data integrity
            this.checkDataIntegrityHashing(),
            this.checkAuditTrailIntegrity(),
            // Change management
            this.checkChangeManagement(),
            // Availability and continuity
            this.checkAvailabilityControls(),
            this.checkBackupRecovery(),
            // Monitoring and incident response
            this.checkAuditLogging(),
            this.checkIncidentResponse(),
        ];
        const { score, passed, failed, warnings } = (0, scheduler_1.computeAuditScore)(checks);
        return {
            auditId: '',
            packId: 'soc1',
            timestamp: new Date().toISOString(),
            checks,
            score,
            passed,
            failed,
            warnings,
        };
    }
    // --- Control environment ---
    checkControlEnvironment() {
        const govFile = path.join(this.governanceDir, 'governance.json');
        const exists = fs.existsSync(govFile);
        if (!exists) {
            return {
                id: 'soc1-cc1-control-environment',
                title: 'CC1: Control environment (governance.json)',
                status: 'fail',
                detail: 'No governance.json -- control environment not documented',
            };
        }
        try {
            const content = JSON.parse(fs.readFileSync(govFile, 'utf-8'));
            const valid = content && (content.version || content.rules || content.agentId);
            return {
                id: 'soc1-cc1-control-environment',
                title: 'CC1: Control environment (governance.json)',
                status: valid ? 'pass' : 'warning',
                detail: valid
                    ? 'Control environment configuration found per SSAE 18 CC1'
                    : 'governance.json found but missing expected structure',
                evidence: govFile,
            };
        }
        catch {
            return {
                id: 'soc1-cc1-control-environment',
                title: 'CC1: Control environment (governance.json)',
                status: 'fail',
                detail: 'governance.json is invalid JSON',
                evidence: govFile,
            };
        }
    }
    checkRiskAssessmentICFR() {
        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: 'soc1-cc3-risk-assessment',
            title: 'CC3: Risk assessment for ICFR',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Risk assessment or anomaly detection found per SSAE 18 CC3'
                : 'No risk-assessment.json or anomaly-detection.json -- ICFR risk assessment not evidenced',
            evidence: exists
                ? [riskFile, anomalyFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Logical access ---
    checkLogicalAccessControls() {
        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: 'soc1-cc6-logical-access',
            title: 'CC6: Logical access restrictions',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Role-based access controls found per SSAE 18 CC6'
                : 'No roles.json or permissions.json -- logical access to financial systems not restricted',
            evidence: exists
                ? [rolesFile, permFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkPrivilegedAccessManagement() {
        const authFile = path.join(this.governanceDir, 'agent-auth.json');
        const rolesFile = path.join(this.governanceDir, 'roles.json');
        const exists = fs.existsSync(authFile) && fs.existsSync(rolesFile);
        return {
            id: 'soc1-cc6-privileged-access',
            title: 'CC6: Privileged access management',
            status: exists ? 'pass' : exists || fs.existsSync(authFile) ? 'warning' : 'fail',
            detail: exists
                ? 'Both authentication and role definitions found for privileged access management'
                : fs.existsSync(authFile)
                    ? 'agent-auth.json found but no roles.json -- privileged access tiers not defined'
                    : 'No agent-auth.json -- privileged access management not configured',
            evidence: exists
                ? [authFile, rolesFile].filter((f) => fs.existsSync(f)).join(', ')
                : fs.existsSync(authFile) ? authFile : undefined,
        };
    }
    checkMFAForFinancialSystems() {
        const authFile = path.join(this.governanceDir, 'agent-auth.json');
        const exists = fs.existsSync(authFile);
        return {
            id: 'soc1-cc6-mfa',
            title: 'CC6: Multi-factor authentication for financial system access',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Authentication configuration found; MFA enforcement implied per CC6'
                : 'No agent-auth.json -- MFA for financial system access not configured',
            evidence: exists ? authFile : undefined,
        };
    }
    // --- Transaction processing ---
    checkTransactionCompleteness() {
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        return {
            id: 'soc1-tpc-completeness',
            title: 'Transaction processing: Completeness assertion',
            status: hasLogs ? 'pass' : 'fail',
            detail: hasLogs
                ? 'JSONL audit logs provide transaction completeness evidence'
                : 'No JSONL audit logs -- transaction completeness not evidenced',
            evidence: hasLogs ? this.logDir : undefined,
        };
    }
    checkTransactionAccuracy() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const exists = fs.existsSync(hashFile);
        return {
            id: 'soc1-tpc-accuracy',
            title: 'Transaction processing: Accuracy assertion',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Hash manifest provides transaction accuracy / integrity verification'
                : 'No hash-manifest.json -- transaction data integrity not verifiable',
            evidence: exists ? hashFile : undefined,
        };
    }
    checkTransactionValidity() {
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const capFile = path.join(this.governanceDir, 'capability-bundles.json');
        const exists = fs.existsSync(permFile) || fs.existsSync(capFile);
        return {
            id: 'soc1-tpc-validity',
            title: 'Transaction processing: Validity assertion (authorized transactions only)',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Permission or capability controls ensure only authorized transactions processed'
                : 'No permissions.json or capability-bundles.json -- transaction validity controls not configured',
            evidence: exists
                ? [permFile, capFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Input/output controls ---
    checkInputValidation() {
        const permFile = path.join(this.governanceDir, 'permissions.json');
        const classifierFile = path.join(this.governanceDir, 'data-classifier.json');
        const exists = fs.existsSync(permFile) || fs.existsSync(classifierFile);
        return {
            id: 'soc1-io-input-validation',
            title: 'Input controls: Data validation at entry points',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Permission or classifier controls validate input data'
                : 'No permissions.json or data-classifier.json -- input validation controls not evidenced',
            evidence: exists
                ? [permFile, classifierFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkOutputReconciliation() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        const exists = fs.existsSync(hashFile) || hasLogs;
        return {
            id: 'soc1-io-output-reconciliation',
            title: 'Output controls: Reconciliation and completeness',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Hash manifest or audit logs support output reconciliation'
                : 'No hash-manifest.json or audit logs -- output reconciliation not evidenced',
            evidence: exists
                ? (fs.existsSync(hashFile) ? hashFile : this.logDir)
                : undefined,
        };
    }
    // --- Data integrity ---
    checkDataIntegrityHashing() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const exists = fs.existsSync(hashFile);
        return {
            id: 'soc1-di-hashing',
            title: 'Data integrity: Cryptographic hash verification',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Hash manifest enables data integrity verification per SSAE 18'
                : 'No hash-manifest.json -- data integrity not cryptographically verifiable',
            evidence: exists ? hashFile : undefined,
        };
    }
    checkAuditTrailIntegrity() {
        const hasChainLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.includes('audit-chain') || f.includes('chain'));
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        return {
            id: 'soc1-di-audit-trail',
            title: 'Data integrity: Audit trail integrity',
            status: hasChainLogs ? 'pass' : hasLogs ? 'warning' : 'fail',
            detail: hasChainLogs
                ? 'Hash-chained audit logs ensure audit trail integrity'
                : hasLogs
                    ? 'JSONL audit logs found but no hash-chained trail -- integrity verification recommended'
                    : 'No audit logs -- audit trail integrity not established',
            evidence: hasLogs ? this.logDir : undefined,
        };
    }
    // --- Change management ---
    checkChangeManagement() {
        const hashFile = path.join(this.governanceDir, 'hash-manifest.json');
        const cbFile = path.join(this.governanceDir, 'circuit-breaker.json');
        const exists = fs.existsSync(hashFile) || fs.existsSync(cbFile);
        return {
            id: 'soc1-cc8-change-mgmt',
            title: 'CC8: Change management controls',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Hash manifest or circuit breaker controls change management per CC8'
                : 'No hash-manifest.json or circuit-breaker.json -- change management controls not evidenced',
            evidence: exists
                ? [hashFile, cbFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    // --- Availability and continuity ---
    checkAvailabilityControls() {
        const cbFile = path.join(this.governanceDir, 'circuit-breaker.json');
        const monitorFile = path.join(this.governanceDir, 'monitoring.json');
        const exists = fs.existsSync(cbFile) || fs.existsSync(monitorFile);
        return {
            id: 'soc1-a1-availability',
            title: 'Availability: Service continuity controls',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Circuit breaker or monitoring configuration supports availability per SSAE 18'
                : 'No circuit-breaker.json or monitoring.json -- availability controls not evidenced',
            evidence: exists
                ? [cbFile, monitorFile].filter((f) => fs.existsSync(f)).join(', ')
                : undefined,
        };
    }
    checkBackupRecovery() {
        const backupFile = path.join(this.governanceDir, 'backup-policy.json');
        const exists = fs.existsSync(backupFile);
        return {
            id: 'soc1-a1-backup',
            title: 'Availability: Backup and recovery procedures',
            status: exists ? 'pass' : 'warning',
            detail: exists
                ? 'Backup policy found per SSAE 18 availability criteria'
                : 'No backup-policy.json -- backup and recovery not documented',
            evidence: exists ? backupFile : undefined,
        };
    }
    // --- Monitoring ---
    checkAuditLogging() {
        const hasLogs = fs.existsSync(this.logDir) &&
            fs.readdirSync(this.logDir).some((f) => f.endsWith('.jsonl'));
        return {
            id: 'soc1-cc7-logging',
            title: 'CC7: System monitoring and audit logging',
            status: hasLogs ? 'pass' : 'fail',
            detail: hasLogs
                ? 'JSONL audit logs found per SSAE 18 CC7 monitoring'
                : 'No JSONL audit logs -- system activity monitoring not operational',
            evidence: hasLogs ? this.logDir : undefined,
        };
    }
    checkIncidentResponse() {
        const irFile = path.join(this.governanceDir, 'incident-response.json');
        const exists = fs.existsSync(irFile);
        return {
            id: 'soc1-cc7-incident-response',
            title: 'CC7: Incident response for ICFR',
            status: exists ? 'pass' : 'fail',
            detail: exists
                ? 'Incident response plan found per SSAE 18 CC7'
                : 'No incident-response.json -- financial system incident response not configured',
            evidence: exists ? irFile : undefined,
        };
    }
    // ---------------------------------------------------------------------------
    // Control objectives per financial assertion
    // ---------------------------------------------------------------------------
    buildControlObjectives(result) {
        const completenessCheck = result.checks.find((c) => c.id === 'soc1-tpc-completeness');
        const accuracyCheck = result.checks.find((c) => c.id === 'soc1-tpc-accuracy');
        const validityCheck = result.checks.find((c) => c.id === 'soc1-tpc-validity');
        const accessCheck = result.checks.find((c) => c.id === 'soc1-cc6-logical-access');
        const loggingCheck = result.checks.find((c) => c.id === 'soc1-cc7-logging');
        const mapStatus = (check) => {
            if (!check)
                return 'not-tested';
            if (check.status === 'pass')
                return 'effective';
            if (check.status === 'warning')
                return 'deficient';
            return 'material-weakness';
        };
        return [
            {
                id: 'CO-01',
                assertion: 'completeness',
                title: 'All transactions are completely recorded',
                status: mapStatus(completenessCheck),
            },
            {
                id: 'CO-02',
                assertion: 'accuracy',
                title: 'Transactions are accurately processed',
                status: mapStatus(accuracyCheck),
            },
            {
                id: 'CO-03',
                assertion: 'validity',
                title: 'Only authorized transactions are processed',
                status: mapStatus(validityCheck),
            },
            {
                id: 'CO-04',
                assertion: 'restricted-access',
                title: 'Access to financial data is restricted',
                status: mapStatus(accessCheck),
            },
            {
                id: 'CO-05',
                assertion: 'timeliness',
                title: 'Transaction activity is logged timely',
                status: mapStatus(loggingCheck),
            },
        ];
    }
    // ---------------------------------------------------------------------------
    // Gap analysis
    // ---------------------------------------------------------------------------
    analyzeGaps(result) {
        return result.checks
            .filter((c) => c.status === 'fail' || c.status === 'warning')
            .map((c) => ({
            controlObjective: c.id,
            title: c.title,
            detail: c.detail,
        }));
    }
    // ---------------------------------------------------------------------------
    // Type II narrative generator
    // ---------------------------------------------------------------------------
    generateTypeIINarrative(result) {
        const controlObjectives = this.buildControlObjectives(result);
        const effectiveCount = controlObjectives.filter((c) => c.status === 'effective').length;
        return this.narrativeWriter.write('SOC1-TYPE-II', `${effectiveCount}/${controlObjectives.length} control objectives effective. Score: ${result.score}/100.`);
    }
    // ---------------------------------------------------------------------------
    // Report generation
    // ---------------------------------------------------------------------------
    generateReport(result, outputDir) {
        if (!fs.existsSync(outputDir))
            fs.mkdirSync(outputDir, { recursive: true });
        const controlObjectives = this.buildControlObjectives(result);
        const gaps = this.analyzeGaps(result);
        const typeIINarrative = this.generateTypeIINarrative(result);
        const report = {
            framework: 'SOC 1 / SSAE 18 (ICFR)',
            generatedAt: new Date().toISOString(),
            auditId: result.auditId,
            score: result.score,
            passed: result.passed,
            failed: result.failed,
            warnings: result.warnings,
            typeIINarrative,
            controlObjectives,
            gaps,
            checks: result.checks,
            auditOpinion: result.score >= 80 ? 'Unqualified' : result.score >= 60 ? 'Qualified' : 'Adverse',
        };
        const filename = `soc1-report-${Date.now()}.json`;
        const filePath = path.join(outputDir, filename);
        fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
        return filePath;
    }
}
exports.SOC1AuditBot = SOC1AuditBot;
//# sourceMappingURL=soc1.js.map