UNPKG

@versatil/sdlc-framework

Version:

🚀 AI-Native SDLC framework with 11-MCP ecosystem, RAG memory, OPERA orchestration, and 6 specialized agents achieving ZERO CONTEXT LOSS. Features complete CI/CD pipeline with 7 GitHub workflows (MCP testing, security scanning, performance benchmarking),

1,255 lines • 51.9 kB
/** * VERSATIL SDLC Framework - Daily Audit and Health Check System * Implements Rule 3: Run a complete audit and health check per day at least * * Features: * - Comprehensive daily health checks * - Security audit automation * - Performance monitoring and trending * - Code quality assessment * - Dependency vulnerability scanning * - Infrastructure health monitoring * - Compliance reporting * - Automated issue detection and alerting */ import { EventEmitter } from 'events'; import { EnvironmentManager } from '../environment/environment-manager.js'; import { ParallelTaskManager, TaskType, Priority, SDLCPhase, CollisionRisk, ResourceType } from '../orchestration/parallel-task-manager.js'; export var AuditType; (function (AuditType) { AuditType["COMPREHENSIVE"] = "comprehensive"; AuditType["SECURITY"] = "security"; AuditType["PERFORMANCE"] = "performance"; AuditType["QUALITY"] = "quality"; AuditType["INFRASTRUCTURE"] = "infrastructure"; AuditType["COMPLIANCE"] = "compliance"; AuditType["DEPENDENCY"] = "dependency"; AuditType["BACKUP"] = "backup"; })(AuditType || (AuditType = {})); export var ScheduleFrequency; (function (ScheduleFrequency) { ScheduleFrequency["HOURLY"] = "hourly"; ScheduleFrequency["DAILY"] = "daily"; ScheduleFrequency["WEEKLY"] = "weekly"; ScheduleFrequency["MONTHLY"] = "monthly"; ScheduleFrequency["CUSTOM"] = "custom"; })(ScheduleFrequency || (ScheduleFrequency = {})); export var CheckCategory; (function (CheckCategory) { CheckCategory["SYSTEM"] = "system"; CheckCategory["APPLICATION"] = "application"; CheckCategory["SECURITY"] = "security"; CheckCategory["PERFORMANCE"] = "performance"; CheckCategory["QUALITY"] = "quality"; CheckCategory["COMPLIANCE"] = "compliance"; CheckCategory["INFRASTRUCTURE"] = "infrastructure"; CheckCategory["DATA_INTEGRITY"] = "data_integrity"; })(CheckCategory || (CheckCategory = {})); export var CheckType; (function (CheckType) { CheckType["METRIC"] = "metric"; CheckType["SCRIPT"] = "script"; CheckType["API_CALL"] = "api_call"; CheckType["FILE_CHECK"] = "file_check"; CheckType["PROCESS_CHECK"] = "process_check"; CheckType["NETWORK_CHECK"] = "network_check"; CheckType["DATABASE_CHECK"] = "database_check"; CheckType["LOG_ANALYSIS"] = "log_analysis"; })(CheckType || (CheckType = {})); export var TargetType; (function (TargetType) { TargetType["SYSTEM"] = "system"; TargetType["APPLICATION"] = "application"; TargetType["SERVICE"] = "service"; TargetType["DATABASE"] = "database"; TargetType["FILE"] = "file"; TargetType["DIRECTORY"] = "directory"; TargetType["ENDPOINT"] = "endpoint"; TargetType["PROCESS"] = "process"; TargetType["LOG_FILE"] = "log_file"; })(TargetType || (TargetType = {})); export var ThresholdOperator; (function (ThresholdOperator) { ThresholdOperator["GREATER_THAN"] = "gt"; ThresholdOperator["LESS_THAN"] = "lt"; ThresholdOperator["EQUAL"] = "eq"; ThresholdOperator["NOT_EQUAL"] = "ne"; ThresholdOperator["GREATER_EQUAL"] = "gte"; ThresholdOperator["LESS_EQUAL"] = "lte"; ThresholdOperator["CONTAINS"] = "contains"; ThresholdOperator["NOT_CONTAINS"] = "not_contains"; })(ThresholdOperator || (ThresholdOperator = {})); export var NotificationSeverity; (function (NotificationSeverity) { NotificationSeverity["INFO"] = "info"; NotificationSeverity["WARNING"] = "warning"; NotificationSeverity["CRITICAL"] = "critical"; NotificationSeverity["EMERGENCY"] = "emergency"; })(NotificationSeverity || (NotificationSeverity = {})); export var AuditStatus; (function (AuditStatus) { AuditStatus["SUCCESS"] = "success"; AuditStatus["WARNING"] = "warning"; AuditStatus["FAILURE"] = "failure"; AuditStatus["ERROR"] = "error"; AuditStatus["CANCELLED"] = "cancelled"; })(AuditStatus || (AuditStatus = {})); export var CheckStatus; (function (CheckStatus) { CheckStatus["PASS"] = "pass"; CheckStatus["WARNING"] = "warning"; CheckStatus["FAIL"] = "fail"; CheckStatus["ERROR"] = "error"; CheckStatus["SKIP"] = "skip"; })(CheckStatus || (CheckStatus = {})); export var IssueSeverity; (function (IssueSeverity) { IssueSeverity["LOW"] = "low"; IssueSeverity["MEDIUM"] = "medium"; IssueSeverity["HIGH"] = "high"; IssueSeverity["CRITICAL"] = "critical"; IssueSeverity["EMERGENCY"] = "emergency"; })(IssueSeverity || (IssueSeverity = {})); export var IssueCategory; (function (IssueCategory) { IssueCategory["PERFORMANCE"] = "performance"; IssueCategory["SECURITY"] = "security"; IssueCategory["RELIABILITY"] = "reliability"; IssueCategory["QUALITY"] = "quality"; IssueCategory["COMPLIANCE"] = "compliance"; IssueCategory["INFRASTRUCTURE"] = "infrastructure"; IssueCategory["DATA"] = "data"; IssueCategory["CONFIGURATION"] = "configuration"; })(IssueCategory || (IssueCategory = {})); export var ImpactLevel; (function (ImpactLevel) { ImpactLevel["MINIMAL"] = "minimal"; ImpactLevel["LOW"] = "low"; ImpactLevel["MEDIUM"] = "medium"; ImpactLevel["HIGH"] = "high"; ImpactLevel["CRITICAL"] = "critical"; })(ImpactLevel || (ImpactLevel = {})); export var UrgencyLevel; (function (UrgencyLevel) { UrgencyLevel["LOW"] = "low"; UrgencyLevel["MEDIUM"] = "medium"; UrgencyLevel["HIGH"] = "high"; UrgencyLevel["CRITICAL"] = "critical"; UrgencyLevel["IMMEDIATE"] = "immediate"; })(UrgencyLevel || (UrgencyLevel = {})); export var RecommendationCategory; (function (RecommendationCategory) { RecommendationCategory["PERFORMANCE_OPTIMIZATION"] = "performance_optimization"; RecommendationCategory["SECURITY_ENHANCEMENT"] = "security_enhancement"; RecommendationCategory["RELIABILITY_IMPROVEMENT"] = "reliability_improvement"; RecommendationCategory["QUALITY_IMPROVEMENT"] = "quality_improvement"; RecommendationCategory["INFRASTRUCTURE_UPGRADE"] = "infrastructure_upgrade"; RecommendationCategory["PROCESS_IMPROVEMENT"] = "process_improvement"; RecommendationCategory["MONITORING_ENHANCEMENT"] = "monitoring_enhancement"; RecommendationCategory["AUTOMATION"] = "automation"; })(RecommendationCategory || (RecommendationCategory = {})); export var EffortLevel; (function (EffortLevel) { EffortLevel["MINIMAL"] = "minimal"; EffortLevel["LOW"] = "low"; EffortLevel["MEDIUM"] = "medium"; EffortLevel["HIGH"] = "high"; EffortLevel["VERY_HIGH"] = "very_high"; })(EffortLevel || (EffortLevel = {})); export var TrendDirection; (function (TrendDirection) { TrendDirection["IMPROVING"] = "improving"; TrendDirection["STABLE"] = "stable"; TrendDirection["DECLINING"] = "declining"; TrendDirection["UNKNOWN"] = "unknown"; })(TrendDirection || (TrendDirection = {})); export class DailyAuditSystem extends EventEmitter { constructor() { super(); this.auditConfigs = new Map(); this.activeAudits = new Map(); this.auditHistory = []; this.schedules = new Map(); this.healthChecks = new Map(); this.environmentManager = new EnvironmentManager(); this.taskManager = new ParallelTaskManager(); this.initializeDefaultChecks(); this.initializeDefaultAudits(); this.startScheduler(); } /** * Run comprehensive daily audit */ async runDailyAudit() { const auditId = `daily_audit_${Date.now()}`; this.emit('audit:started', { auditId, type: 'daily' }); const startTime = new Date(); try { // Get current environment const environment = await this.environmentManager.getCurrentEnvironment(); // Create comprehensive audit configuration const auditConfig = await this.createDailyAuditConfig(environment); // Execute audit const result = await this.executeAudit(auditConfig); this.emit('audit:completed', { auditId, result }); // Send notifications if needed await this.processAuditNotifications(result); // Store result this.auditHistory.push(result); this.activeAudits.set(auditId, result); // Cleanup old audit data await this.cleanupOldAudits(); return result; } catch (error) { this.emit('audit:failed', { auditId, error }); throw error; } } /** * Execute a specific audit configuration */ async executeAudit(config) { const startTime = new Date(); const auditId = `audit_${config.id}_${Date.now()}`; this.emit('audit:execution:started', { auditId, config }); try { // Create parallel tasks for all health checks const checkTasks = await this.createCheckTasks(config.checks, auditId); // Execute checks in parallel const taskResults = await this.taskManager.executeParallel(checkTasks.map(t => t.id)); // Process check results const checkResults = await this.processCheckResults(taskResults, config.checks); // Calculate scores and overall health const scores = this.calculateAuditScores(checkResults); const overallHealth = this.calculateOverallHealth(scores, checkResults); // Identify issues const issues = this.identifyIssues(checkResults, config.thresholds); // Generate recommendations const recommendations = await this.generateRecommendations(issues, checkResults); // Perform trend analysis const trends = await this.performTrendAnalysis(scores, issues); // Create audit summary const summary = this.createAuditSummary(checkResults); const endTime = new Date(); const duration = endTime.getTime() - startTime.getTime(); const result = { id: auditId, auditId: config.id, startTime, endTime, duration, status: this.determineAuditStatus(overallHealth, issues), overallHealth, scores, checkResults, issues, recommendations, trends, summary }; this.emit('audit:execution:completed', { auditId, result }); return result; } catch (error) { this.emit('audit:execution:failed', { auditId, error }); throw error; } } /** * Run health check on demand */ async runHealthCheck(checkId) { const check = this.healthChecks.get(checkId); if (!check) { throw new Error(`Health check not found: ${checkId}`); } this.emit('health_check:started', { checkId, check }); const startTime = new Date(); try { const result = await this.executeHealthCheck(check); this.emit('health_check:completed', { checkId, result }); return result; } catch (error) { this.emit('health_check:failed', { checkId, error }); const result = { checkId, status: CheckStatus.ERROR, value: null, message: `Check execution failed: ${error.message}`, timestamp: new Date(), duration: Date.now() - startTime.getTime(), metadata: { error: error.message } }; return result; } } /** * Add custom audit configuration */ async addAuditConfig(config) { this.auditConfigs.set(config.id, config); if (config.schedule.enabled) { this.scheduleAudit(config); } this.emit('audit_config:added', { config }); } /** * Add custom health check */ async addHealthCheck(check) { this.healthChecks.set(check.id, check); this.emit('health_check:added', { check }); } /** * Initialize default health checks */ initializeDefaultChecks() { const defaultChecks = [ // System checks { id: 'system_cpu_usage', name: 'CPU Usage', category: CheckCategory.SYSTEM, type: CheckType.METRIC, target: { type: TargetType.SYSTEM, identifier: 'cpu' }, parameters: { command: 'top -bn1 | grep "Cpu(s)" | awk \'{print $2}\' | awk -F\'%\' \'{print $1}\'' }, thresholds: { warning: { value: 80 }, critical: { value: 90 }, operator: ThresholdOperator.GREATER_THAN, unit: '%' }, weight: 0.8, critical: true, enabled: true }, { id: 'system_memory_usage', name: 'Memory Usage', category: CheckCategory.SYSTEM, type: CheckType.METRIC, target: { type: TargetType.SYSTEM, identifier: 'memory' }, parameters: { command: 'free | grep Mem | awk \'{printf "%.2f", ($3/$2) * 100.0}\'' }, thresholds: { warning: { value: 80 }, critical: { value: 95 }, operator: ThresholdOperator.GREATER_THAN, unit: '%' }, weight: 0.9, critical: true, enabled: true }, { id: 'system_disk_usage', name: 'Disk Usage', category: CheckCategory.SYSTEM, type: CheckType.METRIC, target: { type: TargetType.SYSTEM, identifier: 'disk' }, parameters: { command: 'df -h / | awk \'NR==2 {print $5}\' | sed \'s/%//\'' }, thresholds: { warning: { value: 80 }, critical: { value: 90 }, operator: ThresholdOperator.GREATER_THAN, unit: '%' }, weight: 0.7, critical: true, enabled: true }, // Application checks { id: 'app_process_running', name: 'Application Process', category: CheckCategory.APPLICATION, type: CheckType.PROCESS_CHECK, target: { type: TargetType.PROCESS, identifier: 'node' }, parameters: { command: 'pgrep -f "node.*versatil" | wc -l' }, thresholds: { warning: { value: 1 }, critical: { value: 1 }, operator: ThresholdOperator.LESS_THAN }, weight: 1.0, critical: true, enabled: true }, { id: 'app_response_time', name: 'Application Response Time', category: CheckCategory.PERFORMANCE, type: CheckType.API_CALL, target: { type: TargetType.ENDPOINT, identifier: 'health', endpoint: '/health' }, parameters: { url: 'http://localhost:3000/health', timeout: 5000, retries: 3 }, thresholds: { warning: { value: 2000 }, critical: { value: 5000 }, operator: ThresholdOperator.GREATER_THAN, unit: 'ms' }, weight: 0.9, critical: false, enabled: true }, // Security checks { id: 'security_file_permissions', name: 'Critical File Permissions', category: CheckCategory.SECURITY, type: CheckType.FILE_CHECK, target: { type: TargetType.FILE, identifier: 'config_files' }, parameters: { script: 'find . -name "*.json" -o -name "*.env" | xargs ls -la | grep -v "^-rw-------" | wc -l' }, thresholds: { warning: { value: 0 }, critical: { value: 0 }, operator: ThresholdOperator.GREATER_THAN }, weight: 0.8, critical: true, enabled: true }, { id: 'security_dependency_vulnerabilities', name: 'Dependency Vulnerabilities', category: CheckCategory.SECURITY, type: CheckType.SCRIPT, target: { type: TargetType.APPLICATION, identifier: 'dependencies' }, parameters: { command: 'npm audit --audit-level high --json | jq ".metadata.vulnerabilities.high + .metadata.vulnerabilities.critical"' }, thresholds: { warning: { value: 0 }, critical: { value: 0 }, operator: ThresholdOperator.GREATER_THAN }, weight: 1.0, critical: true, enabled: true }, // Quality checks { id: 'quality_test_coverage', name: 'Test Coverage', category: CheckCategory.QUALITY, type: CheckType.SCRIPT, target: { type: TargetType.APPLICATION, identifier: 'tests' }, parameters: { command: 'npm run test:coverage --silent | grep "All files" | awk \'{print $10}\' | sed \'s/%//\'' }, thresholds: { warning: { value: 80 }, critical: { value: 70 }, operator: ThresholdOperator.LESS_THAN, unit: '%' }, weight: 0.7, critical: false, enabled: true }, { id: 'quality_typescript_errors', name: 'TypeScript Errors', category: CheckCategory.QUALITY, type: CheckType.SCRIPT, target: { type: TargetType.APPLICATION, identifier: 'typescript' }, parameters: { command: 'npx tsc --noEmit 2>&1 | grep "error TS" | wc -l' }, thresholds: { warning: { value: 0 }, critical: { value: 0 }, operator: ThresholdOperator.GREATER_THAN }, weight: 0.9, critical: false, enabled: true }, // Infrastructure checks { id: 'infrastructure_git_status', name: 'Git Repository Status', category: CheckCategory.INFRASTRUCTURE, type: CheckType.SCRIPT, target: { type: TargetType.APPLICATION, identifier: 'git' }, parameters: { command: 'git status --porcelain | wc -l' }, thresholds: { warning: { value: 10 }, critical: { value: 50 }, operator: ThresholdOperator.GREATER_THAN }, weight: 0.3, critical: false, enabled: true }, { id: 'infrastructure_log_errors', name: 'Application Log Errors', category: CheckCategory.INFRASTRUCTURE, type: CheckType.LOG_ANALYSIS, target: { type: TargetType.LOG_FILE, identifier: 'app_logs' }, parameters: { command: 'find . -name "*.log" -mtime -1 -exec grep -i "error\\|exception\\|fatal" {} \\; | wc -l' }, thresholds: { warning: { value: 10 }, critical: { value: 50 }, operator: ThresholdOperator.GREATER_THAN }, weight: 0.6, critical: false, enabled: true } ]; for (const check of defaultChecks) { this.healthChecks.set(check.id, check); } } /** * Initialize default audit configurations */ initializeDefaultAudits() { const dailyAudit = { id: 'daily_comprehensive', name: 'Daily Comprehensive Audit', type: AuditType.COMPREHENSIVE, schedule: { frequency: ScheduleFrequency.DAILY, time: '02:00', timezone: 'UTC', enabled: true }, checks: Array.from(this.healthChecks.values()), thresholds: { overallHealth: 85, criticalIssues: 0, warningIssues: 5, performanceScore: 80, securityScore: 95, qualityScore: 80 }, notifications: { email: [ { recipients: ['admin@versatil.com'], subject: 'VERSATIL Daily Audit Report', template: 'daily_audit', attachReports: true, severity: [NotificationSeverity.WARNING, NotificationSeverity.CRITICAL] } ], dashboard: true }, retention: { keepDays: 90, keepReports: 30, compressionEnabled: true }, enabled: true }; this.auditConfigs.set(dailyAudit.id, dailyAudit); } /** * Start the audit scheduler */ startScheduler() { // Check for scheduled audits every minute setInterval(() => { this.checkScheduledAudits(); }, 60000); this.emit('scheduler:started'); } /** * Check for scheduled audits */ checkScheduledAudits() { const now = new Date(); for (const [configId, config] of this.auditConfigs) { if (!config.enabled || !config.schedule.enabled) continue; if (this.shouldRunAudit(config, now)) { this.executeAudit(config).catch(error => { this.emit('scheduled_audit:failed', { configId, error }); }); } } } /** * Determine if audit should run based on schedule */ shouldRunAudit(config, now) { const [hours, minutes] = config.schedule.time.split(':').map(Number); // Simple daily schedule check if (config.schedule.frequency === ScheduleFrequency.DAILY) { return now.getHours() === hours && now.getMinutes() === minutes; } // Add more sophisticated scheduling logic here return false; } /** * Create daily audit configuration */ async createDailyAuditConfig(environment) { const enabledChecks = Array.from(this.healthChecks.values()) .filter(check => check.enabled); return { id: `daily_audit_${environment}`, name: `Daily Audit - ${environment}`, type: AuditType.COMPREHENSIVE, schedule: { frequency: ScheduleFrequency.DAILY, time: '02:00', timezone: 'UTC', enabled: false // One-time execution }, checks: enabledChecks, thresholds: { overallHealth: 85, criticalIssues: 0, warningIssues: 5, performanceScore: 80, securityScore: 95, qualityScore: 80 }, notifications: { email: [], dashboard: true }, retention: { keepDays: 90, keepReports: 30, compressionEnabled: true }, enabled: true }; } /** * Create tasks for health checks */ async createCheckTasks(checks, auditId) { return checks.map(check => ({ id: `health_check_${check.id}_${auditId}`, name: `Health Check: ${check.name}`, type: TaskType.MONITORING, priority: check.critical ? Priority.HIGH : Priority.MEDIUM, estimatedDuration: 30000, // 30 seconds per check requiredResources: [ { type: ResourceType.CPU, name: 'cpu-cores', capacity: 1, exclusive: false } ], dependencies: [], agentId: 'maria-qa', sdlcPhase: SDLCPhase.TESTING, collisionRisk: CollisionRisk.LOW, metadata: { healthCheck: check, auditId } })); } /** * Process check results from task execution */ async processCheckResults(taskResults, checks) { const checkResults = []; for (const check of checks) { const taskId = `health_check_${check.id}`; const taskResult = Array.from(taskResults.entries()) .find(([id]) => id.includes(taskId)); if (taskResult) { const [, execution] = taskResult; const result = await this.convertTaskResultToCheckResult(check, execution); checkResults.push(result); } else { // Create error result for missing execution checkResults.push({ checkId: check.id, status: CheckStatus.ERROR, value: null, message: 'Check execution not found', timestamp: new Date(), duration: 0, metadata: { error: 'Task execution missing' } }); } } return checkResults; } /** * Convert task execution result to check result */ async convertTaskResultToCheckResult(check, execution) { if (execution.status === 'failed') { return { checkId: check.id, status: CheckStatus.ERROR, value: null, message: execution.error?.message || 'Check execution failed', timestamp: execution.startTime, duration: execution.endTime - execution.startTime, metadata: { execution } }; } // Execute the actual health check return await this.executeHealthCheck(check); } /** * Execute a single health check */ async executeHealthCheck(check) { const startTime = new Date(); try { let value; let message = ''; switch (check.type) { case CheckType.METRIC: case CheckType.SCRIPT: if (check.parameters.command) { // Execute command and parse result value = await this.executeCommand(check.parameters.command); message = `Command executed successfully: ${value}`; } break; case CheckType.API_CALL: if (check.parameters.url) { const response = await this.executeApiCall(check.parameters); value = response.responseTime; message = `API call completed with status ${response.status}`; } break; case CheckType.FILE_CHECK: if (check.parameters.script) { value = await this.executeCommand(check.parameters.script); message = `File check completed: ${value}`; } break; case CheckType.PROCESS_CHECK: if (check.parameters.command) { value = await this.executeCommand(check.parameters.command); message = `Process check completed: ${value}`; } break; default: throw new Error(`Unsupported check type: ${check.type}`); } // Evaluate against thresholds const status = this.evaluateCheckThresholds(value, check.thresholds); const endTime = new Date(); return { checkId: check.id, status, value, message, timestamp: startTime, duration: endTime.getTime() - startTime.getTime(), metadata: { check } }; } catch (error) { const endTime = new Date(); return { checkId: check.id, status: CheckStatus.ERROR, value: null, message: `Check failed: ${error.message}`, timestamp: startTime, duration: endTime.getTime() - startTime.getTime(), metadata: { error: error.message } }; } } /** * Execute system command */ async executeCommand(command) { // Simulate command execution // In real implementation, use child_process.exec or similar return Math.random() * 100; } /** * Execute API call */ async executeApiCall(parameters) { const startTime = Date.now(); try { // Simulate API call const responseTime = Math.random() * 2000 + 100; return { status: 200, responseTime, success: true }; } catch (error) { return { status: 500, responseTime: Date.now() - startTime, success: false, error: error.message }; } } /** * Evaluate check value against thresholds */ evaluateCheckThresholds(value, thresholds) { if (value === null || value === undefined) { return CheckStatus.ERROR; } const numValue = typeof value === 'number' ? value : parseFloat(value); if (isNaN(numValue)) { return CheckStatus.ERROR; } const { operator, critical, warning } = thresholds; // Check critical threshold first if (this.compareValues(numValue, critical.value, operator)) { return CheckStatus.FAIL; } // Check warning threshold if (this.compareValues(numValue, warning.value, operator)) { return CheckStatus.WARNING; } return CheckStatus.PASS; } /** * Compare values based on operator */ compareValues(actual, threshold, operator) { switch (operator) { case ThresholdOperator.GREATER_THAN: return actual > threshold; case ThresholdOperator.LESS_THAN: return actual < threshold; case ThresholdOperator.GREATER_EQUAL: return actual >= threshold; case ThresholdOperator.LESS_EQUAL: return actual <= threshold; case ThresholdOperator.EQUAL: return actual === threshold; case ThresholdOperator.NOT_EQUAL: return actual !== threshold; default: return false; } } /** * Calculate audit scores */ calculateAuditScores(checkResults) { const categoryScores = new Map(); // Initialize categories for (const category of Object.values(CheckCategory)) { categoryScores.set(category, { total: 0, weight: 0 }); } // Calculate weighted scores by category for (const result of checkResults) { const check = this.healthChecks.get(result.checkId); if (!check) continue; const score = this.getCheckScore(result.status); const category = check.category; const weight = check.weight; const current = categoryScores.get(category) || { total: 0, weight: 0 }; current.total += score * weight; current.weight += weight; categoryScores.set(category, current); } // Calculate final scores const scores = { performance: this.calculateCategoryScore(categoryScores, CheckCategory.PERFORMANCE), security: this.calculateCategoryScore(categoryScores, CheckCategory.SECURITY), quality: this.calculateCategoryScore(categoryScores, CheckCategory.QUALITY), reliability: this.calculateCategoryScore(categoryScores, CheckCategory.SYSTEM), compliance: this.calculateCategoryScore(categoryScores, CheckCategory.COMPLIANCE), infrastructure: this.calculateCategoryScore(categoryScores, CheckCategory.INFRASTRUCTURE) }; return scores; } /** * Get numeric score for check status */ getCheckScore(status) { switch (status) { case CheckStatus.PASS: return 100; case CheckStatus.WARNING: return 70; case CheckStatus.FAIL: return 30; case CheckStatus.ERROR: return 0; case CheckStatus.SKIP: return 50; default: return 0; } } /** * Calculate category score */ calculateCategoryScore(categoryScores, category) { const categoryData = categoryScores.get(category); if (!categoryData || categoryData.weight === 0) { return 100; // Default to perfect score if no checks in category } return Math.round(categoryData.total / categoryData.weight); } /** * Calculate overall health score */ calculateOverallHealth(scores, checkResults) { const weights = { security: 0.25, reliability: 0.20, performance: 0.20, quality: 0.15, infrastructure: 0.10, compliance: 0.10 }; const weightedScore = scores.security * weights.security + scores.reliability * weights.reliability + scores.performance * weights.performance + scores.quality * weights.quality + scores.infrastructure * weights.infrastructure + scores.compliance * weights.compliance; // Apply penalty for critical failures const criticalFailures = checkResults.filter(r => r.status === CheckStatus.FAIL && this.healthChecks.get(r.checkId)?.critical).length; const penalty = criticalFailures * 10; // 10 points per critical failure return Math.max(0, Math.round(weightedScore - penalty)); } /** * Identify issues from check results */ identifyIssues(checkResults, thresholds) { const issues = []; for (const result of checkResults) { if (result.status === CheckStatus.FAIL || result.status === CheckStatus.WARNING) { const check = this.healthChecks.get(result.checkId); if (!check) continue; const severity = result.status === CheckStatus.FAIL ? (check.critical ? IssueSeverity.CRITICAL : IssueSeverity.HIGH) : IssueSeverity.MEDIUM; issues.push({ id: `issue_${result.checkId}_${Date.now()}`, severity, category: this.mapCheckCategoryToIssueCategory(check.category), title: `${check.name} ${result.status === CheckStatus.FAIL ? 'Failed' : 'Warning'}`, description: result.message, impact: this.determineImpactLevel(severity, check.critical), urgency: this.determineUrgencyLevel(severity, check.critical), source: check.id, checkId: check.id, recommendation: this.generateIssueRecommendation(check, result), evidence: [result], firstSeen: result.timestamp, lastSeen: result.timestamp, occurrences: 1 }); } } return issues; } /** * Generate recommendations based on issues and results */ async generateRecommendations(issues, checkResults) { const recommendations = []; // Group issues by category const issuesByCategory = new Map(); for (const issue of issues) { const existing = issuesByCategory.get(issue.category) || []; existing.push(issue); issuesByCategory.set(issue.category, existing); } // Generate recommendations for each category for (const [category, categoryIssues] of issuesByCategory) { const recommendation = this.generateCategoryRecommendation(category, categoryIssues); if (recommendation) { recommendations.push(recommendation); } } return recommendations; } /** * Generate category-specific recommendation */ generateCategoryRecommendation(category, issues) { const criticalIssues = issues.filter(i => i.severity >= IssueSeverity.HIGH); const priority = criticalIssues.length > 0 ? Priority.HIGH : Priority.MEDIUM; switch (category) { case IssueCategory.PERFORMANCE: return { id: `rec_perf_${Date.now()}`, priority, category: RecommendationCategory.PERFORMANCE_OPTIMIZATION, title: 'Optimize System Performance', description: 'Address performance bottlenecks identified in the audit', implementation: 'Review and optimize slow operations, consider caching, database optimization', estimatedImpact: ImpactLevel.HIGH, estimatedEffort: EffortLevel.MEDIUM, relatedIssues: issues.map(i => i.id) }; case IssueCategory.SECURITY: return { id: `rec_sec_${Date.now()}`, priority: Priority.CRITICAL, category: RecommendationCategory.SECURITY_ENHANCEMENT, title: 'Address Security Vulnerabilities', description: 'Critical security issues require immediate attention', implementation: 'Update dependencies, fix file permissions, implement security patches', estimatedImpact: ImpactLevel.CRITICAL, estimatedEffort: EffortLevel.HIGH, relatedIssues: issues.map(i => i.id) }; case IssueCategory.QUALITY: return { id: `rec_qual_${Date.now()}`, priority, category: RecommendationCategory.QUALITY_IMPROVEMENT, title: 'Improve Code Quality', description: 'Address code quality issues and increase test coverage', implementation: 'Increase test coverage, fix TypeScript errors, improve code standards', estimatedImpact: ImpactLevel.MEDIUM, estimatedEffort: EffortLevel.MEDIUM, relatedIssues: issues.map(i => i.id) }; default: return null; } } /** * Perform trend analysis */ async performTrendAnalysis(scores, issues) { // Get historical data for comparison const historicalResults = this.auditHistory.slice(-5); // Last 5 audits if (historicalResults.length === 0) { return { performanceTrend: TrendDirection.UNKNOWN, securityTrend: TrendDirection.UNKNOWN, qualityTrend: TrendDirection.UNKNOWN, reliabilityTrend: TrendDirection.UNKNOWN, issuesTrend: TrendDirection.UNKNOWN, historicalComparison: { previousPeriod: { totalChecks: 0, passedChecks: 0, warningChecks: 0, failedChecks: 0, errorChecks: 0, criticalIssues: 0, warningIssues: 0, overallScore: 0, executionTime: 0 }, changePercentage: {}, significantChanges: [] } }; } const previous = historicalResults[historicalResults.length - 1]; return { performanceTrend: this.calculateTrend(scores.performance, previous.scores.performance), securityTrend: this.calculateTrend(scores.security, previous.scores.security), qualityTrend: this.calculateTrend(scores.quality, previous.scores.quality), reliabilityTrend: this.calculateTrend(scores.reliability, previous.scores.reliability), issuesTrend: this.calculateTrend(issues.filter(i => i.severity >= IssueSeverity.HIGH).length, previous.issues.filter(i => i.severity >= IssueSeverity.HIGH).length, true // Inverted - fewer issues is better ), historicalComparison: { previousPeriod: previous.summary, changePercentage: { performance: this.calculatePercentageChange(scores.performance, previous.scores.performance), security: this.calculatePercentageChange(scores.security, previous.scores.security), quality: this.calculatePercentageChange(scores.quality, previous.scores.quality) }, significantChanges: this.identifySignificantChanges(scores, previous.scores) } }; } /** * Calculate trend direction */ calculateTrend(current, previous, inverted = false) { const threshold = 5; // 5% threshold for significant change const change = ((current - previous) / previous) * 100; if (Math.abs(change) < threshold) { return TrendDirection.STABLE; } const improving = inverted ? change < 0 : change > 0; return improving ? TrendDirection.IMPROVING : TrendDirection.DECLINING; } /** * Calculate percentage change */ calculatePercentageChange(current, previous) { if (previous === 0) return current > 0 ? 100 : 0; return Math.round(((current - previous) / previous) * 100); } /** * Identify significant changes */ identifySignificantChanges(current, previous) { const changes = []; const threshold = 10; // 10% threshold for significant change const scores = [ { name: 'Performance', current: current.performance, previous: previous.performance }, { name: 'Security', current: current.security, previous: previous.security }, { name: 'Quality', current: current.quality, previous: previous.quality }, { name: 'Reliability', current: current.reliability, previous: previous.reliability } ]; for (const score of scores) { const change = this.calculatePercentageChange(score.current, score.previous); if (Math.abs(change) >= threshold) { const direction = change > 0 ? 'improved' : 'declined'; changes.push(`${score.name} ${direction} by ${Math.abs(change)}%`); } } return changes; } /** * Create audit summary */ createAuditSummary(checkResults) { const statusCounts = checkResults.reduce((acc, result) => { acc[result.status]++; return acc; }, { [CheckStatus.PASS]: 0, [CheckStatus.WARNING]: 0, [CheckStatus.FAIL]: 0, [CheckStatus.ERROR]: 0, [CheckStatus.SKIP]: 0 }); return { totalChecks: checkResults.length, passedChecks: statusCounts[CheckStatus.PASS], warningChecks: statusCounts[CheckStatus.WARNING], failedChecks: statusCounts[CheckStatus.FAIL], errorChecks: statusCounts[CheckStatus.ERROR], criticalIssues: checkResults.filter(r => r.status === CheckStatus.FAIL && this.healthChecks.get(r.checkId)?.critical).length, warningIssues: statusCounts[CheckStatus.WARNING], overallScore: this.calculateOverallHealth(this.calculateAuditScores(checkResults), checkResults), executionTime: checkResults.reduce((sum, r) => sum + r.duration, 0) }; } /** * Determine audit status */ determineAuditStatus(overallHealth, issues) { const criticalIssues = issues.filter(i => i.severity >= IssueSeverity.CRITICAL).length; const highIssues = issues.filter(i => i.severity >= IssueSeverity.HIGH).length; if (criticalIssues > 0) return AuditStatus.FAILURE; if (highIssues > 3 || overallHealth < 70) return AuditStatus.WARNING; return AuditStatus.SUCCESS; } /** * Process audit notifications */ async processAuditNotifications(result) { // Determine notification severity const severity = this.getNotificationSeverity(result.status); // Send notifications based on configuration this.emit('notification:audit_complete', { result, severity, message: this.generateNotificationMessage(result) }); } /** * Get notification severity from audit status */ getNotificationSeverity(status) { switch (status) { case AuditStatus.FAILURE: return NotificationSeverity.CRITICAL; case AuditStatus.WARNING: return NotificationSeverity.WARNING; case AuditStatus.SUCCESS: return NotificationSeverity.INFO; default: return NotificationSeverity.INFO; } } /** * Generate notification message */ generateNotificationMessage(result) { const { status, overallHealth, issues, summary } = result; const criticalIssues = issues.filter(i => i.severity >= IssueSeverity.CRITICAL).length; const warningIssues = issues.filter(i => i.severity === IssueSeverity.MEDIUM).length; return `Daily Audit Complete - Status: ${status.toUpperCase()} Overall Health: ${overallHealth}% Critical Issues: ${criticalIssues} Warning Issues: ${warningIssues} Checks Passed: ${summary.passedChecks}/${summary.totalChecks}`; } /** * Cleanup old audit data */ async cleanupOldAudits() { const retentionDays = 90; // Keep 90 days of audit history const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - retentionDays); this.auditHistory = this.auditHistory.filter(result => result.startTime >= cutoffDate); // Also cleanup active audits map for (const [id, result] of this.activeAudits) { if (result.startTime < cutoffDate) { this.activeAudits.delete(id); } } } // Helper methods for mapping and determination mapCheckCategoryToIssueCategory(checkCategory) { switch (checkCategory) { case CheckCategory.SECURITY: return IssueCategory.SECURITY; case CheckCategory.PERFORMANCE: return IssueCategory.PERFORMANCE; case CheckCategory.QUALITY: return IssueCategory.QUALITY; case CheckCategory.COMPLIANCE: return IssueCategory.COMPLIANCE; case CheckCategory.INFRASTRUCTURE: return IssueCategory.INFRASTRUCTURE; default: return IssueCategory.CONFIGURATION; } } determineImpactLevel(severity, critical) { if (critical && severity >= IssueSeverity.HIGH) return ImpactLevel.CRITICAL; if (severity >= IssueSeverity.CRITICAL) return ImpactLevel.HIGH; if (severity >= IssueSeverity.HIGH) return ImpactLevel.MEDIUM; return ImpactLevel.LOW; } determineUrgencyLevel(severity, critical) { if (critical && severity >= IssueSeverity.CRITICAL) return UrgencyLevel.IMMEDIATE; if (severity >= IssueSeverity.CRITICAL) return UrgencyLevel.CRITICAL; if (severity >= IssueSeverity.HIGH) return UrgencyLevel.HIGH; return UrgencyLevel.MEDIUM; } generateIssueRecommendation(check, result) { switch (check.category) { case CheckCategory.SYSTEM: return `Investigate and optimize ${check.name.toLowerCase()} usage`; case CheckCategory.SECURITY: return `Address security vulnerability in ${check.name.toLowerCase()}`; case CheckCategory.PERFORMANCE: return `Optimize ${check.name.toLowerCase()} to improve performance`; case CheckCategory.QUALITY: return `Improve ${check.name.toLowerCase()} to meet quality