@tamyla/clodo-framework 3.1.8 → 3.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/bin/database/enterprise-db-manager.js +4 -4
  3. package/bin/security/security-cli.js +2 -2
  4. package/bin/service-management/create-service.js +2 -2
  5. package/bin/service-management/init-service.js +2 -2
  6. package/bin/shared/cloudflare/domain-manager.js +1 -1
  7. package/bin/shared/config/index.js +1 -1
  8. package/bin/shared/deployment/index.js +2 -2
  9. package/dist/bin/clodo-service-old.js +868 -0
  10. package/dist/bin/clodo-service-test.js +10 -0
  11. package/dist/bin/clodo-service.js +62 -0
  12. package/dist/bin/commands/assess.js +76 -0
  13. package/dist/bin/commands/create.js +56 -0
  14. package/dist/bin/commands/deploy.js +196 -0
  15. package/dist/bin/commands/diagnose.js +70 -0
  16. package/dist/bin/commands/helpers.js +138 -0
  17. package/dist/bin/commands/update.js +55 -0
  18. package/dist/bin/commands/validate.js +26 -0
  19. package/dist/bin/database/deployment-db-manager.js +423 -0
  20. package/dist/bin/database/enterprise-db-manager.js +457 -0
  21. package/dist/bin/database/wrangler-d1-manager.js +685 -0
  22. package/dist/bin/deployment/enterprise-deploy.js +877 -0
  23. package/dist/bin/deployment/master-deploy.js +1376 -0
  24. package/dist/bin/deployment/modular-enterprise-deploy.js +466 -0
  25. package/dist/bin/deployment/modules/DeploymentConfiguration.js +395 -0
  26. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +492 -0
  27. package/dist/bin/deployment/modules/EnvironmentManager.js +517 -0
  28. package/dist/bin/deployment/modules/MonitoringIntegration.js +560 -0
  29. package/dist/bin/deployment/modules/ValidationManager.js +342 -0
  30. package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  31. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +401 -0
  32. package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  33. package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  34. package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  35. package/dist/bin/deployment/test-interactive-utils.js +66 -0
  36. package/dist/bin/portfolio/portfolio-manager.js +487 -0
  37. package/dist/bin/security/security-cli.js +108 -0
  38. package/dist/bin/service-management/create-service.js +122 -0
  39. package/dist/bin/service-management/init-service.js +79 -0
  40. package/dist/{shared → bin/shared}/cloudflare/domain-manager.js +1 -1
  41. package/dist/{shared → bin/shared}/config/index.js +1 -1
  42. package/dist/bin/shared/deployment/index.js +10 -0
  43. package/dist/deployment/index.js +10 -9
  44. package/dist/deployment/rollback-manager.js +21 -508
  45. package/package.json +7 -7
  46. package/dist/shared/deployment/auditor.js +0 -986
  47. package/dist/shared/deployment/index.js +0 -10
  48. package/dist/shared/deployment/validator.js +0 -670
  49. package/dist/shared/production-tester/api-tester.js +0 -80
  50. package/dist/shared/production-tester/auth-tester.js +0 -129
  51. package/dist/shared/production-tester/core.js +0 -217
  52. package/dist/shared/production-tester/database-tester.js +0 -105
  53. package/dist/shared/production-tester/index.js +0 -74
  54. package/dist/shared/production-tester/load-tester.js +0 -120
  55. package/dist/shared/production-tester/performance-tester.js +0 -105
  56. /package/dist/{shared → bin/shared}/cloudflare/domain-discovery.js +0 -0
  57. /package/dist/{shared → bin/shared}/cloudflare/index.js +0 -0
  58. /package/dist/{shared → bin/shared}/cloudflare/ops.js +0 -0
  59. /package/dist/{shared → bin/shared}/config/ConfigurationManager.js +0 -0
  60. /package/dist/{shared → bin/shared}/config/cache.js +0 -0
  61. /package/dist/{shared → bin/shared}/config/command-config-manager.js +0 -0
  62. /package/dist/{shared → bin/shared}/config/manager.js +0 -0
  63. /package/dist/{shared → bin/shared}/database/connection-manager.js +0 -0
  64. /package/dist/{shared → bin/shared}/database/index.js +0 -0
  65. /package/dist/{shared → bin/shared}/database/orchestrator.js +0 -0
  66. /package/dist/{deployment → bin/shared/deployment}/auditor.js +0 -0
  67. /package/dist/{shared → bin/shared}/deployment/rollback-manager.js +0 -0
  68. /package/dist/{deployment → bin/shared/deployment}/validator.js +0 -0
  69. /package/dist/{shared → bin/shared}/index.js +0 -0
  70. /package/dist/{shared → bin/shared}/logging/Logger.js +0 -0
  71. /package/dist/{shared → bin/shared}/monitoring/health-checker.js +0 -0
  72. /package/dist/{shared → bin/shared}/monitoring/index.js +0 -0
  73. /package/dist/{shared → bin/shared}/monitoring/memory-manager.js +0 -0
  74. /package/dist/{shared → bin/shared}/monitoring/production-monitor.js +0 -0
  75. /package/dist/{deployment/testers → bin/shared/production-tester}/api-tester.js +0 -0
  76. /package/dist/{deployment/testers → bin/shared/production-tester}/auth-tester.js +0 -0
  77. /package/dist/{deployment/testers → bin/shared/production-tester}/core.js +0 -0
  78. /package/dist/{deployment/testers → bin/shared/production-tester}/database-tester.js +0 -0
  79. /package/dist/{deployment/testers → bin/shared/production-tester}/index.js +0 -0
  80. /package/dist/{deployment/testers → bin/shared/production-tester}/load-tester.js +0 -0
  81. /package/dist/{deployment/testers → bin/shared/production-tester}/performance-tester.js +0 -0
  82. /package/dist/{shared → bin/shared}/security/api-token-manager.js +0 -0
  83. /package/dist/{shared → bin/shared}/security/index.js +0 -0
  84. /package/dist/{shared → bin/shared}/security/secret-generator.js +0 -0
  85. /package/dist/{shared → bin/shared}/security/secure-token-manager.js +0 -0
  86. /package/dist/{shared → bin/shared}/utils/ErrorHandler.js +0 -0
  87. /package/dist/{shared → bin/shared}/utils/error-recovery.js +0 -0
  88. /package/dist/{shared → bin/shared}/utils/file-manager.js +0 -0
  89. /package/dist/{shared → bin/shared}/utils/formatters.js +0 -0
  90. /package/dist/{shared → bin/shared}/utils/graceful-shutdown-manager.js +0 -0
  91. /package/dist/{shared → bin/shared}/utils/index.js +0 -0
  92. /package/dist/{shared → bin/shared}/utils/interactive-prompts.js +0 -0
  93. /package/dist/{shared → bin/shared}/utils/interactive-utils.js +0 -0
  94. /package/dist/{shared → bin/shared}/utils/rate-limiter.js +0 -0
  95. /package/dist/{shared → bin/shared}/validation/ValidationRegistry.js +0 -0
