/**
 * Security Audit Logger
 *
 * Comprehensive security audit logging service for SOC 2 compliance.
 * Wraps the existing audit service with specialized methods for security events.
 * Provides automatic context enrichment, severity classification, and immutable
 * log format with hash chain continuation.
 *
 * @packageDocumentation
 */
import { createHash } from 'crypto';
import { createLogger } from '../common/logger.js';
import { getTraceContext } from '../common/trace.js';
import { secureRandomString } from '../common/random.js';
import { createAuditService } from './service.js';
import { getSecurityEventDefinition, } from './security-events.js';
const logger = createLogger({ component: 'security-audit-logger' });
// Severity ordering for filtering
const SEVERITY_ORDER = {
    info: 0,
    low: 1,
    medium: 2,
    high: 3,
    critical: 4,
};
// =============================================================================
// SECURITY AUDIT LOGGER CLASS
// =============================================================================
/**
 * Security Audit Logger
 *
 * Provides comprehensive security event logging with automatic context enrichment,
 * severity classification, and immutable hash chain for SOC 2 compliance.
 */
export class SecurityAuditLogger {
    auditService;
    config;
    lastHash = null;
    sequenceNumber = 0;
    requestContext = null;
    constructor(config = {}, deps = {}) {
        this.auditService = deps.auditService ?? createAuditService();
        this.config = {
            enableHashChain: config.enableHashChain ?? true,
            consoleLogging: config.consoleLogging ?? false,
            minSeverity: config.minSeverity ?? 'info',
            defaultMetadata: config.defaultMetadata ?? {},
        };
    }
    // ===========================================================================
    // CONTEXT MANAGEMENT
    // ===========================================================================
    /**
     * Set request context for automatic enrichment
     * Call this at the start of each request to enrich all security events
     */
    setRequestContext(context) {
        this.requestContext = context;
    }
    /**
     * Clear request context
     * Call this at the end of each request
     */
    clearRequestContext() {
        this.requestContext = null;
    }
    /**
     * Create a scoped logger with preset context
     */
    withContext(context) {
        return new ScopedSecurityLogger(this, context);
    }
    // ===========================================================================
    // CORE LOGGING METHOD
    // ===========================================================================
    /**
     * Log a security event
     */
    async log(input) {
        // Get event definition
        const def = getSecurityEventDefinition(input.eventType);
        // Check severity filter
        if (SEVERITY_ORDER[def.severity] < SEVERITY_ORDER[this.config.minSeverity]) {
            throw new Error(`Event severity ${def.severity} below minimum ${this.config.minSeverity}`);
        }
        // Get trace context
        const traceContext = getTraceContext();
        // Build enriched actor
        const enrichedActor = {
            ...input.actor,
            ip: input.actor.ip ?? this.requestContext?.ip,
            userAgent: input.actor.userAgent ?? this.requestContext?.userAgent,
            sessionId: input.actor.sessionId ?? this.requestContext?.sessionId,
            tenantId: input.actor.tenantId ?? this.requestContext?.tenantId,
        };
        // Generate event ID and timestamp
        const eventId = crypto.randomUUID();
        const timestamp = input.timestamp ?? new Date().toISOString();
        const requestId = input.requestId ?? this.requestContext?.requestId ?? traceContext?.traceId ?? this.generateRequestId();
        const traceId = input.traceId ?? this.requestContext?.traceId ?? traceContext?.traceId;
        // Build the event
        const event = {
            id: eventId,
            timestamp,
            eventType: input.eventType,
            category: def.category,
            severity: def.severity,
            actor: enrichedActor,
            action: input.action,
            resource: input.resource,
            outcome: input.outcome,
            metadata: {
                ...this.config.defaultMetadata,
                ...input.metadata,
            },
            requestId,
            traceId,
            reason: input.reason,
            soc2Control: def.soc2Control,
        };
        // Add hash chain if enabled
        if (this.config.enableHashChain) {
            this.sequenceNumber++;
            event.sequenceNumber = this.sequenceNumber;
            event.previousHash = this.lastHash ?? undefined;
            event.recordHash = this.computeHash(event);
            this.lastHash = event.recordHash;
        }
        // Persist to audit service
        const tenantId = enrichedActor.tenantId ?? this.requestContext?.tenantId;
        if (!tenantId) {
            throw new Error('Tenant ID is required for security audit logging');
        }
        await this.auditService.record({
            tenantId,
            eventType: input.eventType,
            actor: {
                type: enrichedActor.type,
                id: enrichedActor.id,
                name: enrichedActor.name,
                ip: enrichedActor.ip,
            },
            target: {
                type: input.resource.type,
                id: input.resource.id,
                name: input.resource.name,
            },
            action: input.action,
            outcome: input.outcome === 'blocked' ? 'failure' : input.outcome === 'escalated' ? 'partial' : input.outcome,
            reason: input.reason,
            metadata: {
                ...event.metadata,
                category: event.category,
                severity: event.severity,
                soc2Control: event.soc2Control,
                recordHash: event.recordHash,
                previousHash: event.previousHash,
                sequenceNumber: event.sequenceNumber,
                resourcePath: input.resource.path,
                resourceAttributes: input.resource.attributes,
            },
            requestId,
            traceId,
        });
        // Console logging if enabled
        if (this.config.consoleLogging) {
            this.logToConsole(event);
        }
        return event;
    }
    // ===========================================================================
    // AUTHENTICATION EVENTS
    // ===========================================================================
    /**
     * Log authentication attempt
     */
    async logAuthAttempt(actor, success, resource, metadata, reason) {
        return this.log({
            eventType: success ? 'LOGIN_SUCCESS' : 'LOGIN_FAILURE',
            actor,
            action: 'authenticate',
            resource,
            outcome: success ? 'success' : 'failure',
            metadata,
            reason: success ? undefined : reason,
        });
    }
    /**
     * Log session creation
     */
    async logSessionCreated(actor, sessionId, metadata) {
        return this.log({
            eventType: 'SESSION_CREATED',
            actor,
            action: 'create_session',
            resource: { type: 'session', id: sessionId },
            outcome: 'success',
            metadata,
        });
    }
    /**
     * Log session validation
     */
    async logSessionValidation(actor, sessionId, valid, reason) {
        return this.log({
            eventType: valid ? 'SESSION_VALIDATED' : 'SESSION_INVALID',
            actor,
            action: 'validate_session',
            resource: { type: 'session', id: sessionId },
            outcome: valid ? 'success' : 'failure',
            reason,
        });
    }
    /**
     * Log session revocation
     */
    async logSessionRevoked(actor, sessionId, reason, metadata) {
        return this.log({
            eventType: 'SESSION_REVOKED',
            actor,
            action: 'revoke_session',
            resource: { type: 'session', id: sessionId },
            outcome: 'success',
            reason,
            metadata,
        });
    }
    /**
     * Log bulk session revocation
     */
    async logSessionsBulkRevoked(actor, userId, count, reason) {
        return this.log({
            eventType: 'SESSIONS_BULK_REVOKED',
            actor,
            action: 'bulk_revoke_sessions',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            reason,
            metadata: { sessionsRevoked: count },
        });
    }
    // ===========================================================================
    // API KEY EVENTS
    // ===========================================================================
    /**
     * Log API key creation
     */
    async logApiKeyCreated(actor, keyId, keyName, scopes, metadata) {
        return this.log({
            eventType: 'API_KEY_CREATED',
            actor,
            action: 'create_api_key',
            resource: { type: 'api_key', id: keyId, name: keyName },
            outcome: 'success',
            metadata: { ...metadata, scopes },
        });
    }
    /**
     * Log API key validation
     */
    async logApiKeyValidation(actor, keyId, keyName, valid, reason, metadata) {
        return this.log({
            eventType: valid ? 'API_KEY_VALIDATED' : 'API_KEY_VALIDATION_FAILED',
            actor,
            action: 'validate_api_key',
            resource: { type: 'api_key', id: keyId, name: keyName },
            outcome: valid ? 'success' : 'failure',
            reason,
            metadata,
        });
    }
    /**
     * Log API key revocation
     */
    async logApiKeyRevoked(actor, keyId, keyName, reason) {
        return this.log({
            eventType: 'API_KEY_REVOKED',
            actor,
            action: 'revoke_api_key',
            resource: { type: 'api_key', id: keyId, name: keyName },
            outcome: 'success',
            reason,
        });
    }
    /**
     * Log API key rotation
     */
    async logApiKeyRotated(actor, oldKeyId, newKeyId, keyName, gracePeriodMinutes) {
        return this.log({
            eventType: 'API_KEY_ROTATED',
            actor,
            action: 'rotate_api_key',
            resource: { type: 'api_key', id: newKeyId, name: keyName },
            outcome: 'success',
            metadata: { oldKeyId, gracePeriodMinutes },
        });
    }
    /**
     * Log API key rate limit exceeded
     */
    async logApiKeyRateLimited(actor, keyId, keyName, retryAfter) {
        return this.log({
            eventType: 'API_KEY_RATE_LIMITED',
            actor,
            action: 'rate_limit_exceeded',
            resource: { type: 'api_key', id: keyId, name: keyName },
            outcome: 'blocked',
            metadata: { retryAfter },
        });
    }
    // ===========================================================================
    // MFA EVENTS
    // ===========================================================================
    /**
     * Log MFA enrollment started
     */
    async logMfaEnrollmentStarted(actor, userId) {
        return this.log({
            eventType: 'MFA_ENROLLMENT_STARTED',
            actor,
            action: 'start_mfa_enrollment',
            resource: { type: 'user', id: userId },
            outcome: 'success',
        });
    }
    /**
     * Log MFA enrollment verification
     */
    async logMfaEnrollmentVerified(actor, userId, success) {
        return this.log({
            eventType: success ? 'MFA_ENROLLMENT_VERIFIED' : 'MFA_ENROLLMENT_FAILED',
            actor,
            action: 'verify_mfa_enrollment',
            resource: { type: 'user', id: userId },
            outcome: success ? 'success' : 'failure',
        });
    }
    /**
     * Log MFA enrollment completed
     */
    async logMfaEnrolled(actor, userId, backupCodeCount) {
        return this.log({
            eventType: 'MFA_ENROLLED',
            actor,
            action: 'complete_mfa_enrollment',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            metadata: { backupCodeCount },
        });
    }
    /**
     * Log MFA disabled
     */
    async logMfaDisabled(actor, userId, reason) {
        return this.log({
            eventType: 'MFA_DISABLED',
            actor,
            action: 'disable_mfa',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            reason,
        });
    }
    /**
     * Log MFA challenge created
     */
    async logMfaChallengeCreated(actor, userId, challengeId) {
        return this.log({
            eventType: 'MFA_CHALLENGE_CREATED',
            actor,
            action: 'create_mfa_challenge',
            resource: { type: 'mfa_challenge', id: challengeId },
            outcome: 'success',
            metadata: { userId },
        });
    }
    /**
     * Log MFA verification
     */
    async logMfaVerification(actor, userId, success, method, attemptsRemaining) {
        return this.log({
            eventType: success ? 'MFA_VERIFICATION_SUCCESS' : 'MFA_VERIFICATION_FAILED',
            actor,
            action: 'verify_mfa',
            resource: { type: 'user', id: userId },
            outcome: success ? 'success' : 'failure',
            metadata: { method, attemptsRemaining },
        });
    }
    /**
     * Log MFA backup code used
     */
    async logMfaBackupCodeUsed(actor, userId, codesRemaining) {
        return this.log({
            eventType: 'MFA_BACKUP_CODE_USED',
            actor,
            action: 'use_backup_code',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            metadata: { codesRemaining },
        });
    }
    /**
     * Log MFA backup codes regenerated
     */
    async logMfaBackupCodesRegenerated(actor, userId, count) {
        return this.log({
            eventType: 'MFA_BACKUP_CODES_REGENERATED',
            actor,
            action: 'regenerate_backup_codes',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            metadata: { codeCount: count },
        });
    }
    /**
     * Log MFA too many attempts
     */
    async logMfaTooManyAttempts(actor, userId, attemptCount) {
        return this.log({
            eventType: 'MFA_TOO_MANY_ATTEMPTS',
            actor,
            action: 'mfa_lockout',
            resource: { type: 'user', id: userId },
            outcome: 'blocked',
            metadata: { attemptCount },
        });
    }
    // ===========================================================================
    // AUTHORIZATION EVENTS
    // ===========================================================================
    /**
     * Log access denied
     */
    async logAccessDenied(actor, resource, reason, metadata) {
        return this.log({
            eventType: 'ACCESS_DENIED',
            actor,
            action: 'access',
            resource,
            outcome: 'blocked',
            reason,
            metadata,
        });
    }
    /**
     * Log access granted
     */
    async logAccessGranted(actor, resource, metadata) {
        return this.log({
            eventType: 'ACCESS_GRANTED',
            actor,
            action: 'access',
            resource,
            outcome: 'success',
            metadata,
        });
    }
    /**
     * Log privilege escalation
     */
    async logPrivilegeEscalated(actor, userId, fromLevel, toLevel, reason) {
        return this.log({
            eventType: 'PRIVILEGE_ESCALATED',
            actor,
            action: 'escalate_privilege',
            resource: { type: 'user', id: userId },
            outcome: 'success',
            reason,
            metadata: { fromLevel, toLevel },
        });
    }
    /**
     * Log DPoP verification
     */
    async logDpopVerification(actor, success, keyThumbprint, error) {
        return this.log({
            eventType: success ? 'DPOP_VERIFIED' : 'DPOP_FAILED',
            actor,
            action: 'verify_dpop',
            resource: { type: 'dpop_proof', id: keyThumbprint ?? 'unknown' },
            outcome: success ? 'success' : 'failure',
            reason: error,
            metadata: { keyThumbprint },
        });
    }
    /**
     * Log agent revocation
     */
    async logAgentRevoked(actor, agentDid, reason) {
        return this.log({
            eventType: 'AGENT_REVOKED',
            actor,
            action: 'revoke_agent',
            resource: { type: 'agent', id: agentDid },
            outcome: 'success',
            reason,
        });
    }
    // ===========================================================================
    // CONFIGURATION EVENTS
    // ===========================================================================
    /**
     * Log key rotation
     */
    async logKeyRotation(actor, keyId, keyType, metadata) {
        return this.log({
            eventType: 'KEY_ROTATED',
            actor,
            action: 'rotate_key',
            resource: { type: keyType, id: keyId },
            outcome: 'success',
            metadata,
        });
    }
    /**
     * Log secret rotation
     */
    async logSecretRotation(actor, secretId, secretType) {
        return this.log({
            eventType: 'SECRET_ROTATED',
            actor,
            action: 'rotate_secret',
            resource: { type: secretType, id: secretId },
            outcome: 'success',
        });
    }
    /**
     * Log configuration change
     */
    async logConfigChange(actor, configKey, resource, metadata) {
        return this.log({
            eventType: 'CONFIG_CHANGED',
            actor,
            action: 'change_config',
            resource,
            outcome: 'success',
            metadata: { ...metadata, configKey },
        });
    }
    /**
     * Log security setting change
     */
    async logSecuritySettingChange(actor, settingName, oldValue, newValue) {
        return this.log({
            eventType: 'SECURITY_SETTING_CHANGED',
            actor,
            action: 'change_security_setting',
            resource: { type: 'security_setting', id: settingName },
            outcome: 'success',
            metadata: { settingName, oldValue: String(oldValue), newValue: String(newValue) },
        });
    }
    // ===========================================================================
    // INCIDENT EVENTS
    // ===========================================================================
    /**
     * Log brute force detection
     */
    async logBruteForceDetected(actor, targetResource, attemptCount, metadata) {
        return this.log({
            eventType: 'BRUTE_FORCE_DETECTED',
            actor,
            action: 'brute_force_attack',
            resource: targetResource,
            outcome: 'blocked',
            metadata: { ...metadata, attemptCount },
        });
    }
    /**
     * Log injection attempt
     */
    async logInjectionAttempt(actor, resource, injectionType, payload) {
        return this.log({
            eventType: 'INJECTION_ATTEMPT',
            actor,
            action: 'injection_attack',
            resource,
            outcome: 'blocked',
            metadata: { injectionType, payloadHash: this.hashPayload(payload) },
        });
    }
    /**
     * Log anomaly detection
     */
    async logAnomalyDetected(actor, anomalyType, resource, details) {
        return this.log({
            eventType: 'ANOMALY_DETECTED',
            actor,
            action: 'anomaly_detection',
            resource,
            outcome: 'escalated',
            metadata: { anomalyType, ...details },
        });
    }
    /**
     * Log rate limit exceeded
     */
    async logRateLimitExceeded(actor, resource, limitType, retryAfter) {
        return this.log({
            eventType: 'RATE_LIMIT_EXCEEDED',
            actor,
            action: 'rate_limit',
            resource,
            outcome: 'blocked',
            metadata: { limitType, retryAfter },
        });
    }
    /**
     * Log IP blocked
     */
    async logIpBlocked(actor, ip, reason, duration) {
        return this.log({
            eventType: 'IP_BLOCKED',
            actor,
            action: 'block_ip',
            resource: { type: 'ip_address', id: ip },
            outcome: 'success',
            reason,
            metadata: { duration },
        });
    }
    /**
     * Log security incident created
     */
    async logIncidentCreated(actor, incidentId, incidentType, severity, description) {
        return this.log({
            eventType: 'INCIDENT_CREATED',
            actor,
            action: 'create_incident',
            resource: { type: 'incident', id: incidentId, name: incidentType },
            outcome: 'success',
            metadata: { incidentType, incidentSeverity: severity, description },
        });
    }
    /**
     * Log data access
     */
    async logDataAccess(actor, resource, operation, metadata) {
        const eventTypeMap = {
            read: 'DATA_READ',
            create: 'DATA_CREATED',
            update: 'DATA_UPDATED',
            delete: 'DATA_DELETED',
            export: 'DATA_EXPORTED',
        };
        return this.log({
            eventType: eventTypeMap[operation],
            actor,
            action: operation,
            resource,
            outcome: 'success',
            metadata,
        });
    }
    /**
     * Log sensitive data access
     */
    async logSensitiveDataAccess(actor, resource, dataClassification, reason) {
        return this.log({
            eventType: 'SENSITIVE_DATA_ACCESS',
            actor,
            action: 'access_sensitive_data',
            resource,
            outcome: 'success',
            reason,
            metadata: { dataClassification },
        });
    }
    // ===========================================================================
    // PRIVATE METHODS
    // ===========================================================================
    /**
     * Generate a unique request ID
     */
    generateRequestId() {
        return `sreq-${Date.now()}-${secureRandomString(8)}`;
    }
    /**
     * Compute hash for an event
     */
    computeHash(event) {
        const payload = {
            id: event.id,
            timestamp: event.timestamp,
            eventType: event.eventType,
            actor: event.actor,
            action: event.action,
            resource: event.resource,
            outcome: event.outcome,
            requestId: event.requestId,
            previousHash: event.previousHash,
            sequenceNumber: event.sequenceNumber,
        };
        return createHash('sha256')
            .update(JSON.stringify(payload, Object.keys(payload).sort()))
            .digest('hex');
    }
    /**
     * Hash a potentially sensitive payload
     */
    hashPayload(payload) {
        return createHash('sha256').update(payload).digest('hex').substring(0, 16);
    }
    /**
     * Log event to console
     */
    logToConsole(event) {
        const logMethod = event.severity === 'critical' || event.severity === 'high'
            ? 'warn'
            : event.severity === 'medium'
                ? 'info'
                : 'debug';
        logger[logMethod]({
            eventType: event.eventType,
            category: event.category,
            severity: event.severity,
            actorId: event.actor.id,
            actorType: event.actor.type,
            resourceType: event.resource.type,
            resourceId: event.resource.id,
            outcome: event.outcome,
            requestId: event.requestId,
        }, `Security event: ${event.eventType}`);
    }
}
// =============================================================================
// SCOPED SECURITY LOGGER
// =============================================================================
/**
 * Scoped security logger with preset context
 */
