/** * Security Event Logger (inst_046 - Quick Win Version) * Centralized logging for all security events * * QUICK WIN: Simple file-based logging with JSON format * Full version in Phase 5 will add ProtonMail/Signal alerts */ const fs = require('fs').promises; const path = require('path'); const SECURITY_LOG_PATH = process.env.SECURITY_LOG_PATH || (process.env.HOME ? `${process.env.HOME}/var/log/tractatus/security-audit.log` : '/var/log/tractatus/security-audit.log'); /** * Log a security event to audit trail * * @param {Object} event - Security event details * @param {string} event.type - Event type (e.g., 'rate_limit_violation') * @param {string} event.sourceIp - Source IP address * @param {string} event.userId - User ID (if authenticated) * @param {string} event.endpoint - Request endpoint * @param {string} event.userAgent - User agent string * @param {Object} event.details - Additional event details * @param {string} event.action - Action taken (e.g., 'blocked', 'logged') * @param {string} event.severity - Severity level ('low', 'medium', 'high', 'critical') */ async function logSecurityEvent(event) { const logEntry = { timestamp: new Date().toISOString(), event_type: event.type || 'unknown', source_ip: event.sourceIp || 'unknown', user_id: event.userId || 'anonymous', endpoint: event.endpoint || 'unknown', user_agent: event.userAgent || 'unknown', violation_details: event.details || {}, action_taken: event.action || 'logged', severity: event.severity || 'medium' }; const logLine = `${JSON.stringify(logEntry) }\n`; try { // Ensure log directory exists const logDir = path.dirname(SECURITY_LOG_PATH); await fs.mkdir(logDir, { recursive: true, mode: 0o750 }); // Append to log file await fs.appendFile(SECURITY_LOG_PATH, logLine, { encoding: 'utf-8' }); } catch (error) { // Fallback to console if file logging fails console.error('[SECURITY LOGGER ERROR]', error.message); console.error('[SECURITY EVENT]', logEntry); } } /** * Helper: Extract client IP from request (handles proxies) */ function getClientIp(req) { return ( req.ip || req.headers['x-forwarded-for']?.split(',')[0]?.trim() || req.connection.remoteAddress || 'unknown' ); } module.exports = { logSecurityEvent, getClientIp };