codecrucible-synth
Version:
Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability
478 lines • 20.3 kB
JavaScript
/**
* Enterprise Error Handler
* Integrates all enterprise error handling components for unified error management
*/
import { ErrorHandler as BaseErrorHandler, } from './structured-error-system.js';
import { AuditEventType, AuditSeverity, AuditOutcome, } from '../security/security-audit-logger.js';
import { AdvancedInputValidator } from '../security/input-validation-system.js';
import { ErrorHandler as AdvancedErrorHandler, ErrorFactory, ErrorCategory, ErrorSeverity, } from './structured-error-system.js';
export class EnterpriseErrorHandler {
auditLogger;
configManager;
config;
errorMetrics = new Map();
constructor(auditLogger, configManager, config = {}) {
this.auditLogger = auditLogger;
this.configManager = configManager;
this.config = {
enableAuditLogging: true,
enableMetrics: true,
enableAlerts: true,
maxRetryAttempts: 3,
circuitBreakerThreshold: 5,
rateLimitingEnabled: true,
securityValidationEnabled: true,
...config,
};
}
/**
* Handle error with enterprise features
*/
async handleEnterpriseError(error, context = {}) {
// First handle with static error handler
const structuredError = await AdvancedErrorHandler.handleError(error, context);
// Enhanced error processing
await this.processEnterpriseError(structuredError, context);
return structuredError;
}
/**
* Process error with enterprise features
*/
async processEnterpriseError(error, context) {
try {
// Update metrics
if (this.config.enableMetrics) {
this.updateErrorMetrics(error);
}
// Security audit logging
if (this.config.enableAuditLogging && this.auditLogger) {
await this.logToSecurityAudit(error, context);
}
// Check for security implications
if (this.config.securityValidationEnabled) {
await this.validateSecurityImplications(error, context);
}
// Alert handling
if (this.config.enableAlerts) {
await this.processAlerts(error, context);
}
}
catch (processingError) {
// If enterprise processing fails, log but don't throw
console.error('Enterprise error processing failed:', processingError);
}
}
/**
* Create enterprise error with enhanced context
*/
static createEnterpriseError(message, category, severity, context = {}) {
return ErrorFactory.createError(message, category, severity, {
context,
userMessage: this.generateEnterpriseUserMessage(category, severity),
suggestedActions: this.generateEnterpriseSuggestedActions(category, severity),
retryable: this.isEnterpriseRetryable(category, severity),
recoverable: this.isEnterpriseRecoverable(category, severity),
metadata: {
estimatedResolutionTime: this.estimateResolutionTime(category, severity),
impactLevel: this.determineImpactLevel(severity),
affectedComponents: this.identifyAffectedComponents(category, context),
mitigations: this.generateMitigations(category, severity),
httpStatusCode: this.getHttpStatusCode(category, severity),
},
});
}
/**
* Validate input with enterprise security
*/
static async validateEnterpriseInput(input, fieldName, options = {}) {
try {
// Use advanced input validator for security validation
const validation = AdvancedInputValidator.validateInput(input, fieldName, {
level: options.securityLevel || 'standard',
maxLength: options.maxLength || 10000,
allowHtml: false,
allowScripts: false,
allowFileOperations: false,
allowSystemCommands: false,
customPatterns: options.allowedPatterns || [],
});
if (!validation.success) {
const error = this.createEnterpriseError(`Input validation failed for ${fieldName}`, ErrorCategory.VALIDATION, ErrorSeverity.HIGH, {
field: fieldName,
securityImplications: ['potential_injection_attack', 'malicious_input'],
complianceIssues: ['data_validation_required'],
});
return BaseErrorHandler.createErrorResponse(error);
}
const sanitizedValue = options.sanitize && validation.data.sanitizedValue ? validation.data.sanitizedValue : input;
return BaseErrorHandler.createSuccessResponse(sanitizedValue);
}
catch (error) {
const enterpriseError = this.createEnterpriseError('Input validation system error', ErrorCategory.SYSTEM, ErrorSeverity.CRITICAL, {
field: fieldName,
originalError: error,
});
return BaseErrorHandler.createErrorResponse(enterpriseError);
}
}
/**
* Circuit breaker pattern for external services
*/
async executeWithCircuitBreaker(operation, serviceName, context = {}) {
const circuitBreakerKey = `circuit_breaker_${serviceName}`;
const failures = this.errorMetrics.get(circuitBreakerKey)?.count || 0;
// Check if circuit breaker is open
if (failures >= this.config.circuitBreakerThreshold) {
const error = EnterpriseErrorHandler.createEnterpriseError(`Service ${serviceName} circuit breaker is open`, ErrorCategory.EXTERNAL_API, ErrorSeverity.HIGH, {
serviceName,
failureCount: failures,
threshold: this.config.circuitBreakerThreshold,
businessImpact: 'Service degradation',
mitigations: ['Use fallback service', 'Implement graceful degradation'],
});
return BaseErrorHandler.createErrorResponse(error);
}
try {
const result = await operation();
// Reset circuit breaker on success
this.errorMetrics.delete(circuitBreakerKey);
return BaseErrorHandler.createSuccessResponse(result);
}
catch (error) {
// Record failure
const currentMetric = this.errorMetrics.get(circuitBreakerKey);
this.errorMetrics.set(circuitBreakerKey, {
count: (currentMetric?.count || 0) + 1,
lastOccurrence: new Date(),
severity: ErrorSeverity.HIGH,
category: ErrorCategory.EXTERNAL_API,
});
const enterpriseError = await this.handleEnterpriseError(error, {
...context,
serviceName,
circuitBreakerState: 'incrementing_failures',
});
return BaseErrorHandler.createErrorResponse(enterpriseError);
}
}
/**
* Update error metrics
*/
updateErrorMetrics(error) {
const key = `${error.category}_${error.severity}`;
const current = this.errorMetrics.get(key);
this.errorMetrics.set(key, {
count: (current?.count || 0) + 1,
lastOccurrence: new Date(),
severity: error.severity,
category: error.category,
});
}
/**
* Log to security audit system
*/
async logToSecurityAudit(error, context) {
if (!this.auditLogger)
return;
const auditSeverity = this.mapToAuditSeverity(error.severity);
const auditType = this.mapToAuditEventType(error.category);
await this.auditLogger.logEvent(auditType, auditSeverity, AuditOutcome.ERROR, 'enterprise-error-handler', 'error_occurred', context.resource || 'system', `Error: ${error.message}`, {
userId: context.userId,
sessionId: context.sessionId,
requestId: context.requestId,
ipAddress: context.ipAddress,
userAgent: context.userAgent,
}, {
errorId: error.id,
errorCategory: error.category,
errorSeverity: error.severity,
operation: context.operation,
stackTrace: error.stackTrace?.substring(0, 1000),
userMessage: error.userMessage,
retryable: error.retryable,
recoverable: error.recoverable,
});
}
/**
* Validate security implications
*/
async validateSecurityImplications(error, context) {
const securityCategories = [
ErrorCategory.AUTHENTICATION,
ErrorCategory.AUTHORIZATION,
ErrorCategory.VALIDATION,
];
if (securityCategories.includes(error.category) && this.auditLogger) {
await this.auditLogger.logSecurityViolation(this.mapToAuditSeverity(error.severity), 'enterprise-error-handler', `Security-related error: ${error.message}`, {
userId: context.userId,
sessionId: context.sessionId,
ipAddress: context.ipAddress,
}, {
errorId: error.id,
errorCategory: error.category,
operation: context.operation,
potentialThreat: this.assessSecurityThreat(error, context),
});
}
}
/**
* Process alerts for critical errors
*/
async processAlerts(error, context) {
if (error.severity === ErrorSeverity.CRITICAL) {
// Critical alerts would trigger immediate notifications
console.error('🚨 CRITICAL ERROR ALERT:', {
errorId: error.id,
message: error.message,
category: error.category,
context: context,
timestamp: new Date().toISOString(),
});
// In a real system, this would integrate with:
// - PagerDuty/OpsGenie for on-call alerts
// - Slack/Teams for team notifications
// - Email for stakeholder alerts
// - SMS for critical system failures
}
}
/**
* Helper methods for enterprise error handling
*/
static generateEnterpriseUserMessage(category, severity) {
const enterpriseMessages = {
[ErrorCategory.VALIDATION]: {
[ErrorSeverity.LOW]: 'Please review your input',
[ErrorSeverity.MEDIUM]: 'Input validation failed - please check your data',
[ErrorSeverity.HIGH]: 'Security validation failed - input rejected',
[ErrorSeverity.CRITICAL]: 'Critical input security violation detected',
},
[ErrorCategory.AUTHENTICATION]: {
[ErrorSeverity.LOW]: 'Authentication issue detected',
[ErrorSeverity.MEDIUM]: 'Authentication failed - please verify credentials',
[ErrorSeverity.HIGH]: 'Authentication security issue - access denied',
[ErrorSeverity.CRITICAL]: 'Critical authentication security breach detected',
},
[ErrorCategory.AUTHORIZATION]: {
[ErrorSeverity.LOW]: 'Permission check required',
[ErrorSeverity.MEDIUM]: 'Access denied - insufficient permissions',
[ErrorSeverity.HIGH]: 'Unauthorized access attempt blocked',
[ErrorSeverity.CRITICAL]: 'Critical authorization violation detected',
},
[ErrorCategory.SYSTEM]: {
[ErrorSeverity.LOW]: 'Minor system issue',
[ErrorSeverity.MEDIUM]: 'System error occurred',
[ErrorSeverity.HIGH]: 'Serious system malfunction',
[ErrorSeverity.CRITICAL]: 'Critical system failure - immediate attention required',
},
[ErrorCategory.NETWORK]: {
[ErrorSeverity.LOW]: 'Network connectivity issue',
[ErrorSeverity.MEDIUM]: 'Network service unavailable',
[ErrorSeverity.HIGH]: 'Critical network failure',
[ErrorSeverity.CRITICAL]: 'Complete network outage detected',
},
};
return enterpriseMessages[category]?.[severity] || 'An error occurred in the system';
}
static generateEnterpriseSuggestedActions(category, severity) {
// Use the static method from ErrorHandler to get base actions
const baseActions = [];
if (severity === ErrorSeverity.CRITICAL) {
return [
'Contact system administrator immediately',
'Escalate to on-call engineer',
'Check system status dashboard',
'Review security incident procedures',
...baseActions,
];
}
if (severity === ErrorSeverity.HIGH) {
return ['Contact support team', 'Check service status', 'Review error logs', ...baseActions];
}
return baseActions;
}
static isEnterpriseRetryable(category, severity) {
// Critical errors are generally not retryable
if (severity === ErrorSeverity.CRITICAL)
return false;
// Security-related errors are not retryable
const securityCategories = [
ErrorCategory.AUTHENTICATION,
ErrorCategory.AUTHORIZATION,
ErrorCategory.VALIDATION,
];
if (securityCategories.includes(category))
return false;
return [
ErrorCategory.NETWORK,
ErrorCategory.EXTERNAL_API,
ErrorCategory.TIMEOUT,
ErrorCategory.RATE_LIMIT,
].includes(category);
}
static isEnterpriseRecoverable(category, severity) {
// Critical system errors are not recoverable
if (severity === ErrorSeverity.CRITICAL && category === ErrorCategory.SYSTEM) {
return false;
}
return severity !== ErrorSeverity.CRITICAL;
}
static estimateResolutionTime(category, severity) {
if (severity === ErrorSeverity.CRITICAL)
return '1-4 hours';
if (severity === ErrorSeverity.HIGH)
return '4-24 hours';
if (severity === ErrorSeverity.MEDIUM)
return '1-3 days';
return '3-7 days';
}
static determineImpactLevel(severity) {
return severity;
}
static identifyAffectedComponents(category, context) {
const components = [];
switch (category) {
case ErrorCategory.AUTHENTICATION:
components.push('auth-service', 'user-management');
break;
case ErrorCategory.AUTHORIZATION:
components.push('rbac-system', 'permission-engine');
break;
case ErrorCategory.NETWORK:
components.push('api-gateway', 'load-balancer');
break;
case ErrorCategory.DATABASE:
components.push('database', 'data-layer');
break;
case ErrorCategory.EXTERNAL_API:
components.push('external-apis', 'third-party-services');
break;
}
if (context.operation) {
components.push(`operation:${context.operation}`);
}
return components;
}
static generateMitigations(category, severity) {
const mitigations = [];
if (severity === ErrorSeverity.CRITICAL) {
mitigations.push('Activate incident response plan');
mitigations.push('Enable fallback systems');
mitigations.push('Notify stakeholders');
}
switch (category) {
case ErrorCategory.NETWORK:
mitigations.push('Switch to backup connectivity');
mitigations.push('Enable offline mode if available');
break;
case ErrorCategory.EXTERNAL_API:
mitigations.push('Use cached data if available');
mitigations.push('Switch to backup service provider');
break;
case ErrorCategory.DATABASE:
mitigations.push('Failover to replica database');
mitigations.push('Enable read-only mode');
break;
}
return mitigations;
}
static getHttpStatusCode(category, severity) {
switch (category) {
case ErrorCategory.AUTHENTICATION:
return 401;
case ErrorCategory.AUTHORIZATION:
return 403;
case ErrorCategory.VALIDATION:
return 400;
case ErrorCategory.NOT_FOUND:
return 404;
case ErrorCategory.CONFLICT:
return 409;
case ErrorCategory.RATE_LIMIT:
return 429;
case ErrorCategory.TIMEOUT:
return 408;
case ErrorCategory.NETWORK:
case ErrorCategory.EXTERNAL_API:
return 503;
case ErrorCategory.SYSTEM:
return severity === ErrorSeverity.CRITICAL ? 503 : 500;
default:
return 500;
}
}
mapToAuditSeverity(severity) {
switch (severity) {
case ErrorSeverity.LOW:
return AuditSeverity.LOW;
case ErrorSeverity.MEDIUM:
return AuditSeverity.MEDIUM;
case ErrorSeverity.HIGH:
return AuditSeverity.HIGH;
case ErrorSeverity.CRITICAL:
return AuditSeverity.CRITICAL;
default:
return AuditSeverity.MEDIUM;
}
}
mapToAuditEventType(category) {
switch (category) {
case ErrorCategory.AUTHENTICATION:
return AuditEventType.AUTHENTICATION;
case ErrorCategory.AUTHORIZATION:
return AuditEventType.AUTHORIZATION;
case ErrorCategory.SECURITY:
return AuditEventType.SECURITY_VIOLATION;
case ErrorCategory.SYSTEM:
return AuditEventType.SYSTEM_EVENT;
default:
return AuditEventType.ERROR_EVENT;
}
}
assessSecurityThreat(error, context) {
if (error.category === ErrorCategory.AUTHENTICATION) {
return 'potential_credential_attack';
}
if (error.category === ErrorCategory.AUTHORIZATION) {
return 'potential_privilege_escalation';
}
if (error.category === ErrorCategory.VALIDATION) {
return 'potential_injection_attack';
}
return 'unknown_threat';
}
/**
* Get enterprise error metrics
*/
getEnterpriseMetrics() {
const errorsByCategory = {};
const errorsBySeverity = {};
const circuitBreakerStatus = {};
let totalErrors = 0;
for (const [key, metric] of this.errorMetrics.entries()) {
totalErrors += metric.count;
const categoryKey = metric.category.toString();
const severityKey = metric.severity.toString();
errorsByCategory[categoryKey] = (errorsByCategory[categoryKey] || 0) + metric.count;
errorsBySeverity[severityKey] = (errorsBySeverity[severityKey] || 0) + metric.count;
// Check circuit breaker status
if (key.startsWith('circuit_breaker_')) {
const serviceName = key.replace('circuit_breaker_', '');
circuitBreakerStatus[serviceName] = metric.count >= this.config.circuitBreakerThreshold;
}
}
const recentErrors = Array.from(this.errorMetrics.entries())
.map(([key, metric]) => ({ key, count: metric.count, lastOccurrence: metric.lastOccurrence }))
.sort((a, b) => b.lastOccurrence.getTime() - a.lastOccurrence.getTime())
.slice(0, 10);
return {
totalErrors,
errorsByCategory,
errorsBySeverity,
recentErrors,
circuitBreakerStatus,
};
}
}
// Export singleton instance
export const enterpriseErrorHandler = new EnterpriseErrorHandler();
//# sourceMappingURL=enterprise-error-handler.js.map