import { Request, Response, NextFunction } from 'express'; export function maskPII(data: any): any { if (typeof data === 'string') { // Mask email if (data.includes('@')) { const [local, domain] = data.split('@'); return `${local.substring(0, 2)}***@${domain}`; } // Mask phone if (/^\d{10,}$/.test(data.replace(/\D/g, ''))) { const cleaned = data.replace(/\D/g, ''); return `***-***-${cleaned.slice(-4)}`; } // Mask SSN if (/^\d{3}-\d{2}-\d{4}$/.test(data)) { return `***-**-${data.slice(-4)}`; } } if (Array.isArray(data)) { return data.map(item => maskPII(item)); } if (data && typeof data === 'object') { const masked: any = {}; const sensitiveFields = ['ssn', 'taxId', 'accountNumber', 'routingNumber', 'creditCard', 'cvv']; for (const [key, value] of Object.entries(data)) { if (sensitiveFields.includes(key.toLowerCase())) { masked[key] = '***'; } else { masked[key] = maskPII(value); } } return masked; } return data; } export function maskDataInResponse(req: Request, res: Response, next: NextFunction): void { const originalJson = res.json.bind(res); res.json = function (data: any) { // Only mask in non-production or for non-admin users if (process.env.NODE_ENV !== 'production' || (req as any).userRole !== 'ADMIN') { data = maskPII(data); } return originalJson(data); }; next(); }