class LogPolicy { static const Set _sensitiveKeys = { 'password', 'currentpassword', 'newpassword', 'oldpassword', 'token', 'accesstoken', 'refreshtoken', 'secret', 'clientsecret', 'authorization', 'cookie', 'setcookie', 'verificationcode', 'code', 'loginchallenge', 'loginverifier', 'sessionjwt', 'accessjwt', 'refreshjwt', }; static bool isProductionEnv(String? appEnv) { final env = (appEnv ?? '').trim().toLowerCase(); return env == 'prod' || env == 'production' || env == 'stage' || env == 'staging'; } static bool parseBoolFlag(String? raw) { final value = (raw ?? '').trim().toLowerCase(); return value == '1' || value == 'true' || value == 'yes' || value == 'y' || value == 'on'; } static bool debugEnabled({ required String? appEnv, required String? productionDebugFlag, }) { if (!isProductionEnv(appEnv)) { return true; } return parseBoolFlag(productionDebugFlag); } static bool shouldRelayClientLog({ required String level, required String? appEnv, required String? productionDebugFlag, }) { if (debugEnabled( appEnv: appEnv, productionDebugFlag: productionDebugFlag, )) { return true; } final normalized = level.trim().toUpperCase(); return normalized == 'SEVERE' || normalized == 'ERROR' || normalized == 'WARNING' || normalized == 'WARN'; } static String sanitizeMessage(String message) { if (message.trim().isEmpty) { return message; } var sanitized = message.replaceAllMapped( RegExp( r'"(password|currentpassword|newpassword|oldpassword|token|accesstoken|refreshtoken|secret|clientsecret|authorization|cookie|setcookie|verificationcode|code|loginchallenge|loginverifier|sessionjwt|accessjwt|refreshjwt)"\s*:\s*"[^"]*"', caseSensitive: false, ), (match) { final key = match.group(1) ?? 'sensitive'; return '"$key":"*****"'; }, ); sanitized = sanitized.replaceAllMapped( RegExp( r'\b(password|current_password|currentpassword|new_password|newpassword|old_password|oldpassword|token|access_token|accesstoken|refresh_token|refreshtoken|authorization|cookie|session_jwt|sessionjwt|access_jwt|accessjwt|refresh_jwt|refreshjwt)\b\s*[:=]\s*([^\s,;]+)', caseSensitive: false, ), (match) { final key = match.group(1) ?? 'sensitive'; return '$key=*****'; }, ); return sanitized; } static Map sanitizeData(Map input) { final output = {}; for (final entry in input.entries) { if (_isSensitiveKey(entry.key)) { output[entry.key] = '*****'; } else { output[entry.key] = _sanitizeValue(entry.value); } } return output; } static dynamic _sanitizeValue(dynamic value) { if (value is Map) { return sanitizeData(value); } if (value is List) { return value.map(_sanitizeValue).toList(growable: false); } if (value is String) { return sanitizeMessage(value); } return value; } static bool _isSensitiveKey(String key) { var normalized = key.trim().toLowerCase(); normalized = normalized.replaceAll(RegExp(r'[-_.\s]'), ''); return _sensitiveKeys.contains(normalized); } }