@devilsdev/rag-pipeline-utils 2.1.11 → 2.2.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 (110) hide show
  1. package/.ragrc.schema.json +218 -0
  2. package/README.md +651 -393
  3. package/bin/cli.js +8 -14
  4. package/dist/index.d.ts +237 -0
  5. package/dist/index.mjs +22 -7
  6. package/package.json +17 -13
  7. package/src/ai/adaptive-retrieval.js +191 -0
  8. package/src/ai/federated-learning.js +214 -0
  9. package/src/ai/federation/federated-learning-coordinator.js +345 -0
  10. package/src/ai/federation.js +76 -0
  11. package/src/ai/index-fixed.js +509 -0
  12. package/src/ai/index.js +33 -0
  13. package/src/ai/model-trainer.js +217 -0
  14. package/src/ai/model-training.js +205 -0
  15. package/src/ai/module-template.js +37 -0
  16. package/src/ai/multimodal/multi-modal-processor.js +345 -0
  17. package/src/ai/multimodal-processing.js +268 -0
  18. package/src/ai/multimodal.js +71 -0
  19. package/src/ai/orchestrator.js +70 -0
  20. package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
  21. package/src/ai/retrieval-engine.js +69 -0
  22. package/src/ai/training/model-training-orchestrator.js +228 -0
  23. package/src/ci/workflow-analyzer.js +71 -0
  24. package/src/cli/commands/ai-ml.js +967 -0
  25. package/src/cli/commands/docs.js +228 -0
  26. package/src/cli/commands/dx.js +538 -0
  27. package/src/cli/commands/plugin-hub.js +875 -0
  28. package/src/cli/doctor-command.js +639 -0
  29. package/src/cli/enhanced-cli-commands.js +945 -0
  30. package/src/cli/interactive-wizard.js +997 -0
  31. package/src/cli/plugin-marketplace-commands.js +869 -0
  32. package/src/cli.js +17 -0
  33. package/src/config/enhanced-ragrc-schema.js +632 -0
  34. package/src/config/load-config.js +54 -0
  35. package/src/config/load-plugin-config.js +69 -0
  36. package/src/config/normalize-config.js +105 -0
  37. package/src/config/schema-validator.js +315 -0
  38. package/src/config/validate-plugin-schema.js +35 -0
  39. package/src/config/validate-schema.js +113 -0
  40. package/src/contracts/plugin-contracts.js +33 -0
  41. package/src/core/create-pipeline.js +99 -0
  42. package/src/core/dependency-injection.js +242 -0
  43. package/src/core/observability/event-logger.js +241 -0
  44. package/src/core/observability/instrumented-pipeline.js +609 -0
  45. package/src/core/observability/metrics.js +497 -0
  46. package/src/core/observability/tracing.js +781 -0
  47. package/src/core/performance/benchmark.js +516 -0
  48. package/src/core/performance/parallel-processor.js +240 -0
  49. package/src/core/performance/streaming-safeguards.js +611 -0
  50. package/src/core/pipeline-factory.js +60 -0
  51. package/src/core/plugin-contracts.js +89 -0
  52. package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
  53. package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
  54. package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
  55. package/src/core/plugin-marketplace/version-resolver.js +61 -0
  56. package/src/core/plugin-registry.js +265 -0
  57. package/src/dag/dag-engine.js +954 -0
  58. package/src/dag/dag-node.js +76 -0
  59. package/src/dag/enhanced-dag-engine.js +822 -0
  60. package/src/dx/index.js +40 -0
  61. package/src/dx/integration-templates.js +665 -0
  62. package/src/dx/performance-profiler.js +968 -0
  63. package/src/dx/realtime-debugger.js +755 -0
  64. package/src/dx/visual-pipeline-builder.js +578 -0
  65. package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
  66. package/src/ecosystem/plugin-certification.js +580 -0
  67. package/src/ecosystem/plugin-hub.js +821 -0
  68. package/src/enterprise/audit-logging.js +967 -0
  69. package/src/enterprise/data-governance.js +408 -0
  70. package/src/enterprise/multi-tenancy.js +496 -0
  71. package/src/enterprise/sso-integration.js +903 -0
  72. package/src/evaluate/evaluator.js +52 -0
  73. package/src/evaluate/scoring.js +91 -0
  74. package/src/index.js +67 -0
  75. package/src/ingest.js +59 -0
  76. package/src/loader/csv-loader.js +38 -0
  77. package/src/loader/directory-loader.js +48 -0
  78. package/src/loader/html-loader.js +62 -0
  79. package/src/loader/markdown-loader.js +67 -0
  80. package/src/mocks/openai-embedder.js +119 -0
  81. package/src/mocks/openai-llm.js +77 -0
  82. package/src/mocks/pdf-loader.js +21 -0
  83. package/src/mocks/pinecone-retriever.js +106 -0
  84. package/src/observability/audit-logger.js +758 -0
  85. package/src/observability/dashboard-config.json +675 -0
  86. package/src/observability/event-logger.js +310 -0
  87. package/src/observability/metrics.js +691 -0
  88. package/src/observability/security-monitor.js +830 -0
  89. package/src/observability/slo-monitor.js +319 -0
  90. package/src/observability/telemetry.js +686 -0
  91. package/src/pipeline/pipeline.js +18 -0
  92. package/src/plugins/sample-embedder.js +53 -0
  93. package/src/plugins/sample-llm.js +30 -0
  94. package/src/plugins/sample-loader.js +24 -0
  95. package/src/plugins/sample-retriever.js +84 -0
  96. package/src/query.js +117 -0
  97. package/src/reranker/llm-reranker.js +85 -0
  98. package/src/scripts/script-utilities.js +36 -0
  99. package/src/security/plugin-sandbox.js +586 -0
  100. package/src/security/plugin-signature-verifier.js +414 -0
  101. package/src/security/validator.js +36 -0
  102. package/src/utils/ci/diagnostic-reporter.js +57 -0
  103. package/src/utils/logger.js +211 -0
  104. package/src/utils/performance-monitor.js +561 -0
  105. package/src/utils/plugin-scaffolder.js +447 -0
  106. package/src/utils/retry-policy.js +443 -0
  107. package/src/utils/retry.js +107 -0
  108. package/src/utils/safe-expression-evaluator.js +579 -0
  109. package/src/utils/structured-logger.js +361 -0
  110. package/src/utils/validate-plugin-contract.js +42 -0