export class ScopedSecurityLogger {
    parent;
    context;
    constructor(parent, context) {
        this.parent = parent;
        this.context = context;
    }
    /**
     * Log a security event with scoped context
     */
    async log(input) {
        // Merge context into actor
        const enrichedInput = {
            ...input,
            actor: {
                ...input.actor,
                ip: input.actor.ip ?? this.context.ip,
                userAgent: input.actor.userAgent ?? this.context.userAgent,
                sessionId: input.actor.sessionId ?? this.context.sessionId,
                tenantId: input.actor.tenantId ?? this.context.tenantId,
            },
            requestId: input.requestId ?? this.context.requestId,
            traceId: input.traceId ?? this.context.traceId,
        };
        this.parent.setRequestContext(this.context);
        try {
            return await this.parent.log(enrichedInput);
        }
        finally {
            this.parent.clearRequestContext();
        }
    }
    // Delegate all typed methods to parent with context
    logAuthAttempt = (...args) => this.withScope(() => this.parent.logAuthAttempt(...args));
    logSessionCreated = (...args) => this.withScope(() => this.parent.logSessionCreated(...args));
    logSessionValidation = (...args) => this.withScope(() => this.parent.logSessionValidation(...args));
    logSessionRevoked = (...args) => this.withScope(() => this.parent.logSessionRevoked(...args));
    logApiKeyCreated = (...args) => this.withScope(() => this.parent.logApiKeyCreated(...args));
    logApiKeyValidation = (...args) => this.withScope(() => this.parent.logApiKeyValidation(...args));
    logApiKeyRevoked = (...args) => this.withScope(() => this.parent.logApiKeyRevoked(...args));
    logApiKeyRotated = (...args) => this.withScope(() => this.parent.logApiKeyRotated(...args));
    logMfaEnrollmentStarted = (...args) => this.withScope(() => this.parent.logMfaEnrollmentStarted(...args));
    logMfaEnrolled = (...args) => this.withScope(() => this.parent.logMfaEnrolled(...args));
    logMfaVerification = (...args) => this.withScope(() => this.parent.logMfaVerification(...args));
    logAccessDenied = (...args) => this.withScope(() => this.parent.logAccessDenied(...args));
    logAccessGranted = (...args) => this.withScope(() => this.parent.logAccessGranted(...args));
    logKeyRotation = (...args) => this.withScope(() => this.parent.logKeyRotation(...args));
    logBruteForceDetected = (...args) => this.withScope(() => this.parent.logBruteForceDetected(...args));
    logInjectionAttempt = (...args) => this.withScope(() => this.parent.logInjectionAttempt(...args));
    logAnomalyDetected = (...args) => this.withScope(() => this.parent.logAnomalyDetected(...args));
    logDataAccess = (...args) => this.withScope(() => this.parent.logDataAccess(...args));
    async withScope(fn) {
        this.parent.setRequestContext(this.context);
        try {
            return await fn();
        }
        finally {
            this.parent.clearRequestContext();
        }
    }
}
// =============================================================================
// FACTORY & SINGLETON
// =============================================================================
let securityLogger = null;
/**
 * Get the singleton security audit logger
 */
export function getSecurityAuditLogger(config) {
    if (!securityLogger) {
        securityLogger = new SecurityAuditLogger(config);
        logger.info('Security audit logger initialized');
    }
    return securityLogger;
}
/**
 * Create a new security audit logger instance
 */
export function createSecurityAuditLogger(config, deps) {
    return new SecurityAuditLogger(config, deps);
}
/**
 * Reset the singleton (for testing)
 */
export function resetSecurityAuditLogger() {
    securityLogger = null;
}
//# sourceMappingURL=security-logger.js.map