@@ -1,986 +0,0 @@
1
- /**
2
- * Enterprise Deployment Audit System
3
- *
4
- * Comprehensive audit and logging system for enterprise deployments with:
5
- * - Structured deployment logging with multiple output formats
6
- * - Comprehensive audit trails with compliance features
7
- * - Deployment history tracking and analytics
8
- * - Backup and recovery logging
9
- * - Performance metrics and reporting
10
- * - Cross-environment audit coordination
11
- * - Real-time monitoring and alerting
12
- * - Compliance reporting and retention policies
13
- * - Advanced search and filtering capabilities
14
- *
15
- * @module deployment-auditor
16
- * @version 2.0.0
17
- */
18
-
19
- import { existsSync, writeFileSync, appendFileSync, mkdirSync, readFileSync, readdirSync, statSync } from 'fs';
20
- import { join, dirname } from 'path';
21
- import { execSync } from 'child_process';
22
- import { logger } from '../logging/Logger.js';
23
- export class DeploymentAuditor {
24
- constructor(options = {}) {
25
- this.config = {
26
- // Audit configuration
27
- auditLevel: options.auditLevel || 'detailed',
28
- // minimal, standard, detailed, verbose
29
- retentionDays: options.retentionDays || 90,
30
- maxLogSize: options.maxLogSize || 100 * 1024 * 1024,
31
- // 100MB
32
-
33
- // Output formats
34
- formats: options.formats || ['json', 'csv', 'plain'],
35
- includeMetrics: options.includeMetrics !== false,
36
- includeBackups: options.includeBackups !== false,
37
- // Paths
38
- auditDir: options.auditDir || 'audit-logs',
39
- backupDir: options.backupDir || 'audit-backups',
40
- reportsDir: options.reportsDir || 'audit-reports',
41
- // Real-time options
42
- realTimeAlerts: options.realTimeAlerts || false,
43
- alertWebhook: options.alertWebhook || null,
44
- // Compliance
45
- complianceMode: options.complianceMode || false,
46
- encryptLogs: options.encryptLogs || false,
47
- digitallySigned: options.digitallySigned || false,
48
- // Environment tracking
49
- environments: options.environments || ['development', 'staging', 'production'],
50
- crossEnvironmentTracking: options.crossEnvironmentTracking !== false
51
- };
52
-
53
- // Audit state
54
- this.currentSession = {
55
- sessionId: this.generateSessionId(),
56
- startTime: new Date(),
57
- deployments: new Map(),
58
- events: [],
59
- metrics: {
60
- totalEvents: 0,
61
- errorCount: 0,
62
- warningCount: 0,
63
- deploymentCount: 0,
64
- rollbackCount: 0
65
- }
66
- };
67
-
68
- // Event types registry
69
- this.eventTypes = {
70
- DEPLOYMENT_START: {
71
- level: 'info',
72
- category: 'deployment',
73
- retention: 'long'
74
- },
75
- DEPLOYMENT_END: {
76
- level: 'info',
77
- category: 'deployment',
78
- retention: 'long'
79
- },
80
- DEPLOYMENT_ERROR: {
81
- level: 'error',
82
- category: 'deployment',
83
- retention: 'permanent'
84
- },
85
- PHASE_START: {
86
- level: 'debug',
87
- category: 'phase',
88
- retention: 'standard'
89
- },
90
- PHASE_END: {
91
- level: 'debug',
92
- category: 'phase',
93
- retention: 'standard'
94
- },
95
- ROLLBACK_START: {
96
- level: 'warn',
97
- category: 'rollback',
98
- retention: 'long'
99
- },
100
- ROLLBACK_END: {
101
- level: 'warn',
102
- category: 'rollback',
103
- retention: 'long'
104
- },
105
- SECRET_GENERATED: {
106
- level: 'info',
107
- category: 'security',
108
- retention: 'long'
109
- },
110
- SECRET_DEPLOYED: {
111
- level: 'info',
112
- category: 'security',
113
- retention: 'long'
114
- },
115
- DATABASE_MIGRATION: {
116
- level: 'info',
117
- category: 'database',
118
- retention: 'long'
119
- },
120
- VALIDATION_ERROR: {
121
- level: 'error',
122
- category: 'validation',
123
- retention: 'long'
124
- },
125
- PERFORMANCE_METRIC: {
126
- level: 'info',
127
- category: 'performance',
128
- retention: 'standard'
129
- },
130
- SECURITY_EVENT: {
131
- level: 'warn',
132
- category: 'security',
133
- retention: 'permanent'
134
- },
135
- COMPLIANCE_VIOLATION: {
136
- level: 'error',
137
- category: 'compliance',
138
- retention: 'permanent'
139
- },
140
- AUDIT_EVENT: {
141
- level: 'info',
142
- category: 'audit',
143
- retention: 'permanent'
144
- }
145
- };
146
-
147
- // Initialize audit system
148
- this.initializeAuditSystem();
149
- this.logAuditEvent('AUDIT_SYSTEM_INITIALIZED', 'SYSTEM', {
150
- config: this.config,
151
- sessionId: this.currentSession.sessionId
152
- });
153
- console.log('📋 Deployment Audit System initialized');
154
- if (this.config.auditLevel === 'verbose') {
155
- console.log(` 📊 Session ID: ${this.currentSession.sessionId}`);
156
- console.log(` 🔍 Audit Level: ${this.config.auditLevel}`);
157
- console.log(` 💾 Formats: ${this.config.formats.join(', ')}`);
158
- console.log(` 📁 Audit Directory: ${this.config.auditDir}`);
159
- }
160
- }
161
-
162
- /**
163
- * Initialize audit system directories and files
164
- */
165
- initializeAuditSystem() {
166
- this.paths = {
167
- audit: this.config.auditDir,
168
- backup: this.config.backupDir,
169
- reports: this.config.reportsDir,
170
- daily: join(this.config.auditDir, 'daily'),
171
- deployments: join(this.config.auditDir, 'deployments'),
172
- security: join(this.config.auditDir, 'security'),
173
- performance: join(this.config.auditDir, 'performance'),
174
- compliance: join(this.config.auditDir, 'compliance')
175
- };
176
-
177
- // Create directory structure
178
- Object.values(this.paths).forEach(path => {
179
- if (!existsSync(path)) {
180
- mkdirSync(path, {
181
- recursive: true
182
- });
183
- }
184
- });
185
-
186
- // Initialize log files
187
- this.logFiles = {
188
- main: join(this.paths.audit, 'deployment-audit.log'),
189
- errors: join(this.paths.audit, 'deployment-errors.log'),
190
- security: join(this.paths.security, 'security-audit.log'),
191
- performance: join(this.paths.performance, 'performance-audit.log'),
192
- compliance: join(this.paths.compliance, 'compliance-audit.log'),
193
- daily: join(this.paths.daily, `audit-${this.getCurrentDateString()}.log`)
194
- };
195
-
196
- // Initialize session log
197
- this.sessionLogFile = join(this.paths.deployments, `session-${this.currentSession.sessionId}.log`);
198
- }
199
-
200
- /**
201
- * Generate unique session ID
202
- * @returns {string} Session ID
203
- */
204
- generateSessionId() {
205
- const timestamp = Date.now().toString(36);
206
- const random = Math.random().toString(36).substr(2, 9);
207
- return `audit_${timestamp}_${random}`;
208
- }
209
-
210
- /**
211
- * Get current date string for file naming
212
- * @returns {string} Date string
213
- */
214
- getCurrentDateString() {
215
- return new Date().toISOString().split('T')[0];
216
- }
217
-
218
- /**
219
- * Start deployment audit session
220
- * @param {string} deploymentId - Deployment identifier
221
- * @param {string} domain - Domain being deployed
222
- * @param {Object} config - Deployment configuration
223
- * @returns {Object} Deployment audit context
224
- */
225
- startDeploymentAudit(deploymentId, domain, config = {}) {
226
- const deploymentContext = {
227
- deploymentId,
228
- domain,
229
- config,
230
- startTime: new Date(),
231
- phases: [],
232
- events: [],
233
- metrics: {
234
- phaseCount: 0,
235
- errorCount: 0,
236
- warningCount: 0,
237
- duration: 0
238
- },
239
- rollbacks: [],
240
- status: 'in-progress'
241
- };
242
- this.currentSession.deployments.set(deploymentId, deploymentContext);
243
- this.currentSession.metrics.deploymentCount++;
244
- this.logAuditEvent('DEPLOYMENT_START', domain, {
245
- deploymentId,
246
- config,
247
- sessionId: this.currentSession.sessionId,
248
- environment: config.environment || 'unknown'
249
- });
250
- console.log(`📋 Deployment audit started: ${deploymentId}`);
251
- if (this.config.auditLevel === 'verbose') {
252
- console.log(` 🌐 Domain: ${domain}`);
253
- console.log(` 🌍 Environment: ${config.environment || 'unknown'}`);
254
- }
255
- return deploymentContext;
256
- }
257
-
258
- /**
259
- * End deployment audit session
260
- * @param {string} deploymentId - Deployment identifier
261
- * @param {string} status - Final deployment status
262
- * @param {Object} summary - Deployment summary
263
- */
264
- endDeploymentAudit(deploymentId, status, summary = {}) {
265
- const deployment = this.currentSession.deployments.get(deploymentId);
266
- if (!deployment) {
267
- this.logAuditEvent('AUDIT_ERROR', 'SYSTEM', {
268
- error: `Deployment not found: ${deploymentId}`,
269
- deploymentId
270
- });
271
- return;
272
- }
273
- deployment.endTime = new Date();
274
- deployment.duration = (deployment.endTime - deployment.startTime) / 1000;
275
- deployment.status = status;
276
- deployment.summary = summary;
277
- this.logAuditEvent('DEPLOYMENT_END', deployment.domain, {
278
- deploymentId,
279
- status,
280
- duration: deployment.duration,
281
- phaseCount: deployment.phases.length,
282
- errorCount: deployment.metrics.errorCount,
283
- summary
284
- });
285
- console.log(`📋 Deployment audit completed: ${deploymentId} (${status})`);
286
- if (this.config.auditLevel !== 'minimal') {
287
- console.log(` ⏱️ Duration: ${deployment.duration.toFixed(2)}s`);
288
- console.log(` 📊 Phases: ${deployment.phases.length}`);
289
- console.log(` ❌ Errors: ${deployment.metrics.errorCount}`);
290
- }
291
-
292
- // Generate deployment report
293
- this.generateDeploymentReport(deploymentId);
294
- }
295
-
296
- /**
297
- * Log deployment phase start/end
298
- * @param {string} deploymentId - Deployment identifier
299
- * @param {string} phaseName - Phase name
300
- * @param {string} action - 'start' or 'end'
301
- * @param {Object} details - Phase details
302
- */
303
- logPhase(deploymentId, phaseName, action, details = {}) {
304
- const deployment = this.currentSession.deployments.get(deploymentId);
305
- if (!deployment) {
306
- logger.warn('Deployment not found for phase logging', {
307
- deploymentId
308
- });
309
- return;
310
- }
311
- const phaseEvent = {
312
- phase: phaseName,
313
- action,
314
- timestamp: new Date(),
315
- details
316
- };
317
- deployment.phases.push(phaseEvent);
318
- if (action === 'start') {
319
- deployment.metrics.phaseCount++;
320
- }
321
- this.logAuditEvent(`PHASE_${action.toUpperCase()}`, deployment.domain, {
322
- deploymentId,
323
- phase: phaseName,
324
- phaseNumber: deployment.phases.filter(p => p.action === 'start').length,
325
- details
326
- });
327
- if (this.config.auditLevel === 'verbose') {
328
- console.log(` 📋 Phase ${action}: ${phaseName}`);
329
- }
330
- }
331
-
332
- /**
333
- * Log deployment error with context
334
- * @param {string} deploymentId - Deployment identifier
335
- * @param {Error|string} error - Error object or message
336
- * @param {Object} context - Additional context
337
- */
338
- logError(deploymentId, error, context = {}) {
339
- const deployment = this.currentSession.deployments.get(deploymentId);
340
- if (deployment) {
341
- deployment.metrics.errorCount++;
342
- }
343
- this.currentSession.metrics.errorCount++;
344
- const errorDetails = {
345
- deploymentId,
346
- error: error instanceof Error ? {
347
- message: error.message,
348
- stack: error.stack,
349
- name: error.name
350
- } : {
351
- message: error.toString()
352
- },
353
- context,
354
- timestamp: new Date()
355
- };
356
- this.logAuditEvent('DEPLOYMENT_ERROR', deployment?.domain || 'UNKNOWN', errorDetails);
357
-
358
- // Write to error log
359
- this.writeToLogFile(this.logFiles.errors, {
360
- type: 'error',
361
- timestamp: new Date(),
362
- deploymentId,
363
- error: errorDetails.error,
364
- context
365
- });
366
- logger.error('Deployment error logged', {
367
- deploymentId
368
- });
369
- }
370
-
371
- /**
372
- * Log security-related events
373
- * @param {string} deploymentId - Deployment identifier
374
- * @param {string} eventType - Security event type
375
- * @param {Object} details - Security event details
376
- */
377
- logSecurityEvent(deploymentId, eventType, details = {}) {
378
- const securityEvent = {
379
- deploymentId,
380
- eventType,
381
- details,
382
- timestamp: new Date(),
383
- severity: details.severity || 'medium'
384
- };
385
- this.logAuditEvent('SECURITY_EVENT', details.domain || 'SYSTEM', securityEvent);
386
-
387
- // Write to security log
388
- this.writeToLogFile(this.logFiles.security, securityEvent);
389
- if (this.config.auditLevel !== 'minimal') {
390
- console.log(`🔐 Security event: ${eventType} (${securityEvent.severity})`);
391
- }
392
-
393
- // Alert on high severity events
394
- if (securityEvent.severity === 'high' && this.config.realTimeAlerts) {
395
- this.sendSecurityAlert(securityEvent);
396
- }
397
- }
398
-
399
- /**
400
- * Log performance metrics
401
- * @param {string} deploymentId - Deployment identifier
402
- * @param {string} metricName - Metric name
403
- * @param {number} value - Metric value
404
- * @param {Object} metadata - Additional metric metadata
405
- */
406
- logPerformanceMetric(deploymentId, metricName, value, metadata = {}) {
407
- const performanceEvent = {
408
- deploymentId,
409
- metric: metricName,
410
- value,
411
- metadata,
412
- timestamp: new Date()
413
- };
414
- this.logAuditEvent('PERFORMANCE_METRIC', metadata.domain || 'SYSTEM', performanceEvent);
415
- if (this.config.includeMetrics) {
416
- this.writeToLogFile(this.logFiles.performance, performanceEvent);
417
- }
418
- if (this.config.auditLevel === 'verbose') {
419
- console.log(`⚡ Performance: ${metricName} = ${value}${metadata.unit || ''}`);
420
- }
421
- }
422
-
423
- /**
424
- * Log rollback operations
425
- * @param {string} deploymentId - Deployment identifier
426
- * @param {string} action - Rollback action ('start' or 'end')
427
- * @param {Object} rollbackData - Rollback details
428
- */
429
- logRollback(deploymentId, action, rollbackData = {}) {
430
- const deployment = this.currentSession.deployments.get(deploymentId);
431
- if (deployment && action === 'start') {
432
- deployment.rollbacks.push({
433
- startTime: new Date(),
434
- actions: rollbackData.actions || [],
435
- reason: rollbackData.reason || 'deployment-failure'
436
- });
437
- }
438
- if (action === 'start') {
439
- this.currentSession.metrics.rollbackCount++;
440
- }
441
- this.logAuditEvent(`ROLLBACK_${action.toUpperCase()}`, deployment?.domain || 'SYSTEM', {
442
- deploymentId,
443
- rollbackData,
444
- timestamp: new Date()
445
- });
446
- console.log(`🔄 Rollback ${action}: ${deploymentId}`);
447
- }
448
-
449
- /**
450
- * Log general audit event
451
- * @param {string} eventType - Type of event
452
- * @param {string} domain - Domain context
453
- * @param {Object} details - Event details
454
- */
455
- logAuditEvent(eventType, domain, details = {}) {
456
- const eventConfig = this.eventTypes[eventType] || {
457
- level: 'info',
458
- category: 'general',
459
- retention: 'standard'
460
- };
461
- const auditEvent = {
462
- eventType,
463
- level: eventConfig.level,
464
- category: eventConfig.category,
465
- retention: eventConfig.retention,
466
- domain,
467
- details,
468
- timestamp: new Date(),
469
- sessionId: this.currentSession.sessionId,
470
- sequence: this.currentSession.metrics.totalEvents++
471
- };
472
-
473
- // Add to session events
474
- this.currentSession.events.push(auditEvent);
475
-
476
- // Write to main audit log
477
- this.writeToLogFile(this.logFiles.main, auditEvent);
478
-
479
- // Write to daily log
480
- this.writeToLogFile(this.logFiles.daily, auditEvent);
481
-
482
- // Write to session log
483
- this.writeToLogFile(this.sessionLogFile, auditEvent);
484
-
485
- // Category-specific logging
486
- if (eventConfig.category === 'security') {
487
- this.writeToLogFile(this.logFiles.security, auditEvent);
488
- } else if (eventConfig.category === 'compliance') {
489
- this.writeToLogFile(this.logFiles.compliance, auditEvent);
490
- }
491
-
492
- // Update metrics
493
- if (eventConfig.level === 'error') {
494
- this.currentSession.metrics.errorCount++;
495
- } else if (eventConfig.level === 'warn') {
496
- this.currentSession.metrics.warningCount++;
497
- }
498
-
499
- // Real-time processing
500
- if (this.config.realTimeAlerts && eventConfig.level === 'error') {
501
- this.sendAlert(auditEvent);
502
- }
503
- }
504
-
505
- /**
506
- * Write structured log entry to file
507
- * @param {string} logFile - Log file path
508
- * @param {Object} logEntry - Log entry object
509
- */
510
- writeToLogFile(logFile, logEntry) {
511
- try {
512
- // Ensure directory exists
513
- const dir = dirname(logFile);
514
- if (!existsSync(dir)) {
515
- mkdirSync(dir, {
516
- recursive: true
517
- });
518
- }
519
-
520
- // Check file size and rotate if needed
521
- if (existsSync(logFile)) {
522
- const stats = statSync(logFile);
523
- if (stats.size > this.config.maxLogSize) {
524
- this.rotateLogFile(logFile);
525
- }
526
- }
527
-
528
- // Write log entry based on format
529
- if (this.config.formats.includes('json')) {
530
- appendFileSync(logFile, JSON.stringify(logEntry) + '\n');
531
- }
532
- if (this.config.formats.includes('plain')) {
533
- const plainEntry = `[${logEntry.timestamp?.toISOString() || new Date().toISOString()}] ${logEntry.eventType || 'LOG'}: ${JSON.stringify(logEntry.details || logEntry)}`;
534
- const plainFile = logFile.replace('.log', '.txt');
535
- appendFileSync(plainFile, plainEntry + '\n');
536
- }
537
- if (this.config.formats.includes('csv')) {
538
- const csvFile = logFile.replace('.log', '.csv');
539
- const csvHeaders = 'timestamp,eventType,level,category,domain,details\n';
540
- if (!existsSync(csvFile)) {
541
- writeFileSync(csvFile, csvHeaders);
542
- }
543
- const csvEntry = [logEntry.timestamp?.toISOString() || new Date().toISOString(), logEntry.eventType || 'LOG', logEntry.level || 'info', logEntry.category || 'general', logEntry.domain || '', JSON.stringify(logEntry.details || {}).replace(/"/g, '""')].join(',');
544
- appendFileSync(csvFile, csvEntry + '\n');
545
- }
546
- } catch (error) {
547
- logger.error('Failed to write audit log', {
548
- error: error.message
549
- });
550
- }
551
- }
552
-
553
- /**
554
- * Rotate log file when it exceeds size limit
555
- * @param {string} logFile - Log file to rotate
556
- */
557
- rotateLogFile(logFile) {
558
- try {
559
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
560
- const rotatedFile = logFile.replace('.log', `-${timestamp}.log`);
561
-
562
- // Move current file
563
- execSync(`move "${logFile}" "${rotatedFile}"`, {
564
- shell: true
565
- });
566
- this.logAuditEvent('AUDIT_LOG_ROTATED', 'SYSTEM', {
567
- originalFile: logFile,
568
- rotatedFile: rotatedFile,
569
- timestamp: new Date()
570
- });
571
- } catch (error) {
572
- logger.error('Failed to rotate log file', {
573
- error: error.message
574
- });
575
- }
576
- }
577
-
578
- /**
579
- * Generate comprehensive deployment report
580
- * @param {string} deploymentId - Deployment identifier
581
- * @returns {Object} Generated report info
582
- */
583
- generateDeploymentReport(deploymentId) {
584
- const deployment = this.currentSession.deployments.get(deploymentId);
585
- if (!deployment) {
586
- logger.warn('Cannot generate report: deployment not found', {
587
- deploymentId
588
- });
589
- return null;
590
- }
591
- const reportData = {
592
- deploymentId,
593
- domain: deployment.domain,
594
- startTime: deployment.startTime,
595
- endTime: deployment.endTime,
596
- duration: deployment.duration,
597
- status: deployment.status,
598
- phases: deployment.phases,
599
- metrics: deployment.metrics,
600
- rollbacks: deployment.rollbacks,
601
- events: deployment.events,
602
- summary: deployment.summary || {},
603
- generatedAt: new Date()
604
- };
605
-
606
- // Generate report files
607
- const reportFiles = {
608
- json: join(this.paths.reports, `deployment-${deploymentId}.json`),
609
- html: join(this.paths.reports, `deployment-${deploymentId}.html`),
610
- csv: join(this.paths.reports, `deployment-${deploymentId}.csv`)
611
- };
612
-
613
- // JSON report
614
- writeFileSync(reportFiles.json, JSON.stringify(reportData, null, 2));
615
-
616
- // HTML report
617
- const htmlReport = this.generateHtmlReport(reportData);
618
- writeFileSync(reportFiles.html, htmlReport);
619
-
620
- // CSV report
621
- const csvReport = this.generateCsvReport(reportData);
622
- writeFileSync(reportFiles.csv, csvReport);
623
- console.log(`📊 Deployment report generated: ${deploymentId}`);
624
- if (this.config.auditLevel !== 'minimal') {
625
- console.log(` 📄 JSON: ${reportFiles.json}`);
626
- console.log(` 🌐 HTML: ${reportFiles.html}`);
627
- console.log(` 📊 CSV: ${reportFiles.csv}`);
628
- }
629
- return reportFiles;
630
- }
631
-
632
- /**
633
- * Generate HTML deployment report
634
- * @param {Object} reportData - Report data
635
- * @returns {string} HTML content
636
- */
637
- generateHtmlReport(reportData) {
638
- return `<!DOCTYPE html>
639
- <html lang="en">
640
- <head>
641
- <meta charset="UTF-8">
642
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
643
- <title>Deployment Report - ${reportData.deploymentId}</title>
644
- <style>
645
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; }
646
- .container { max-width: 1200px; margin: 0 auto; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
647
- .header { background: ${reportData.status === 'success' ? '#059669' : '#dc2626'}; color: white; padding: 30px; border-radius: 8px 8px 0 0; }
648
- .content { padding: 30px; }
649
- .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
650
- .summary-card { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 20px; text-align: center; }
651
- .summary-card h3 { margin: 0 0 10px 0; font-size: 24px; }
652
- .phases { background: #f1f5f9; border-radius: 6px; padding: 20px; margin-top: 20px; }
653
- .phase { padding: 15px; border-left: 4px solid #3b82f6; margin-bottom: 10px; background: white; }
654
- .phase.error { border-color: #dc2626; background: #fef2f2; }
655
- .timeline { margin-top: 20px; }
656
- .event { padding: 10px; border-left: 3px solid #e2e8f0; margin-bottom: 8px; font-size: 14px; }
657
- .event.error { border-color: #dc2626; color: #dc2626; }
658
- .event.warn { border-color: #f59e0b; color: #f59e0b; }
659
- </style>
660
- </head>
661
- <body>
662
- <div class="container">
663
- <div class="header">
664
- <h1>📋 Deployment Report</h1>
665
- <p>Deployment: ${reportData.deploymentId}</p>
666
- <p>Domain: ${reportData.domain}</p>
667
- <p>Status: ${reportData.status.toUpperCase()}</p>
668
- <p>Generated: ${reportData.generatedAt.toLocaleString()}</p>
669
- </div>
670
-
671
- <div class="content">
672
- <div class="summary">
673
- <div class="summary-card">
674
- <h3>${reportData.duration?.toFixed(2) || 0}s</h3>
675
- <p>Total Duration</p>
676
- </div>
677
- <div class="summary-card">
678
- <h3>${reportData.phases.length}</h3>
679
- <p>Phases Executed</p>
680
- </div>
681
- <div class="summary-card">
682
- <h3>${reportData.metrics.errorCount}</h3>
683
- <p>Errors</p>
684
- </div>
685
- <div class="summary-card">
686
- <h3>${reportData.rollbacks.length}</h3>
687
- <p>Rollbacks</p>
688
- </div>
689
- </div>
690
-
691
- <div class="phases">
692
- <h3>📊 Deployment Phases</h3>
693
- ${reportData.phases.map((phase, index) => `
694
- <div class="phase ${phase.error ? 'error' : ''}">
695
- <strong>${index + 1}. ${phase.phase} (${phase.action})</strong>
696
- <div>Time: ${phase.timestamp.toLocaleString()}</div>
697
- ${phase.details ? `<div>Details: ${JSON.stringify(phase.details)}</div>` : ''}
698
- </div>
699
- `).join('')}
700
- </div>
701
-
702
- ${reportData.events.length > 0 ? `
703
- <div class="timeline">
704
- <h3>📝 Event Timeline</h3>
705
- ${reportData.events.slice(-20).map(event => `
706
- <div class="event ${event.level}">
707
- <strong>${event.timestamp.toLocaleString()}</strong> - ${event.eventType}
708
- ${event.details ? `<div>${JSON.stringify(event.details)}</div>` : ''}
709
- </div>
710
- `).join('')}
711
- </div>
712
- ` : ''}
713
- </div>
714
- </div>
715
- </body>
716
- </html>`;
717
- }
718
-
719
- /**
720
- * Generate CSV deployment report
721
- * @param {Object} reportData - Report data
722
- * @returns {string} CSV content
723
- */
724
- generateCsvReport(reportData) {
725
- const headers = 'timestamp,phase,action,status,duration,details\n';
726
- const rows = reportData.phases.map(phase => [phase.timestamp.toISOString(), phase.phase, phase.action, phase.error ? 'error' : 'success', reportData.duration || 0, JSON.stringify(phase.details || {}).replace(/"/g, '""')].join(',')).join('\n');
727
- return headers + rows;
728
- }
729
-
730
- /**
731
- * Search audit logs with filters
732
- * @param {Object} filters - Search filters
733
- * @returns {Array} Matching log entries
734
- */
735
- searchAuditLogs(filters = {}) {
736
- const results = [];
737
- const {
738
- eventType,
739
- domain,
740
- dateFrom,
741
- dateTo,
742
- level,
743
- category,
744
- deploymentId,
745
- limit = 100
746
- } = filters;
747
-
748
- // Search current session events
749
- let matchingEvents = this.currentSession.events.filter(event => {
750
- if (eventType && event.eventType !== eventType) return false;
751
- if (domain && event.domain !== domain) return false;
752
- if (level && event.level !== level) return false;
753
- if (category && event.category !== category) return false;
754
- if (deploymentId && event.details?.deploymentId !== deploymentId) return false;
755
- if (dateFrom && event.timestamp < new Date(dateFrom)) return false;
756
- if (dateTo && event.timestamp > new Date(dateTo)) return false;
757
- return true;
758
- });
759
-
760
- // Sort by timestamp (newest first)
761
- matchingEvents.sort((a, b) => b.timestamp - a.timestamp);
762
-
763
- // Apply limit
764
- results.push(...matchingEvents.slice(0, limit));
765
- this.logAuditEvent('AUDIT_SEARCH', 'SYSTEM', {
766
- filters,
767
- resultCount: results.length
768
- });
769
- return results;
770
- }
771
-
772
- /**
773
- * Generate audit summary for current session
774
- * @returns {Object} Audit summary
775
- */
776
- generateAuditSummary() {
777
- const sessionDuration = (new Date() - this.currentSession.startTime) / 1000;
778
- const summary = {
779
- sessionId: this.currentSession.sessionId,
780
- sessionDuration,
781
- metrics: {
782
- ...this.currentSession.metrics
783
- },
784
- deployments: Array.from(this.currentSession.deployments.entries()).map(([id, deployment]) => ({
785
- deploymentId: id,
786
- domain: deployment.domain,
787
- status: deployment.status,
788
- duration: deployment.duration,
789
- phaseCount: deployment.phases.length,
790
- errorCount: deployment.metrics.errorCount
791
- })),
792
- eventsByCategory: {},
793
- eventsByLevel: {},
794
- generatedAt: new Date()
795
- };
796
-
797
- // Categorize events
798
- this.currentSession.events.forEach(event => {
799
- // By category
800
- if (!summary.eventsByCategory[event.category]) {
801
- summary.eventsByCategory[event.category] = 0;
802
- }
803
- summary.eventsByCategory[event.category]++;
804
-
805
- // By level
806
- if (!summary.eventsByLevel[event.level]) {
807
- summary.eventsByLevel[event.level] = 0;
808
- }
809
- summary.eventsByLevel[event.level]++;
810
- });
811
- console.log('\n📊 Audit Session Summary');
812
- console.log(` 🆔 Session: ${summary.sessionId}`);
813
- console.log(` ⏱️ Duration: ${sessionDuration.toFixed(2)}s`);
814
- console.log(` 📈 Deployments: ${summary.metrics.deploymentCount}`);
815
- console.log(` 📝 Total Events: ${summary.metrics.totalEvents}`);
816
- console.log(` ❌ Errors: ${summary.metrics.errorCount}`);
817
- console.log(` ⚠️ Warnings: ${summary.metrics.warningCount}`);
818
- return summary;
819
- }
820
-
821
- /**
822
- * Send real-time security alert
823
- * @param {Object} securityEvent - Security event data
824
- */
825
- async sendSecurityAlert(securityEvent) {
826
- if (!this.config.alertWebhook) {
827
- logger.warn('Security alert webhook not configured');
828
- return;
829
- }
830
- const alert = {
831
- type: 'security_alert',
832
- severity: securityEvent.severity,
833
- event: securityEvent,
834
- timestamp: new Date(),
835
- sessionId: this.currentSession.sessionId
836
- };
837
- try {
838
- // In a real implementation, this would send to a webhook
839
- console.log(`🚨 Security Alert: ${securityEvent.eventType} (${securityEvent.severity})`);
840
- this.logAuditEvent('SECURITY_ALERT_SENT', 'SYSTEM', {
841
- alertId: Date.now().toString(),
842
- event: securityEvent
843
- });
844
- } catch (error) {
845
- logger.error('Failed to send security alert', {
846
- error: error.message
847
- });
848
- }
849
- }
850
-
851
- /**
852
- * Send general alert
853
- * @param {Object} auditEvent - Audit event to alert on
854
- */
855
- async sendAlert(auditEvent) {
856
- if (!this.config.realTimeAlerts) return;
857
- console.log(`🔔 Alert: ${auditEvent.eventType} (${auditEvent.level})`);
858
- this.logAuditEvent('ALERT_SENT', 'SYSTEM', {
859
- alertId: Date.now().toString(),
860
- originalEvent: auditEvent.eventType
861
- });
862
- }
863
-
864
- /**
865
- * Clean up old audit logs based on retention policy
866
- * @returns {Object} Cleanup results
867
- */
868
- cleanupAuditLogs() {
869
- const cleanupResults = {
870
- filesRemoved: 0,
871
- spaceSaved: 0,
872
- errors: []
873
- };
874
- try {
875
- const cutoffDate = new Date();
876
- cutoffDate.setDate(cutoffDate.getDate() - this.config.retentionDays);
877
-
878
- // Scan audit directory for old files
879
- const scanDirectory = dir => {
880
- if (!existsSync(dir)) return;
881
- const items = readdirSync(dir);
882
- items.forEach(item => {
883
- const itemPath = join(dir, item);
884
- const stats = statSync(itemPath);
885
- if (stats.isFile() && stats.mtime < cutoffDate) {
886
- try {
887
- cleanupResults.spaceSaved += stats.size;
888
- execSync(`del "${itemPath}"`, {
889
- shell: true
890
- });
891
- cleanupResults.filesRemoved++;
892
- } catch (error) {
893
- cleanupResults.errors.push({
894
- file: itemPath,
895
- error: error.message
896
- });
897
- }
898
- }
899
- });
900
- };
901
- scanDirectory(this.paths.daily);
902
- scanDirectory(this.paths.deployments);
903
- this.logAuditEvent('AUDIT_CLEANUP_COMPLETED', 'SYSTEM', cleanupResults);
904
- console.log(`🧹 Audit cleanup completed: ${cleanupResults.filesRemoved} files removed`);
905
- } catch (error) {
906
- logger.error('Audit cleanup failed', {
907
- error: error.message
908
- });
909
- cleanupResults.errors.push({
910
- general: error.message
911
- });
912
- }
913
- return cleanupResults;
914
- }
915
- }
916
-
917
- // Legacy function exports for backward compatibility
918
-
919
- /**
920
- * Create simple audit logger
921
- * @param {string} deploymentId - Deployment identifier
922
- * @param {Object} options - Audit options
923
- * @returns {DeploymentAuditor} Auditor instance
924
- */
925
- export function createAuditLogger(deploymentId, options = {}) {
926
- const auditor = new DeploymentAuditor(options);
927
- return {
928
- logPhase: (phase, action, details) => auditor.logPhase(deploymentId, phase, action, details),
929
- logError: (error, context) => auditor.logError(deploymentId, error, context),
930
- logEvent: (eventType, details) => auditor.logAuditEvent(eventType, details.domain || 'SYSTEM', details),
931
- generateReport: () => auditor.generateDeploymentReport(deploymentId),
932
- getSummary: () => auditor.generateAuditSummary()
933
- };
934
- }
935
-
936
- /**
937
- * Simple deployment logging
938
- * @param {string} deploymentId - Deployment identifier
939
- * @param {string} message - Log message
940
- * @param {Object} context - Additional context
941
- */
942
- export function logDeployment(deploymentId, message, context = {}) {
943
- const auditor = new DeploymentAuditor({
944
- auditLevel: 'standard'
945
- });
946
- auditor.logAuditEvent('DEPLOYMENT_LOG', context.domain || 'SYSTEM', {
947
- deploymentId,
948
- message,
949
- ...context
950
- });
951
- }
952
-
953
- /**
954
- * Log deployment phase with timing
955
- * @param {string} deploymentId - Deployment identifier
956
- * @param {string} phase - Phase name
957
- * @param {Function} operation - Operation to execute
958
- * @returns {Promise<*>} Operation result
959
- */
960
- export async function auditPhase(deploymentId, phase, operation) {
961
- const auditor = new DeploymentAuditor({
962
- auditLevel: 'detailed'
963
- });
964
- auditor.logPhase(deploymentId, phase, 'start');
965
- const startTime = Date.now();
966
- try {
967
- const result = await operation();
968
- const duration = Date.now() - startTime;
969
- auditor.logPhase(deploymentId, phase, 'end', {
970
- duration,
971
- success: true
972
- });
973
- return result;
974
- } catch (error) {
975
- const duration = Date.now() - startTime;
976
- auditor.logPhase(deploymentId, phase, 'end', {
977
- duration,
978
- success: false,
979
- error: error.message
980
- });
981
- auditor.logError(deploymentId, error, {
982
- phase
983
- });
984
- throw error;
985
- }
986
- }