import { db } from '../db'; import { systemAuditLog } from '@shared/schema'; export interface AuditEntry { action: string; userId?: number | null; organizationId?: number | null; taskId?: number | null; details?: Record | null; ip?: string | null; userAgent?: string | null; } /** * Write a system audit log entry asynchronously (fire-and-forget). * A write failure is logged to console but never throws — it must not * interrupt the primary action. */ export function logAudit(entry: AuditEntry): void { db.insert(systemAuditLog) .values({ action: entry.action, userId: entry.userId ?? null, organizationId: entry.organizationId ?? null, taskId: entry.taskId ?? null, details: entry.details ?? null, ip: entry.ip ?? null, userAgent: entry.userAgent ?? null, }) .catch(err => { console.error('[audit] Failed to write system audit log:', err); }); } /** * Extract the client IP address from an Express request, * honouring the X-Forwarded-For header (trust proxy must be enabled). */ export function getClientIp(req: { ip?: string; headers: Record }): string | null { const forwarded = req.headers['x-forwarded-for']; if (forwarded) { const first = Array.isArray(forwarded) ? forwarded[0] : forwarded.split(',')[0]; return first.trim() || null; } return req.ip ?? null; }