@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.
- package/.ragrc.schema.json +218 -0
- package/README.md +651 -393
- package/bin/cli.js +8 -14
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +22 -7
- package/package.json +17 -13
- package/src/ai/adaptive-retrieval.js +191 -0
- package/src/ai/federated-learning.js +214 -0
- package/src/ai/federation/federated-learning-coordinator.js +345 -0
- package/src/ai/federation.js +76 -0
- package/src/ai/index-fixed.js +509 -0
- package/src/ai/index.js +33 -0
- package/src/ai/model-trainer.js +217 -0
- package/src/ai/model-training.js +205 -0
- package/src/ai/module-template.js +37 -0
- package/src/ai/multimodal/multi-modal-processor.js +345 -0
- package/src/ai/multimodal-processing.js +268 -0
- package/src/ai/multimodal.js +71 -0
- package/src/ai/orchestrator.js +70 -0
- package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
- package/src/ai/retrieval-engine.js +69 -0
- package/src/ai/training/model-training-orchestrator.js +228 -0
- package/src/ci/workflow-analyzer.js +71 -0
- package/src/cli/commands/ai-ml.js +967 -0
- package/src/cli/commands/docs.js +228 -0
- package/src/cli/commands/dx.js +538 -0
- package/src/cli/commands/plugin-hub.js +875 -0
- package/src/cli/doctor-command.js +639 -0
- package/src/cli/enhanced-cli-commands.js +945 -0
- package/src/cli/interactive-wizard.js +997 -0
- package/src/cli/plugin-marketplace-commands.js +869 -0
- package/src/cli.js +17 -0
- package/src/config/enhanced-ragrc-schema.js +632 -0
- package/src/config/load-config.js +54 -0
- package/src/config/load-plugin-config.js +69 -0
- package/src/config/normalize-config.js +105 -0
- package/src/config/schema-validator.js +315 -0
- package/src/config/validate-plugin-schema.js +35 -0
- package/src/config/validate-schema.js +113 -0
- package/src/contracts/plugin-contracts.js +33 -0
- package/src/core/create-pipeline.js +99 -0
- package/src/core/dependency-injection.js +242 -0
- package/src/core/observability/event-logger.js +241 -0
- package/src/core/observability/instrumented-pipeline.js +609 -0
- package/src/core/observability/metrics.js +497 -0
- package/src/core/observability/tracing.js +781 -0
- package/src/core/performance/benchmark.js +516 -0
- package/src/core/performance/parallel-processor.js +240 -0
- package/src/core/performance/streaming-safeguards.js +611 -0
- package/src/core/pipeline-factory.js +60 -0
- package/src/core/plugin-contracts.js +89 -0
- package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
- package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
- package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
- package/src/core/plugin-marketplace/version-resolver.js +61 -0
- package/src/core/plugin-registry.js +265 -0
- package/src/dag/dag-engine.js +954 -0
- package/src/dag/dag-node.js +76 -0
- package/src/dag/enhanced-dag-engine.js +822 -0
- package/src/dx/index.js +40 -0
- package/src/dx/integration-templates.js +665 -0
- package/src/dx/performance-profiler.js +968 -0
- package/src/dx/realtime-debugger.js +755 -0
- package/src/dx/visual-pipeline-builder.js +578 -0
- package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
- package/src/ecosystem/plugin-certification.js +580 -0
- package/src/ecosystem/plugin-hub.js +821 -0
- package/src/enterprise/audit-logging.js +967 -0
- package/src/enterprise/data-governance.js +408 -0
- package/src/enterprise/multi-tenancy.js +496 -0
- package/src/enterprise/sso-integration.js +903 -0
- package/src/evaluate/evaluator.js +52 -0
- package/src/evaluate/scoring.js +91 -0
- package/src/index.js +67 -0
- package/src/ingest.js +59 -0
- package/src/loader/csv-loader.js +38 -0
- package/src/loader/directory-loader.js +48 -0
- package/src/loader/html-loader.js +62 -0
- package/src/loader/markdown-loader.js +67 -0
- package/src/mocks/openai-embedder.js +119 -0
- package/src/mocks/openai-llm.js +77 -0
- package/src/mocks/pdf-loader.js +21 -0
- package/src/mocks/pinecone-retriever.js +106 -0
- package/src/observability/audit-logger.js +758 -0
- package/src/observability/dashboard-config.json +675 -0
- package/src/observability/event-logger.js +310 -0
- package/src/observability/metrics.js +691 -0
- package/src/observability/security-monitor.js +830 -0
- package/src/observability/slo-monitor.js +319 -0
- package/src/observability/telemetry.js +686 -0
- package/src/pipeline/pipeline.js +18 -0
- package/src/plugins/sample-embedder.js +53 -0
- package/src/plugins/sample-llm.js +30 -0
- package/src/plugins/sample-loader.js +24 -0
- package/src/plugins/sample-retriever.js +84 -0
- package/src/query.js +117 -0
- package/src/reranker/llm-reranker.js +85 -0
- package/src/scripts/script-utilities.js +36 -0
- package/src/security/plugin-sandbox.js +586 -0
- package/src/security/plugin-signature-verifier.js +414 -0
- package/src/security/validator.js +36 -0
- package/src/utils/ci/diagnostic-reporter.js +57 -0
- package/src/utils/logger.js +211 -0
- package/src/utils/performance-monitor.js +561 -0
- package/src/utils/plugin-scaffolder.js +447 -0
- package/src/utils/retry-policy.js +443 -0
- package/src/utils/retry.js +107 -0
- package/src/utils/safe-expression-evaluator.js +579 -0
- package/src/utils/structured-logger.js +361 -0
- 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
|