@@ -0,0 +1,967 @@
1
+ /**
2
+ * Enterprise Audit Logging
3
+ * Compliance-grade activity tracking with immutable logs
4
+ */
5
+
6
+ const fs = require('fs').promises;
7
+ // eslint-disable-line global-require
8
+ const path = require('path');
9
+ // eslint-disable-line global-require
10
+ const crypto = require('crypto');
11
+ // eslint-disable-line global-require
12
+ const { EventEmitter } = require('events');
13
+ // eslint-disable-line global-require
14
+
15
+ class AuditLogger extends EventEmitter {
16
+ constructor(_options = {}) {
17
+ super();
18
+
19
+ this._config = {
20
+ logDir:
21
+ _options.logDir ||
22
+ path.join(process.cwd(), '.rag-enterprise', 'audit-logs'),
23
+ retention: {
24
+ days: _options.retentionDays || 2555, // 7 years default for compliance
25
+ maxSizeMB: _options.maxLogSizeMB || 1000,
26
+ compressionEnabled: _options.compressionEnabled !== false,
27
+ },
28
+ compliance: {
29
+ standards: _options.standards || ['SOC2', 'GDPR', 'HIPAA', 'PCI-DSS'],
30
+ immutable: _options.immutable !== false,
31
+ encryption: _options.encryption !== false,
32
+ digitalSigning: _options.digitalSigning !== false,
33
+ },
34
+ realtime: {
35
+ enabled: _options.realtimeEnabled !== false,
36
+ batchSize: _options.batchSize || 100,
37
+ flushInterval: _options.flushInterval || 5000, // 5 seconds
38
+ webhookUrl: _options.webhookUrl,
39
+ },
40
+ categories: {
41
+ authentication: { level: 'HIGH', retention: 2555 },
42
+ authorization: { level: 'HIGH', retention: 2555 },
43
+ dataAccess: { level: 'MEDIUM', retention: 1825 }, // 5 years
44
+ dataModification: { level: 'HIGH', retention: 2555 },
45
+ systemChanges: { level: 'HIGH', retention: 2555 },
46
+ userActivity: { level: 'LOW', retention: 365 },
47
+ apiAccess: { level: 'MEDIUM', retention: 1095 }, // 3 years
48
+ pluginActivity: { level: 'MEDIUM', retention: 1095 },
49
+ complianceEvents: { level: 'CRITICAL', retention: 3650 }, // 10 years
50
+ },
51
+ ..._options,
52
+ };
53
+
54
+ this.logBuffer = [];
55
+ this.encryptionKey =
56
+ _options.encryptionKey || this._generateEncryptionKey();
57
+ this.signingKey = _options.signingKey || this._generateSigningKey();
58
+ this.sequenceNumber = 0;
59
+
60
+ this._initializeAuditSystem();
61
+ }
62
+
63
+ /**
64
+ * Initialize audit logging system
65
+ */
66
+ async _initializeAuditSystem() {
67
+ // Create audit log directories
68
+ await fs.mkdir(this._config.logDir, { recursive: true });
69
+ await fs.mkdir(path.join(this._config.logDir, 'daily'), {
70
+ recursive: true,
71
+ });
72
+ await fs.mkdir(path.join(this._config.logDir, 'archived'), {
73
+ recursive: true,
74
+ });
75
+ await fs.mkdir(path.join(this._config.logDir, 'integrity'), {
76
+ recursive: true,
77
+ });
78
+
79
+ // Start periodic flush
80
+ if (this._config.realtime.enabled) {
81
+ this.flushTimer = setInterval(() => {
82
+ this._flushLogs();
83
+ }, this._config.realtime.flushInterval);
84
+ if (typeof this.flushTimer.unref === 'function') this.flushTimer.unref();
85
+ }
86
+
87
+ // Initialize integrity chain
88
+ await this._initializeIntegrityChain();
89
+
90
+ this.emit('audit_system_initialized');
91
+ }
92
+
93
+ /**
94
+ * Log authentication events
95
+ */
96
+ async logAuthentication(event) {
97
+ const auditEvent = {
98
+ _category: 'authentication',
99
+ action: event._action, // login, logout, login_failed, password_change, mfa_enabled
100
+ tenantId: event._tenantId,
101
+ userId: event._userId,
102
+ sessionId: event.sessionId,
103
+ provider: event.provider, // sso, local, api_key
104
+ details: {
105
+ ipAddress: event.ipAddress,
106
+ userAgent: event.userAgent,
107
+ location: event.location,
108
+ riskScore: event.riskScore,
109
+ mfaUsed: event.mfaUsed,
110
+ deviceFingerprint: event.deviceFingerprint,
111
+ },
112
+ result: event.result, // success, failure, blocked
113
+ reason: event.reason, // invalid_credentials, account_locked, etc.
114
+ metadata: {
115
+ timestamp: new Date().toISOString(),
116
+ correlationId: event._correlationId || crypto.randomUUID(),
117
+ _severity: this._calculateSeverity(
118
+ 'authentication',
119
+ event._action,
120
+ event.result,
121
+ ),
122
+ },
123
+ };
124
+
125
+ return await this._writeAuditLog(auditEvent);
126
+ }
127
+
128
+ /**
129
+ * Log authorization events
130
+ */
131
+ async logAuthorization(event) {
132
+ const auditEvent = {
133
+ _category: 'authorization',
134
+ action: event._action, // access_granted, access_denied, permission_changed
135
+ tenantId: event._tenantId,
136
+ userId: event._userId,
137
+ resource: {
138
+ type: event.resourceType, // workspace, plugin, data, api
139
+ id: event.resourceId,
140
+ path: event.resourcePath,
141
+ operation: event.operation, // read, write, delete, execute
142
+ },
143
+ permissions: {
144
+ required: event.requiredPermissions,
145
+ granted: event.grantedPermissions,
146
+ roles: event.userRoles,
147
+ groups: event.userGroups,
148
+ },
149
+ result: event.result,
150
+ reason: event.reason,
151
+ metadata: {
152
+ timestamp: new Date().toISOString(),
153
+ correlationId: event._correlationId || crypto.randomUUID(),
154
+ _severity: this._calculateSeverity(
155
+ 'authorization',
156
+ event._action,
157
+ event.result,
158
+ ),
159
+ },
160
+ };
161
+
162
+ return await this._writeAuditLog(auditEvent);
163
+ }
164
+
165
+ /**
166
+ * Log data access events
167
+ */
168
+ async logDataAccess(event) {
169
+ const auditEvent = {
170
+ _category: 'dataAccess',
171
+ action: event._action, // read, query, export, download
172
+ tenantId: event._tenantId,
173
+ userId: event._userId,
174
+ workspaceId: event.workspaceId,
175
+ data: {
176
+ type: event.dataType, // document, embedding, pipeline_result
177
+ classification: event.dataClassification, // public, internal, confidential, restricted
178
+ sensitivity: event.dataSensitivity, // none, pii, phi, financial
179
+ recordCount: event.recordCount,
180
+ sizeBytes: event.sizeBytes,
181
+ query: event.query ? this._sanitizeQuery(event.query) : null,
182
+ },
183
+ access: {
184
+ method: event.accessMethod, // api, ui, cli, plugin
185
+ source: event.source,
186
+ destination: event.destination,
187
+ },
188
+ result: event.result,
189
+ metadata: {
190
+ timestamp: new Date().toISOString(),
191
+ correlationId: event._correlationId || crypto.randomUUID(),
192
+ _severity: this._calculateSeverity(
193
+ 'dataAccess',
194
+ event._action,
195
+ event.result,
196
+ ),
197
+ },
198
+ };
199
+
200
+ return await this._writeAuditLog(auditEvent);
201
+ }
202
+
203
+ /**
204
+ * Log data modification events
205
+ */
206
+ async logDataModification(event) {
207
+ const auditEvent = {
208
+ _category: 'dataModification',
209
+ action: event._action, // create, update, delete, purge
210
+ tenantId: event._tenantId,
211
+ userId: event._userId,
212
+ workspaceId: event.workspaceId,
213
+ data: {
214
+ _type: event.dataType,
215
+ classification: event.dataClassification,
216
+ recordsAffected: event.recordsAffected,
217
+ beforeHash: event.beforeHash,
218
+ afterHash: event.afterHash,
219
+ changeType: event.changeType, // bulk, individual, migration
220
+ },
221
+ changes: {
222
+ fields: event.changedFields,
223
+ reason: event.changeReason,
224
+ approvalRequired: event.approvalRequired,
225
+ approvedBy: event.approvedBy,
226
+ },
227
+ result: event.result,
228
+ metadata: {
229
+ timestamp: new Date().toISOString(),
230
+ correlationId: event._correlationId || crypto.randomUUID(),
231
+ _severity: this._calculateSeverity(
232
+ 'dataModification',
233
+ event._action,
234
+ event.result,
235
+ ),
236
+ },
237
+ };
238
+
239
+ return await this._writeAuditLog(auditEvent);
240
+ }
241
+
242
+ /**
243
+ * Log system configuration changes
244
+ */
245
+ async logSystemChanges(event) {
246
+ const auditEvent = {
247
+ _category: 'systemChanges',
248
+ action: event._action, // config_change, user_management, role_change, integration_change
249
+ tenantId: event._tenantId,
250
+ userId: event._userId,
251
+ system: {
252
+ component: event.component, // sso, quotas, plugins, security
253
+ setting: event.setting,
254
+ oldValue: event.oldValue ? this._sanitizeValue(event.oldValue) : null,
255
+ newValue: event.newValue ? this._sanitizeValue(event.newValue) : null,
256
+ impact: event.impact, // low, medium, high, critical
257
+ },
258
+ approval: {
259
+ required: event.approvalRequired,
260
+ approvedBy: event.approvedBy,
261
+ approvalTime: event.approvalTime,
262
+ },
263
+ result: event.result,
264
+ metadata: {
265
+ timestamp: new Date().toISOString(),
266
+ correlationId: event._correlationId || crypto.randomUUID(),
267
+ _severity: this._calculateSeverity(
268
+ 'systemChanges',
269
+ event._action,
270
+ event.result,
271
+ ),
272
+ },
273
+ };
274
+
275
+ return await this._writeAuditLog(auditEvent);
276
+ }
277
+
278
+ /**
279
+ * Log API access events
280
+ */
281
+ async logAPIAccess(event) {
282
+ const auditEvent = {
283
+ _category: 'apiAccess',
284
+ action: event._action, // api_call, rate_limit_hit, api_key_used
285
+ tenantId: event._tenantId,
286
+ userId: event._userId,
287
+ api: {
288
+ endpoint: event.endpoint,
289
+ method: event.method,
290
+ version: event.apiVersion,
291
+ key: event.apiKey ? this._hashApiKey(event.apiKey) : null,
292
+ rateLimitRemaining: event.rateLimitRemaining,
293
+ responseTime: event.responseTime,
294
+ responseSize: event.responseSize,
295
+ },
296
+ request: {
297
+ ipAddress: event.ipAddress,
298
+ userAgent: event.userAgent,
299
+ parameters: event.parameters
300
+ ? this._sanitizeParameters(event.parameters)
301
+ : null,
302
+ },
303
+ result: event.result,
304
+ httpStatus: event.httpStatus,
305
+ metadata: {
306
+ timestamp: new Date().toISOString(),
307
+ correlationId: event._correlationId || crypto.randomUUID(),
308
+ _severity: this._calculateSeverity(
309
+ 'apiAccess',
310
+ event._action,
311
+ event.result,
312
+ ),
313
+ },
314
+ };
315
+
316
+ return await this._writeAuditLog(auditEvent);
317
+ }
318
+
319
+ /**
320
+ * Log compliance events
321
+ */
322
+ async logComplianceEvent(event) {
323
+ const auditEvent = {
324
+ _category: 'complianceEvents',
325
+ action: event._action, // data_retention, privacy_request, breach_detected, audit_requested
326
+ tenantId: event._tenantId,
327
+ compliance: {
328
+ standard: event.standard, // GDPR, HIPAA, SOC2, PCI-DSS
329
+ requirement: event.requirement,
330
+ status: event.status, // compliant, non_compliant, remediated
331
+ evidence: event.evidence,
332
+ riskLevel: event.riskLevel,
333
+ },
334
+ details: {
335
+ affectedRecords: event.affectedRecords,
336
+ timeframe: event.timeframe,
337
+ remediation: event.remediation,
338
+ reportedTo: event.reportedTo,
339
+ },
340
+ result: event.result,
341
+ metadata: {
342
+ timestamp: new Date().toISOString(),
343
+ correlationId: event._correlationId || crypto.randomUUID(),
344
+ _severity: 'CRITICAL',
345
+ },
346
+ };
347
+
348
+ return await this._writeAuditLog(auditEvent);
349
+ }
350
+
351
+ /**
352
+ * Write audit log with integrity protection
353
+ */
354
+ async _writeAuditLog(auditEvent) {
355
+ // Add sequence number for integrity chain
356
+ auditEvent.sequence = ++this.sequenceNumber;
357
+
358
+ // Calculate integrity hash
359
+ auditEvent.integrity = await this._calculateIntegrityHash(auditEvent);
360
+
361
+ // Encrypt sensitive data if enabled
362
+ if (this._config.compliance.encryption) {
363
+ auditEvent = await this._encryptSensitiveFields(auditEvent);
364
+ }
365
+
366
+ // Digital signature if enabled
367
+ if (this._config.compliance.digitalSigning) {
368
+ auditEvent.signature = await this._signAuditEvent(auditEvent);
369
+ }
370
+
371
+ // Add to buffer for batch processing
372
+ this.logBuffer.push(auditEvent);
373
+
374
+ // Immediate flush for critical events
375
+ if (auditEvent.metadata._severity === 'CRITICAL') {
376
+ await this._flushLogs();
377
+ }
378
+
379
+ // Check buffer size
380
+ if (this.logBuffer.length >= this._config.realtime.batchSize) {
381
+ await this._flushLogs();
382
+ }
383
+
384
+ this.emit('audit_logged', {
385
+ _category: auditEvent._category,
386
+ _action: auditEvent._action,
387
+ _severity: auditEvent.metadata._severity,
388
+ _correlationId: auditEvent.metadata._correlationId,
389
+ });
390
+
391
+ return auditEvent.metadata.correlationId;
392
+ }
393
+
394
+ /**
395
+ * Flush logs to persistent storage
396
+ */
397
+ async _flushLogs() {
398
+ if (this.logBuffer.length === 0) return;
399
+
400
+ const logsToFlush = [...this.logBuffer];
401
+ this.logBuffer = [];
402
+
403
+ const today = new Date().toISOString().split('T')[0];
404
+ const logFile = path.join(
405
+ this._config.logDir,
406
+ 'daily',
407
+ `audit-${today}.jsonl`,
408
+ );
409
+
410
+ try {
411
+ // Write logs in JSONL format
412
+ const logLines =
413
+ logsToFlush.map((log) => JSON.stringify(log)).join('\n') + '\n';
414
+ await fs.appendFile(logFile, logLines);
415
+
416
+ // Update integrity chain
417
+ await this._updateIntegrityChain(logsToFlush);
418
+
419
+ // Send to webhook if configured
420
+ if (this._config.realtime.webhookUrl) {
421
+ await this._sendToWebhook(logsToFlush);
422
+ }
423
+
424
+ this.emit('logs_flushed', { count: logsToFlush.length, file: logFile });
425
+ } catch (error) {
426
+ // Re-add logs to buffer on failure
427
+ this.logBuffer.unshift(...logsToFlush);
428
+ this.emit('flush_failed', {
429
+ error: error.message,
430
+ count: logsToFlush.length,
431
+ });
432
+ throw error;
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Query audit logs
438
+ */
439
+ async queryLogs(query) {
440
+ const {
441
+ _tenantId,
442
+ _userId,
443
+ _category,
444
+ _action,
445
+ startDate,
446
+ endDate,
447
+ _severity,
448
+ _correlationId,
449
+ limit = 1000,
450
+ offset = 0,
451
+ } = query;
452
+
453
+ const results = [];
454
+ const startTime = startDate
455
+ ? new Date(startDate)
456
+ : new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
457
+ const endTime = endDate ? new Date(endDate) : new Date();
458
+
459
+ // Generate list of log files to search
460
+ const filesToSearch = await this._getLogFilesInRange(startTime, endTime);
461
+
462
+ for (const file of filesToSearch) {
463
+ const logs = await this._readLogFile(file);
464
+
465
+ for (const log of logs) {
466
+ if (this._matchesQuery(log, query)) {
467
+ results.push(await this._decryptAuditEvent(log));
468
+
469
+ if (results.length >= limit + offset) {
470
+ break;
471
+ }
472
+ }
473
+ }
474
+
475
+ if (results.length >= limit + offset) {
476
+ break;
477
+ }
478
+ }
479
+
480
+ return {
481
+ results: results.slice(offset, offset + limit),
482
+ total: results.length,
483
+ hasMore: results.length > limit + offset,
484
+ };
485
+ }
486
+
487
+ /**
488
+ * Generate compliance report
489
+ */
490
+ async generateComplianceReport(_options) {
491
+ const {
492
+ _tenantId,
493
+ standard, // GDPR, HIPAA, SOC2, PCI-DSS
494
+ startDate,
495
+ endDate,
496
+ includeEvidence = false,
497
+ } = _options;
498
+
499
+ const query = {
500
+ _tenantId,
501
+ startDate,
502
+ endDate,
503
+ limit: 10000,
504
+ };
505
+
506
+ const logs = await this.queryLogs(query);
507
+
508
+ const report = {
509
+ metadata: {
510
+ _tenantId,
511
+ standard,
512
+ period: { startDate, endDate },
513
+ generatedAt: new Date().toISOString(),
514
+ totalEvents: logs.total,
515
+ },
516
+ summary: {
517
+ authenticationEvents: 0,
518
+ authorizationEvents: 0,
519
+ dataAccessEvents: 0,
520
+ dataModificationEvents: 0,
521
+ systemChangeEvents: 0,
522
+ complianceEvents: 0,
523
+ criticalEvents: 0,
524
+ failedEvents: 0,
525
+ },
526
+ compliance: {
527
+ requirements: [],
528
+ violations: [],
529
+ recommendations: [],
530
+ },
531
+ evidence: includeEvidence ? [] : null,
532
+ };
533
+
534
+ // Analyze logs for compliance
535
+ for (const log of logs.results) {
536
+ report.summary[log._category + 'Events']++;
537
+
538
+ if (log.metadata._severity === 'CRITICAL') {
539
+ report.summary.criticalEvents++;
540
+ }
541
+
542
+ if (log.result === 'failure' || log.result === 'blocked') {
543
+ report.summary.failedEvents++;
544
+ }
545
+
546
+ // Check compliance requirements
547
+ const complianceCheck = this._checkCompliance(log, standard);
548
+ if (complianceCheck.violation) {
549
+ report.compliance.violations.push(complianceCheck);
550
+ }
551
+
552
+ if (includeEvidence && complianceCheck.evidence) {
553
+ report.evidence.push({
554
+ logId: log.metadata._correlationId,
555
+ requirement: complianceCheck.requirement,
556
+ evidence: complianceCheck.evidence,
557
+ });
558
+ }
559
+ }
560
+
561
+ return report;
562
+ }
563
+
564
+ /**
565
+ * Verify log integrity
566
+ */
567
+ async verifyIntegrity(_options = {}) {
568
+ const { startDate, endDate, _tenantId } = _options;
569
+
570
+ const integrityFile = path.join(
571
+ this._config.logDir,
572
+ 'integrity',
573
+ 'chain.json',
574
+ );
575
+ const _integrityChain = JSON.parse(
576
+ await fs.readFile(integrityFile, 'utf8'),
577
+ );
578
+
579
+ const verification = {
580
+ verified: true,
581
+ totalLogs: 0,
582
+ verifiedLogs: 0,
583
+ tamperedLogs: [],
584
+ missingLogs: [],
585
+ integrityBreaks: [],
586
+ };
587
+
588
+ // Verify each log file
589
+ const filesToVerify = await this._getLogFilesInRange(
590
+ startDate ? new Date(startDate) : new Date(0),
591
+ endDate ? new Date(endDate) : new Date(),
592
+ );
593
+
594
+ for (const file of filesToVerify) {
595
+ const logs = await this._readLogFile(file);
596
+
597
+ for (const log of logs) {
598
+ if (_tenantId && log.tenantId !== _tenantId) continue;
599
+
600
+ verification.totalLogs++;
601
+
602
+ // Verify integrity hash
603
+ const expectedHash = await this._calculateIntegrityHash(log);
604
+ if (log.integrity !== expectedHash) {
605
+ verification.tamperedLogs.push({
606
+ _correlationId: log.metadata._correlationId,
607
+ sequence: log.sequence,
608
+ file: file,
609
+ });
610
+ verification.verified = false;
611
+ } else {
612
+ verification.verifiedLogs++;
613
+ }
614
+
615
+ // Verify digital signature if present
616
+ if (log.signature && !(await this._verifySignature(log))) {
617
+ verification.tamperedLogs.push({
618
+ _correlationId: log.metadata._correlationId,
619
+ reason: 'invalid_signature',
620
+ file: file,
621
+ });
622
+ verification.verified = false;
623
+ }
624
+ }
625
+ }
626
+
627
+ return verification;
628
+ }
629
+
630
+ // Private helper methods
631
+ async _calculateIntegrityHash(auditEvent) {
632
+ const data = {
633
+ sequence: auditEvent.sequence,
634
+ category: auditEvent._category,
635
+ action: auditEvent._action,
636
+ tenantId: auditEvent._tenantId,
637
+ timestamp: auditEvent.metadata.timestamp,
638
+ };
639
+
640
+ return crypto
641
+ .createHash('sha256')
642
+ .update(JSON.stringify(data))
643
+ .digest('hex');
644
+ }
645
+
646
+ async _encryptSensitiveFields(auditEvent) {
647
+ const sensitiveFields = ['details', 'data', 'request'];
648
+
649
+ for (const field of sensitiveFields) {
650
+ if (auditEvent[field]) {
651
+ const cipher = crypto.createCipher('aes-256-gcm', this.encryptionKey);
652
+ let encrypted = cipher.update(
653
+ JSON.stringify(auditEvent[field]),
654
+ 'utf8',
655
+ 'hex',
656
+ );
657
+ encrypted += cipher.final('hex');
658
+
659
+ auditEvent[field] = {
660
+ encrypted: true,
661
+ data: encrypted,
662
+ authTag: cipher.getAuthTag().toString('hex'),
663
+ };
664
+ }
665
+ }
666
+
667
+ return auditEvent;
668
+ }
669
+
670
+ async _decryptAuditEvent(auditEvent) {
671
+ const sensitiveFields = ['details', 'data', 'request'];
672
+
673
+ for (const field of sensitiveFields) {
674
+ if (auditEvent[field] && auditEvent[field].encrypted) {
675
+ try {
676
+ const decipher = crypto.createDecipher(
677
+ 'aes-256-gcm',
678
+ this.encryptionKey,
679
+ );
680
+ decipher.setAuthTag(Buffer.from(auditEvent[field].authTag, 'hex'));
681
+
682
+ let decrypted = decipher.update(
683
+ auditEvent[field].data,
684
+ 'hex',
685
+ 'utf8',
686
+ );
687
+ decrypted += decipher.final('utf8');
688
+
689
+ auditEvent[field] = JSON.parse(decrypted);
690
+ } catch (error) {
691
+ auditEvent[field] = { decryptionError: error.message };
692
+ }
693
+ }
694
+ }
695
+
696
+ return auditEvent;
697
+ }
698
+
699
+ _calculateSeverity(_category, _action, result) {
700
+ const severityMatrix = {
701
+ authentication: {
702
+ login_failed: result === 'blocked' ? 'HIGH' : 'MEDIUM',
703
+ login: 'LOW',
704
+ logout: 'LOW',
705
+ password_change: 'MEDIUM',
706
+ mfa_enabled: 'MEDIUM',
707
+ },
708
+ authorization: {
709
+ access_denied: 'HIGH',
710
+ access_granted: 'LOW',
711
+ permission_changed: 'HIGH',
712
+ },
713
+ dataAccess: {
714
+ read: 'LOW',
715
+ export: 'MEDIUM',
716
+ query: 'LOW',
717
+ },
718
+ dataModification: {
719
+ delete: 'HIGH',
720
+ purge: 'CRITICAL',
721
+ create: 'LOW',
722
+ update: 'MEDIUM',
723
+ },
724
+ systemChanges: {
725
+ config_change: 'HIGH',
726
+ user_management: 'HIGH',
727
+ role_change: 'HIGH',
728
+ },
729
+ };
730
+
731
+ return severityMatrix[_category]?.[_action] || 'MEDIUM';
732
+ }
733
+
734
+ _sanitizeQuery(query) {
735
+ // Remove sensitive data from queries
736
+ return query.replace(/password|token|key|secret/gi, '[REDACTED]');
737
+ }
738
+
739
+ _sanitizeValue(value) {
740
+ if (
741
+ typeof value === 'string' &&
742
+ (value.includes('password') ||
743
+ value.includes('token') ||
744
+ value.includes('key'))
745
+ ) {
746
+ return '[REDACTED]';
747
+ }
748
+ return value;
749
+ }
750
+
751
+ _sanitizeParameters(params) {
752
+ const sanitized = { ...params };
753
+ const sensitiveKeys = ['password', 'token', 'key', 'secret', 'credential'];
754
+
755
+ for (const key of Object.keys(sanitized)) {
756
+ if (
757
+ sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive))
758
+ ) {
759
+ sanitized[key] = '[REDACTED]';
760
+ }
761
+ }
762
+
763
+ return sanitized;
764
+ }
765
+
766
+ _hashApiKey(apiKey) {
767
+ return crypto
768
+ .createHash('sha256')
769
+ .update(apiKey)
770
+ .digest('hex')
771
+ .substring(0, 16);
772
+ }
773
+
774
+ _generateEncryptionKey() {
775
+ return crypto.randomBytes(32);
776
+ }
777
+
778
+ _generateSigningKey() {
779
+ return crypto.randomBytes(64);
780
+ }
781
+
782
+ async _initializeIntegrityChain() {
783
+ const integrityFile = path.join(
784
+ this._config.logDir,
785
+ 'integrity',
786
+ 'chain.json',
787
+ );
788
+
789
+ try {
790
+ await fs.access(integrityFile);
791
+ } catch {
792
+ // Create initial integrity chain
793
+ const initialChain = {
794
+ created: new Date().toISOString(),
795
+ lastHash: crypto.createHash('sha256').update('genesis').digest('hex'),
796
+ sequence: 0,
797
+ };
798
+
799
+ await fs.writeFile(integrityFile, JSON.stringify(initialChain, null, 2));
800
+ }
801
+ }
802
+
803
+ async _updateIntegrityChain(logs) {
804
+ const integrityFile = path.join(
805
+ this._config.logDir,
806
+ 'integrity',
807
+ 'chain.json',
808
+ );
809
+ const chain = JSON.parse(await fs.readFile(integrityFile, 'utf8'));
810
+
811
+ for (const log of logs) {
812
+ const blockData = {
813
+ sequence: log.sequence,
814
+ timestamp: log.metadata.timestamp,
815
+ hash: log.integrity,
816
+ previousHash: chain.lastHash,
817
+ };
818
+
819
+ chain.lastHash = crypto
820
+ .createHash('sha256')
821
+ .update(JSON.stringify(blockData))
822
+ .digest('hex');
823
+ chain.sequence = log.sequence;
824
+ }
825
+
826
+ chain.lastUpdated = new Date().toISOString();
827
+ await fs.writeFile(integrityFile, JSON.stringify(chain, null, 2));
828
+ }
829
+
830
+ async _signAuditEvent(auditEvent) {
831
+ const data = JSON.stringify(auditEvent);
832
+ return crypto
833
+ .createHmac('sha256', this.signingKey)
834
+ .update(data)
835
+ .digest('hex');
836
+ }
837
+
838
+ async _verifySignature(auditEvent) {
839
+ const { signature, ...eventData } = auditEvent;
840
+ const expectedSignature = await this._signAuditEvent(eventData);
841
+ return signature === expectedSignature;
842
+ }
843
+
844
+ async _getLogFilesInRange(startDate, endDate) {
845
+ const files = [];
846
+ const currentDate = new Date(startDate);
847
+
848
+ while (currentDate <= endDate) {
849
+ const dateStr = currentDate.toISOString().split('T')[0];
850
+ const filename = `audit-${dateStr}.jsonl`;
851
+ const filepath = path.join(this._config.logDir, 'daily', filename);
852
+
853
+ try {
854
+ await fs.access(filepath);
855
+ files.push(filepath);
856
+ } catch {
857
+ // File doesn't exist, skip
858
+ }
859
+
860
+ currentDate.setDate(currentDate.getDate() + 1);
861
+ }
862
+
863
+ return files;
864
+ }
865
+
866
+ async _readLogFile(filepath) {
867
+ const content = await fs.readFile(filepath, 'utf8');
868
+ return content
869
+ .trim()
870
+ .split('\n')
871
+ .map((line) => JSON.parse(line));
872
+ }
873
+
874
+ _matchesQuery(log, query) {
875
+ if (query.tenantId && log._tenantId !== query._tenantId) return false;
876
+ if (query.userId && log._userId !== query._userId) return false;
877
+ if (query.category && log._category !== query._category) return false;
878
+ if (query.action && log._action !== query._action) return false;
879
+ if (query.severity && log.metadata._severity !== query._severity)
880
+ return false;
881
+ if (
882
+ query.correlationId &&
883
+ log.metadata._correlationId !== query._correlationId
884
+ )
885
+ return false;
886
+
887
+ const logTime = new Date(log.metadata.timestamp);
888
+ if (query.startDate && logTime < new Date(query.startDate)) return false;
889
+ if (query.endDate && logTime > new Date(query.endDate)) return false;
890
+
891
+ return true;
892
+ }
893
+
894
+ _checkCompliance(log, standard) {
895
+ // Mock compliance checking - would integrate with actual compliance frameworks
896
+ const requirements = {
897
+ GDPR: [
898
+ 'data_processing_lawfulness',
899
+ 'consent_management',
900
+ 'data_subject_rights',
901
+ ],
902
+ HIPAA: ['access_controls', 'audit_logs', 'data_encryption'],
903
+ SOC2: ['access_controls', 'system_monitoring', 'incident_response'],
904
+ 'PCI-DSS': ['access_controls', 'network_security', 'data_encryption'],
905
+ };
906
+
907
+ return {
908
+ requirement: requirements[standard]?.[0] || 'general_compliance',
909
+ violation: false,
910
+ evidence: log.metadata._correlationId,
911
+ };
912
+ }
913
+
914
+ async _sendToWebhook(logs) {
915
+ if (!this._config.realtime.webhookUrl) return;
916
+
917
+ try {
918
+ // Mock webhook sending - would use actual HTTP client
919
+ console.log(`Sending ${logs.length} audit logs to webhook`);
920
+ // eslint-disable-line no-console
921
+ } catch (error) {
922
+ this.emit('webhook_failed', { error: error.message, count: logs.length });
923
+ }
924
+ }
925
+
926
+ /**
927
+ * Cleanup old logs based on retention policy
928
+ */
929
+ async cleanupOldLogs() {
930
+ const now = new Date();
931
+ const cleanupResults = {
932
+ filesRemoved: 0,
933
+ bytesFreed: 0,
934
+ errors: [],
935
+ };
936
+
937
+ try {
938
+ const dailyDir = path.join(this._config.logDir, 'daily');
939
+ const files = await fs.readdir(dailyDir);
940
+
941
+ for (const file of files) {
942
+ if (!file.startsWith('audit-') || !file.endsWith('.jsonl')) continue;
943
+
944
+ const filepath = path.join(dailyDir, file);
945
+ const stats = await fs.stat(filepath);
946
+ const fileAge = (now - stats.mtime) / (1000 * 60 * 60 * 24); // days
947
+
948
+ if (fileAge > this._config.retention.days) {
949
+ await fs.unlink(filepath);
950
+ cleanupResults.filesRemoved++;
951
+ cleanupResults.bytesFreed += stats.size;
952
+ }
953
+ }
954
+ } catch (error) {
955
+ cleanupResults.errors.push(error.message);
956
+ }
957
+
958
+ this.emit('cleanup_completed', cleanupResults);
959
+ return cleanupResults;
960
+ }
961
+ }
962
+
963
+ module.exports = {
964
+ AuditLogger,
965
+ };
966
+
967
+ // Ensure module.exports is properly defined