@tamyla/clodo-framework 1.0.0

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