@revealui/security 0.2.4 → 0.2.5

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.
@@ -0,0 +1,21 @@
1
+ import {
2
+ AuditReportGenerator,
3
+ AuditSystem,
4
+ AuditTrail,
5
+ InMemoryAuditStorage,
6
+ audit,
7
+ createAuditMiddleware,
8
+ signAuditEntry,
9
+ verifyAuditEntry
10
+ } from "./chunk-Q5KAPSST.js";
11
+ export {
12
+ AuditReportGenerator,
13
+ AuditSystem,
14
+ AuditTrail,
15
+ InMemoryAuditStorage,
16
+ audit,
17
+ createAuditMiddleware,
18
+ signAuditEntry,
19
+ verifyAuditEntry
20
+ };
21
+ //# sourceMappingURL=audit-UF7PIYBU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,429 @@
1
+ // src/audit.ts
2
+ var AuditSystem = class {
3
+ storage;
4
+ filters = [];
5
+ constructor(storage) {
6
+ this.storage = storage;
7
+ }
8
+ /**
9
+ * Replace the backing storage (e.g. swap InMemory for Postgres at startup).
10
+ * Events already written to the old storage are NOT migrated.
11
+ */
12
+ setStorage(storage) {
13
+ this.storage = storage;
14
+ }
15
+ /**
16
+ * Log audit event
17
+ */
18
+ async log(event) {
19
+ const fullEvent = {
20
+ ...event,
21
+ id: crypto.randomUUID(),
22
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
23
+ };
24
+ const shouldLog = this.filters.every((filter) => filter(fullEvent));
25
+ if (!shouldLog) {
26
+ return;
27
+ }
28
+ await this.storage.write(fullEvent);
29
+ }
30
+ /**
31
+ * Log authentication event
32
+ */
33
+ async logAuth(type, actorId, result, metadata) {
34
+ await this.log({
35
+ type,
36
+ severity: result === "failure" ? "medium" : "low",
37
+ actor: {
38
+ id: actorId,
39
+ type: "user"
40
+ },
41
+ action: type.replace("auth.", ""),
42
+ result,
43
+ metadata
44
+ });
45
+ }
46
+ /**
47
+ * Log data access event
48
+ */
49
+ async logDataAccess(action, actorId, resourceType, resourceId, result, changes) {
50
+ await this.log({
51
+ type: `data.${action}`,
52
+ severity: action === "delete" ? "high" : "medium",
53
+ actor: {
54
+ id: actorId,
55
+ type: "user"
56
+ },
57
+ resource: {
58
+ type: resourceType,
59
+ id: resourceId
60
+ },
61
+ action,
62
+ result,
63
+ changes
64
+ });
65
+ }
66
+ /**
67
+ * Log permission change
68
+ */
69
+ async logPermissionChange(action, actorId, targetUserId, permission, result) {
70
+ await this.log({
71
+ type: `permission.${action}`,
72
+ severity: "high",
73
+ actor: {
74
+ id: actorId,
75
+ type: "user"
76
+ },
77
+ resource: {
78
+ type: "user",
79
+ id: targetUserId
80
+ },
81
+ action,
82
+ result,
83
+ metadata: {
84
+ permission
85
+ }
86
+ });
87
+ }
88
+ /**
89
+ * Log security event
90
+ */
91
+ async logSecurityEvent(type, severity, actorId, message, metadata) {
92
+ await this.log({
93
+ type: `security.${type}`,
94
+ severity,
95
+ actor: {
96
+ id: actorId,
97
+ type: "user"
98
+ },
99
+ action: type,
100
+ result: "failure",
101
+ message,
102
+ metadata
103
+ });
104
+ }
105
+ /**
106
+ * Log GDPR event
107
+ */
108
+ async logGDPREvent(type, actorId, result, metadata) {
109
+ await this.log({
110
+ type: `gdpr.${type}`,
111
+ severity: "high",
112
+ actor: {
113
+ id: actorId,
114
+ type: "user"
115
+ },
116
+ action: type,
117
+ result,
118
+ metadata
119
+ });
120
+ }
121
+ /**
122
+ * Query audit logs
123
+ */
124
+ async query(query) {
125
+ return this.storage.query(query);
126
+ }
127
+ /**
128
+ * Count audit logs
129
+ */
130
+ async count(query) {
131
+ return this.storage.count(query);
132
+ }
133
+ /**
134
+ * Add filter
135
+ */
136
+ addFilter(filter) {
137
+ this.filters.push(filter);
138
+ }
139
+ /**
140
+ * Remove filter
141
+ */
142
+ removeFilter(filter) {
143
+ const index = this.filters.indexOf(filter);
144
+ if (index > -1) {
145
+ this.filters.splice(index, 1);
146
+ }
147
+ }
148
+ };
149
+ var InMemoryAuditStorage = class {
150
+ events = [];
151
+ maxEvents;
152
+ constructor(maxEvents = 1e4) {
153
+ this.maxEvents = maxEvents;
154
+ }
155
+ async write(event) {
156
+ this.events.push(event);
157
+ if (this.events.length > this.maxEvents) {
158
+ this.events.shift();
159
+ }
160
+ }
161
+ async query(query) {
162
+ let results = [...this.events];
163
+ if (query.types && query.types.length > 0) {
164
+ results = results.filter((e) => query.types?.includes(e.type));
165
+ }
166
+ if (query.actorId) {
167
+ results = results.filter((e) => e.actor.id === query.actorId);
168
+ }
169
+ if (query.resourceType) {
170
+ results = results.filter((e) => e.resource?.type === query.resourceType);
171
+ }
172
+ if (query.resourceId) {
173
+ results = results.filter((e) => e.resource?.id === query.resourceId);
174
+ }
175
+ if (query.startDate) {
176
+ const startDate = query.startDate;
177
+ results = results.filter((e) => new Date(e.timestamp) >= startDate);
178
+ }
179
+ if (query.endDate) {
180
+ const endDate = query.endDate;
181
+ results = results.filter((e) => new Date(e.timestamp) <= endDate);
182
+ }
183
+ if (query.severity && query.severity.length > 0) {
184
+ results = results.filter((e) => query.severity?.includes(e.severity));
185
+ }
186
+ if (query.result && query.result.length > 0) {
187
+ results = results.filter((e) => query.result?.includes(e.result));
188
+ }
189
+ results.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
190
+ const offset = query.offset || 0;
191
+ const limit = query.limit || 100;
192
+ return results.slice(offset, offset + limit);
193
+ }
194
+ async count(query) {
195
+ const results = await this.query({ ...query, limit: void 0, offset: void 0 });
196
+ return results.length;
197
+ }
198
+ /**
199
+ * Clear all events
200
+ */
201
+ clear() {
202
+ this.events = [];
203
+ }
204
+ /**
205
+ * Get all events
206
+ */
207
+ getAll() {
208
+ return [...this.events];
209
+ }
210
+ };
211
+ function AuditTrail(type, action, options) {
212
+ return (_target, _propertyKey, descriptor) => {
213
+ const originalMethod = descriptor.value;
214
+ descriptor.value = async function(...args) {
215
+ const actorId = this.user?.id || "system";
216
+ const before = options?.captureChanges ? args[0] : void 0;
217
+ let result = "success";
218
+ let error;
219
+ try {
220
+ const returnValue = await originalMethod.apply(this, args);
221
+ if (this.audit) {
222
+ await this.audit.log({
223
+ type,
224
+ severity: options?.severity || "medium",
225
+ actor: {
226
+ id: actorId,
227
+ type: "user"
228
+ },
229
+ resource: options?.resourceType ? {
230
+ type: options.resourceType,
231
+ id: args[0]?.id || "unknown"
232
+ } : void 0,
233
+ action,
234
+ result,
235
+ changes: options?.captureChanges ? {
236
+ before,
237
+ after: returnValue
238
+ } : void 0
239
+ });
240
+ }
241
+ return returnValue;
242
+ } catch (err) {
243
+ result = "failure";
244
+ error = err;
245
+ if (this.audit) {
246
+ await this.audit.log({
247
+ type,
248
+ severity: "high",
249
+ actor: {
250
+ id: actorId,
251
+ type: "user"
252
+ },
253
+ resource: options?.resourceType ? {
254
+ type: options.resourceType,
255
+ id: args[0]?.id || "unknown"
256
+ } : void 0,
257
+ action,
258
+ result,
259
+ message: error.message
260
+ });
261
+ }
262
+ throw error;
263
+ }
264
+ };
265
+ return descriptor;
266
+ };
267
+ }
268
+ function createAuditMiddleware(audit2, getUser) {
269
+ return async (request, next) => {
270
+ const user = getUser(request);
271
+ const startTime = Date.now();
272
+ try {
273
+ const response = await next();
274
+ await audit2.log({
275
+ type: "data.read",
276
+ severity: "low",
277
+ actor: {
278
+ id: user.id,
279
+ type: "user",
280
+ ip: user.ip,
281
+ userAgent: user.userAgent
282
+ },
283
+ action: request.method,
284
+ result: "success",
285
+ metadata: {
286
+ path: request.url,
287
+ duration: Date.now() - startTime,
288
+ status: response.status
289
+ }
290
+ });
291
+ return response;
292
+ } catch (error) {
293
+ await audit2.log({
294
+ type: "data.read",
295
+ severity: "medium",
296
+ actor: {
297
+ id: user.id,
298
+ type: "user",
299
+ ip: user.ip,
300
+ userAgent: user.userAgent
301
+ },
302
+ action: request.method,
303
+ result: "failure",
304
+ message: error instanceof Error ? error.message : "Unknown error",
305
+ metadata: {
306
+ path: request.url,
307
+ duration: Date.now() - startTime
308
+ }
309
+ });
310
+ throw error;
311
+ }
312
+ };
313
+ }
314
+ var AuditReportGenerator = class {
315
+ constructor(audit2) {
316
+ this.audit = audit2;
317
+ }
318
+ /**
319
+ * Generate security report
320
+ */
321
+ async generateSecurityReport(startDate, endDate) {
322
+ const allEvents = await this.audit.query({
323
+ startDate,
324
+ endDate
325
+ });
326
+ const securityViolations = allEvents.filter((e) => e.type.startsWith("security.")).length;
327
+ const failedLogins = allEvents.filter((e) => e.type === "auth.failed_login").length;
328
+ const permissionChanges = allEvents.filter((e) => e.type.startsWith("permission.")).length;
329
+ const dataExports = allEvents.filter((e) => e.type === "data.export").length;
330
+ const criticalEvents = allEvents.filter((e) => e.severity === "critical");
331
+ return {
332
+ totalEvents: allEvents.length,
333
+ securityViolations,
334
+ failedLogins,
335
+ permissionChanges,
336
+ dataExports,
337
+ criticalEvents
338
+ };
339
+ }
340
+ /**
341
+ * Generate user activity report
342
+ */
343
+ async generateUserActivityReport(userId, startDate, endDate) {
344
+ const events = await this.audit.query({
345
+ actorId: userId,
346
+ startDate,
347
+ endDate
348
+ });
349
+ const actionsByType = events.reduce(
350
+ (acc, event) => {
351
+ acc[event.type] = (acc[event.type] || 0) + 1;
352
+ return acc;
353
+ },
354
+ {}
355
+ );
356
+ const failedActions = events.filter((e) => e.result === "failure").length;
357
+ return {
358
+ totalActions: events.length,
359
+ actionsByType,
360
+ failedActions,
361
+ recentActions: events.slice(0, 10)
362
+ };
363
+ }
364
+ /**
365
+ * Generate compliance report
366
+ */
367
+ async generateComplianceReport(startDate, endDate) {
368
+ const events = await this.audit.query({
369
+ startDate,
370
+ endDate
371
+ });
372
+ const dataAccesses = events.filter((e) => e.type === "data.read").length;
373
+ const dataModifications = events.filter(
374
+ (e) => e.type === "data.update" || e.type === "data.create"
375
+ ).length;
376
+ const dataDeletions = events.filter((e) => e.type === "data.delete").length;
377
+ const gdprRequests = events.filter((e) => e.type.startsWith("gdpr.")).length;
378
+ const auditTrailComplete = this.checkAuditTrailContinuity(events);
379
+ return {
380
+ dataAccesses,
381
+ dataModifications,
382
+ dataDeletions,
383
+ gdprRequests,
384
+ auditTrailComplete
385
+ };
386
+ }
387
+ /**
388
+ * Check audit trail continuity
389
+ */
390
+ checkAuditTrailContinuity(events) {
391
+ if (events.length === 0) return true;
392
+ const sorted = events.sort(
393
+ (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
394
+ );
395
+ return sorted.length > 0;
396
+ }
397
+ };
398
+ async function signAuditEntry(entry, secret) {
399
+ const { createHmac } = await import("crypto");
400
+ const canonical = JSON.stringify({
401
+ timestamp: entry.timestamp,
402
+ eventType: entry.eventType,
403
+ severity: entry.severity,
404
+ agentId: entry.agentId,
405
+ payload: entry.payload
406
+ });
407
+ return createHmac("sha256", secret).update(canonical).digest("hex");
408
+ }
409
+ async function verifyAuditEntry(entry, signature, secret) {
410
+ const { timingSafeEqual } = await import("crypto");
411
+ const expected = await signAuditEntry(entry, secret);
412
+ if (expected.length !== signature.length) {
413
+ return false;
414
+ }
415
+ return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
416
+ }
417
+ var audit = new AuditSystem(new InMemoryAuditStorage());
418
+
419
+ export {
420
+ AuditSystem,
421
+ InMemoryAuditStorage,
422
+ AuditTrail,
423
+ createAuditMiddleware,
424
+ AuditReportGenerator,
425
+ signAuditEntry,
426
+ verifyAuditEntry,
427
+ audit
428
+ };
429
+ //# sourceMappingURL=chunk-Q5KAPSST.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/audit.ts"],"sourcesContent":["/**\n * Audit Logging System\n *\n * Track security-relevant events and user actions for compliance\n */\n\nexport type AuditEventType =\n | 'auth.login'\n | 'auth.logout'\n | 'auth.failed_login'\n | 'auth.password_change'\n | 'auth.password_reset'\n | 'auth.mfa_enabled'\n | 'auth.mfa_disabled'\n | 'user.create'\n | 'user.update'\n | 'user.delete'\n | 'user.view'\n | 'data.create'\n | 'data.read'\n | 'data.update'\n | 'data.delete'\n | 'data.export'\n | 'permission.grant'\n | 'permission.revoke'\n | 'role.assign'\n | 'role.remove'\n | 'config.change'\n | 'security.violation'\n | 'security.alert'\n | 'gdpr.consent'\n | 'gdpr.data_request'\n | 'gdpr.data_deletion'\n | `data.${string}`\n | `permission.${string}`\n | `security.${string}`\n | `gdpr.${string}`;\n\nexport type AuditSeverity = 'low' | 'medium' | 'high' | 'critical';\n\nexport interface AuditEvent {\n id: string;\n timestamp: string;\n type: AuditEventType;\n severity: AuditSeverity;\n actor: {\n id: string;\n type: 'user' | 'system' | 'api';\n ip?: string;\n userAgent?: string;\n };\n resource?: {\n type: string;\n id: string;\n name?: string;\n };\n action: string;\n result: 'success' | 'failure' | 'partial';\n changes?: {\n before?: Record<string, unknown>;\n after?: Record<string, unknown>;\n };\n metadata?: Record<string, unknown>;\n message?: string;\n}\n\nexport interface AuditQuery {\n types?: AuditEventType[];\n actorId?: string;\n resourceType?: string;\n resourceId?: string;\n startDate?: Date;\n endDate?: Date;\n severity?: AuditSeverity[];\n result?: ('success' | 'failure' | 'partial')[];\n limit?: number;\n offset?: number;\n}\n\nexport interface AuditStorage {\n write(event: AuditEvent): Promise<void>;\n query(query: AuditQuery): Promise<AuditEvent[]>;\n count(query: AuditQuery): Promise<number>;\n}\n\n/**\n * Audit logging system\n */\nexport class AuditSystem {\n private storage: AuditStorage;\n private filters: Array<(event: AuditEvent) => boolean> = [];\n\n constructor(storage: AuditStorage) {\n this.storage = storage;\n }\n\n /**\n * Replace the backing storage (e.g. swap InMemory for Postgres at startup).\n * Events already written to the old storage are NOT migrated.\n */\n setStorage(storage: AuditStorage): void {\n this.storage = storage;\n }\n\n /**\n * Log audit event\n */\n async log(event: Omit<AuditEvent, 'id' | 'timestamp'>): Promise<void> {\n const fullEvent: AuditEvent = {\n ...event,\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n };\n\n // Apply filters\n const shouldLog = this.filters.every((filter) => filter(fullEvent));\n\n if (!shouldLog) {\n return;\n }\n\n await this.storage.write(fullEvent);\n }\n\n /**\n * Log authentication event\n */\n async logAuth(\n type: Extract<\n AuditEventType,\n 'auth.login' | 'auth.logout' | 'auth.failed_login' | 'auth.password_change'\n >,\n actorId: string,\n result: 'success' | 'failure',\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n await this.log({\n type,\n severity: result === 'failure' ? 'medium' : 'low',\n actor: {\n id: actorId,\n type: 'user',\n },\n action: (type as string).replace('auth.', ''),\n result,\n metadata,\n });\n }\n\n /**\n * Log data access event\n */\n async logDataAccess(\n action: 'create' | 'read' | 'update' | 'delete',\n actorId: string,\n resourceType: string,\n resourceId: string,\n result: 'success' | 'failure',\n changes?: { before?: Record<string, unknown>; after?: Record<string, unknown> },\n ): Promise<void> {\n await this.log({\n type: `data.${action}` as AuditEventType,\n severity: action === 'delete' ? 'high' : 'medium',\n actor: {\n id: actorId,\n type: 'user',\n },\n resource: {\n type: resourceType,\n id: resourceId,\n },\n action,\n result,\n changes,\n });\n }\n\n /**\n * Log permission change\n */\n async logPermissionChange(\n action: 'grant' | 'revoke',\n actorId: string,\n targetUserId: string,\n permission: string,\n result: 'success' | 'failure',\n ): Promise<void> {\n await this.log({\n type: `permission.${action}` as AuditEventType,\n severity: 'high',\n actor: {\n id: actorId,\n type: 'user',\n },\n resource: {\n type: 'user',\n id: targetUserId,\n },\n action,\n result,\n metadata: {\n permission,\n },\n });\n }\n\n /**\n * Log security event\n */\n async logSecurityEvent(\n type: 'violation' | 'alert',\n severity: AuditSeverity,\n actorId: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n await this.log({\n type: `security.${type}` as AuditEventType,\n severity,\n actor: {\n id: actorId,\n type: 'user',\n },\n action: type,\n result: 'failure',\n message,\n metadata,\n });\n }\n\n /**\n * Log GDPR event\n */\n async logGDPREvent(\n type: 'consent' | 'data_request' | 'data_deletion',\n actorId: string,\n result: 'success' | 'failure',\n metadata?: Record<string, unknown>,\n ): Promise<void> {\n await this.log({\n type: `gdpr.${type}` as AuditEventType,\n severity: 'high',\n actor: {\n id: actorId,\n type: 'user',\n },\n action: type,\n result,\n metadata,\n });\n }\n\n /**\n * Query audit logs\n */\n async query(query: AuditQuery): Promise<AuditEvent[]> {\n return this.storage.query(query);\n }\n\n /**\n * Count audit logs\n */\n async count(query: AuditQuery): Promise<number> {\n return this.storage.count(query);\n }\n\n /**\n * Add filter\n */\n addFilter(filter: (event: AuditEvent) => boolean): void {\n this.filters.push(filter);\n }\n\n /**\n * Remove filter\n */\n removeFilter(filter: (event: AuditEvent) => boolean): void {\n const index = this.filters.indexOf(filter);\n if (index > -1) {\n this.filters.splice(index, 1);\n }\n }\n}\n\n/**\n * In-memory audit storage (for development)\n */\nexport class InMemoryAuditStorage implements AuditStorage {\n private events: AuditEvent[] = [];\n private maxEvents: number;\n\n constructor(maxEvents: number = 10000) {\n this.maxEvents = maxEvents;\n }\n\n async write(event: AuditEvent): Promise<void> {\n this.events.push(event);\n\n // Trim old events\n if (this.events.length > this.maxEvents) {\n this.events.shift();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditEvent[]> {\n let results = [...this.events];\n\n // Filter by type\n if (query.types && query.types.length > 0) {\n results = results.filter((e) => query.types?.includes(e.type));\n }\n\n // Filter by actor\n if (query.actorId) {\n results = results.filter((e) => e.actor.id === query.actorId);\n }\n\n // Filter by resource\n if (query.resourceType) {\n results = results.filter((e) => e.resource?.type === query.resourceType);\n }\n\n if (query.resourceId) {\n results = results.filter((e) => e.resource?.id === query.resourceId);\n }\n\n // Filter by date range\n if (query.startDate) {\n const startDate = query.startDate;\n results = results.filter((e) => new Date(e.timestamp) >= startDate);\n }\n\n if (query.endDate) {\n const endDate = query.endDate;\n results = results.filter((e) => new Date(e.timestamp) <= endDate);\n }\n\n // Filter by severity\n if (query.severity && query.severity.length > 0) {\n results = results.filter((e) => query.severity?.includes(e.severity));\n }\n\n // Filter by result\n if (query.result && query.result.length > 0) {\n results = results.filter((e) => query.result?.includes(e.result));\n }\n\n // Sort by timestamp (newest first)\n results.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());\n\n // Apply pagination\n const offset = query.offset || 0;\n const limit = query.limit || 100;\n\n return results.slice(offset, offset + limit);\n }\n\n async count(query: AuditQuery): Promise<number> {\n const results = await this.query({ ...query, limit: undefined, offset: undefined });\n return results.length;\n }\n\n /**\n * Clear all events\n */\n clear(): void {\n this.events = [];\n }\n\n /**\n * Get all events\n */\n getAll(): AuditEvent[] {\n return [...this.events];\n }\n}\n\n/**\n * Audit trail decorator\n */\nexport function AuditTrail(\n type: AuditEventType,\n action: string,\n options?: {\n severity?: AuditSeverity;\n captureChanges?: boolean;\n resourceType?: string;\n },\n) {\n return (_target: object, _propertyKey: string, descriptor: PropertyDescriptor) => {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (\n this: { user?: { id?: string }; audit?: AuditSystem },\n ...args: unknown[]\n ) {\n const actorId = this.user?.id || 'system';\n const before = options?.captureChanges ? args[0] : undefined;\n\n let result: 'success' | 'failure' | 'partial' = 'success';\n let error: Error | undefined;\n\n try {\n const returnValue = await originalMethod.apply(this, args);\n\n // Log audit event\n if (this.audit) {\n await this.audit.log({\n type,\n severity: options?.severity || 'medium',\n actor: {\n id: actorId,\n type: 'user',\n },\n resource: options?.resourceType\n ? {\n type: options.resourceType,\n id: (args[0] as { id?: string })?.id || 'unknown',\n }\n : undefined,\n action,\n result,\n changes: options?.captureChanges\n ? {\n before: before as Record<string, unknown> | undefined,\n after: returnValue as Record<string, unknown> | undefined,\n }\n : undefined,\n });\n }\n\n return returnValue;\n } catch (err) {\n result = 'failure';\n error = err as Error;\n\n // Log failure\n if (this.audit) {\n await this.audit.log({\n type,\n severity: 'high',\n actor: {\n id: actorId,\n type: 'user',\n },\n resource: options?.resourceType\n ? {\n type: options.resourceType,\n id: (args[0] as { id?: string })?.id || 'unknown',\n }\n : undefined,\n action,\n result,\n message: error.message,\n });\n }\n\n throw error;\n }\n };\n\n return descriptor;\n };\n}\n\n/**\n * Audit middleware\n */\nexport function createAuditMiddleware<TRequest = unknown, TResponse = unknown>(\n audit: AuditSystem,\n getUser: (request: TRequest) => { id: string; ip?: string; userAgent?: string },\n) {\n return async (\n request: TRequest & { method: string; url: string },\n next: () => Promise<TResponse & { status?: number }>,\n ) => {\n const user = getUser(request);\n const startTime = Date.now();\n\n try {\n const response = await next();\n\n // Log successful request\n await audit.log({\n type: 'data.read',\n severity: 'low',\n actor: {\n id: user.id,\n type: 'user',\n ip: user.ip,\n userAgent: user.userAgent,\n },\n action: request.method,\n result: 'success',\n metadata: {\n path: request.url,\n duration: Date.now() - startTime,\n status: response.status,\n },\n });\n\n return response;\n } catch (error) {\n // Log failed request\n await audit.log({\n type: 'data.read',\n severity: 'medium',\n actor: {\n id: user.id,\n type: 'user',\n ip: user.ip,\n userAgent: user.userAgent,\n },\n action: request.method,\n result: 'failure',\n message: error instanceof Error ? error.message : 'Unknown error',\n metadata: {\n path: request.url,\n duration: Date.now() - startTime,\n },\n });\n\n throw error;\n }\n };\n}\n\n/**\n * Audit report generator\n */\nexport class AuditReportGenerator {\n constructor(private audit: AuditSystem) {}\n\n /**\n * Generate security report\n */\n async generateSecurityReport(\n startDate: Date,\n endDate: Date,\n ): Promise<{\n totalEvents: number;\n securityViolations: number;\n failedLogins: number;\n permissionChanges: number;\n dataExports: number;\n criticalEvents: AuditEvent[];\n }> {\n const allEvents = await this.audit.query({\n startDate,\n endDate,\n });\n\n const securityViolations = allEvents.filter((e) => e.type.startsWith('security.')).length;\n\n const failedLogins = allEvents.filter((e) => e.type === 'auth.failed_login').length;\n\n const permissionChanges = allEvents.filter((e) => e.type.startsWith('permission.')).length;\n\n const dataExports = allEvents.filter((e) => e.type === 'data.export').length;\n\n const criticalEvents = allEvents.filter((e) => e.severity === 'critical');\n\n return {\n totalEvents: allEvents.length,\n securityViolations,\n failedLogins,\n permissionChanges,\n dataExports,\n criticalEvents,\n };\n }\n\n /**\n * Generate user activity report\n */\n async generateUserActivityReport(\n userId: string,\n startDate: Date,\n endDate: Date,\n ): Promise<{\n totalActions: number;\n actionsByType: Record<string, number>;\n failedActions: number;\n recentActions: AuditEvent[];\n }> {\n const events = await this.audit.query({\n actorId: userId,\n startDate,\n endDate,\n });\n\n const actionsByType = events.reduce(\n (acc, event) => {\n acc[event.type] = (acc[event.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n\n const failedActions = events.filter((e) => e.result === 'failure').length;\n\n return {\n totalActions: events.length,\n actionsByType,\n failedActions,\n recentActions: events.slice(0, 10),\n };\n }\n\n /**\n * Generate compliance report\n */\n async generateComplianceReport(\n startDate: Date,\n endDate: Date,\n ): Promise<{\n dataAccesses: number;\n dataModifications: number;\n dataDeletions: number;\n gdprRequests: number;\n auditTrailComplete: boolean;\n }> {\n const events = await this.audit.query({\n startDate,\n endDate,\n });\n\n const dataAccesses = events.filter((e) => e.type === 'data.read').length;\n\n const dataModifications = events.filter(\n (e) => e.type === 'data.update' || e.type === 'data.create',\n ).length;\n\n const dataDeletions = events.filter((e) => e.type === 'data.delete').length;\n\n const gdprRequests = events.filter((e) => e.type.startsWith('gdpr.')).length;\n\n // Check if audit trail is complete (no gaps)\n const auditTrailComplete = this.checkAuditTrailContinuity(events);\n\n return {\n dataAccesses,\n dataModifications,\n dataDeletions,\n gdprRequests,\n auditTrailComplete,\n };\n }\n\n /**\n * Check audit trail continuity\n */\n private checkAuditTrailContinuity(events: AuditEvent[]): boolean {\n if (events.length === 0) return true;\n\n // Sort by timestamp\n const sorted = events.sort(\n (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),\n );\n\n // Check for gaps (simplified - just check if we have events)\n return sorted.length > 0;\n }\n}\n\n// =============================================================================\n// Audit Log Integrity — HMAC-SHA256 Signing\n// =============================================================================\n\n/** Fields included in the HMAC signature for tamper detection. */\ninterface SignableFields {\n timestamp: string;\n eventType: string;\n severity: string;\n agentId: string;\n payload: unknown;\n}\n\n/**\n * Compute an HMAC-SHA256 signature over the canonical fields of an audit entry.\n *\n * The signature covers `timestamp`, `eventType`, `severity`, `agentId`, and\n * `payload` — the immutable core of every audit record. Changing any of\n * these fields after signing will cause verification to fail.\n *\n * @param entry - The audit entry fields to sign\n * @param secret - The HMAC secret key\n * @returns Hex-encoded HMAC-SHA256 signature\n */\nexport async function signAuditEntry(entry: SignableFields, secret: string): Promise<string> {\n const { createHmac } = await import('node:crypto');\n const canonical = JSON.stringify({\n timestamp: entry.timestamp,\n eventType: entry.eventType,\n severity: entry.severity,\n agentId: entry.agentId,\n payload: entry.payload,\n });\n return createHmac('sha256', secret).update(canonical).digest('hex');\n}\n\n/**\n * Verify an HMAC-SHA256 signature against the canonical fields of an audit entry.\n *\n * Uses timing-safe comparison to prevent timing attacks.\n *\n * @param entry - The audit entry fields to verify\n * @param signature - The hex-encoded HMAC-SHA256 signature to verify\n * @param secret - The HMAC secret key\n * @returns True if the signature is valid\n */\nexport async function verifyAuditEntry(\n entry: SignableFields,\n signature: string,\n secret: string,\n): Promise<boolean> {\n const { timingSafeEqual } = await import('node:crypto');\n const expected = await signAuditEntry(entry, secret);\n\n // Lengths must match for timingSafeEqual\n if (expected.length !== signature.length) {\n return false;\n }\n\n return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));\n}\n\n/**\n * Global audit system\n */\nexport const audit = new AuditSystem(new InMemoryAuditStorage());\n"],"mappings":";AAwFO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA,UAAiD,CAAC;AAAA,EAE1D,YAAY,SAAuB;AACjC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,SAA6B;AACtC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,OAA4D;AACpE,UAAM,YAAwB;AAAA,MAC5B,GAAG;AAAA,MACH,IAAI,OAAO,WAAW;AAAA,MACtB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAGA,UAAM,YAAY,KAAK,QAAQ,MAAM,CAAC,WAAW,OAAO,SAAS,CAAC;AAElE,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,KAAK,QAAQ,MAAM,SAAS;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,MAIA,SACA,QACA,UACe;AACf,UAAM,KAAK,IAAI;AAAA,MACb;AAAA,MACA,UAAU,WAAW,YAAY,WAAW;AAAA,MAC5C,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,QAAS,KAAgB,QAAQ,SAAS,EAAE;AAAA,MAC5C;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,QACA,SACA,cACA,YACA,QACA,SACe;AACf,UAAM,KAAK,IAAI;AAAA,MACb,MAAM,QAAQ,MAAM;AAAA,MACpB,UAAU,WAAW,WAAW,SAAS;AAAA,MACzC,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACJ,QACA,SACA,cACA,YACA,QACe;AACf,UAAM,KAAK,IAAI;AAAA,MACb,MAAM,cAAc,MAAM;AAAA,MAC1B,UAAU;AAAA,MACV,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACR;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACJ,MACA,UACA,SACA,SACA,UACe;AACf,UAAM,KAAK,IAAI;AAAA,MACb,MAAM,YAAY,IAAI;AAAA,MACtB;AAAA,MACA,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,MACA,SACA,QACA,UACe;AACf,UAAM,KAAK,IAAI;AAAA,MACb,MAAM,QAAQ,IAAI;AAAA,MAClB,UAAU;AAAA,MACV,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM,OAA0C;AACpD,WAAO,KAAK,QAAQ,MAAM,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM,OAAoC;AAC9C,WAAO,KAAK,QAAQ,MAAM,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAA8C;AACtD,SAAK,QAAQ,KAAK,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA8C;AACzD,UAAM,QAAQ,KAAK,QAAQ,QAAQ,MAAM;AACzC,QAAI,QAAQ,IAAI;AACd,WAAK,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC9B;AAAA,EACF;AACF;AAKO,IAAM,uBAAN,MAAmD;AAAA,EAChD,SAAuB,CAAC;AAAA,EACxB;AAAA,EAER,YAAY,YAAoB,KAAO;AACrC,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,MAAM,OAAkC;AAC5C,SAAK,OAAO,KAAK,KAAK;AAGtB,QAAI,KAAK,OAAO,SAAS,KAAK,WAAW;AACvC,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,OAA0C;AACpD,QAAI,UAAU,CAAC,GAAG,KAAK,MAAM;AAG7B,QAAI,MAAM,SAAS,MAAM,MAAM,SAAS,GAAG;AACzC,gBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,IAC/D;AAGA,QAAI,MAAM,SAAS;AACjB,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,OAAO,MAAM,OAAO;AAAA,IAC9D;AAGA,QAAI,MAAM,cAAc;AACtB,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,MAAM,YAAY;AAAA,IACzE;AAEA,QAAI,MAAM,YAAY;AACpB,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,OAAO,MAAM,UAAU;AAAA,IACrE;AAGA,QAAI,MAAM,WAAW;AACnB,YAAM,YAAY,MAAM;AACxB,gBAAU,QAAQ,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,SAAS,KAAK,SAAS;AAAA,IACpE;AAEA,QAAI,MAAM,SAAS;AACjB,YAAM,UAAU,MAAM;AACtB,gBAAU,QAAQ,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,SAAS,KAAK,OAAO;AAAA,IAClE;AAGA,QAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAC/C,gBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,UAAU,SAAS,EAAE,QAAQ,CAAC;AAAA,IACtE;AAGA,QAAI,MAAM,UAAU,MAAM,OAAO,SAAS,GAAG;AAC3C,gBAAU,QAAQ,OAAO,CAAC,MAAM,MAAM,QAAQ,SAAS,EAAE,MAAM,CAAC;AAAA,IAClE;AAGA,YAAQ,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC;AAGxF,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,QAAQ,MAAM,SAAS;AAE7B,WAAO,QAAQ,MAAM,QAAQ,SAAS,KAAK;AAAA,EAC7C;AAAA,EAEA,MAAM,MAAM,OAAoC;AAC9C,UAAM,UAAU,MAAM,KAAK,MAAM,EAAE,GAAG,OAAO,OAAO,QAAW,QAAQ,OAAU,CAAC;AAClF,WAAO,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS,CAAC;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAuB;AACrB,WAAO,CAAC,GAAG,KAAK,MAAM;AAAA,EACxB;AACF;AAKO,SAAS,WACd,MACA,QACA,SAKA;AACA,SAAO,CAAC,SAAiB,cAAsB,eAAmC;AAChF,UAAM,iBAAiB,WAAW;AAElC,eAAW,QAAQ,kBAEd,MACH;AACA,YAAM,UAAU,KAAK,MAAM,MAAM;AACjC,YAAM,SAAS,SAAS,iBAAiB,KAAK,CAAC,IAAI;AAEnD,UAAI,SAA4C;AAChD,UAAI;AAEJ,UAAI;AACF,cAAM,cAAc,MAAM,eAAe,MAAM,MAAM,IAAI;AAGzD,YAAI,KAAK,OAAO;AACd,gBAAM,KAAK,MAAM,IAAI;AAAA,YACnB;AAAA,YACA,UAAU,SAAS,YAAY;AAAA,YAC/B,OAAO;AAAA,cACL,IAAI;AAAA,cACJ,MAAM;AAAA,YACR;AAAA,YACA,UAAU,SAAS,eACf;AAAA,cACE,MAAM,QAAQ;AAAA,cACd,IAAK,KAAK,CAAC,GAAuB,MAAM;AAAA,YAC1C,IACA;AAAA,YACJ;AAAA,YACA;AAAA,YACA,SAAS,SAAS,iBACd;AAAA,cACE;AAAA,cACA,OAAO;AAAA,YACT,IACA;AAAA,UACN,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,iBAAS;AACT,gBAAQ;AAGR,YAAI,KAAK,OAAO;AACd,gBAAM,KAAK,MAAM,IAAI;AAAA,YACnB;AAAA,YACA,UAAU;AAAA,YACV,OAAO;AAAA,cACL,IAAI;AAAA,cACJ,MAAM;AAAA,YACR;AAAA,YACA,UAAU,SAAS,eACf;AAAA,cACE,MAAM,QAAQ;AAAA,cACd,IAAK,KAAK,CAAC,GAAuB,MAAM;AAAA,YAC1C,IACA;AAAA,YACJ;AAAA,YACA;AAAA,YACA,SAAS,MAAM;AAAA,UACjB,CAAC;AAAA,QACH;AAEA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAKO,SAAS,sBACdA,QACA,SACA;AACA,SAAO,OACL,SACA,SACG;AACH,UAAM,OAAO,QAAQ,OAAO;AAC5B,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI;AACF,YAAM,WAAW,MAAM,KAAK;AAG5B,YAAMA,OAAM,IAAI;AAAA,QACd,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,UACL,IAAI,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,WAAW,KAAK;AAAA,QAClB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU;AAAA,UACR,MAAM,QAAQ;AAAA,UACd,UAAU,KAAK,IAAI,IAAI;AAAA,UACvB,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,YAAMA,OAAM,IAAI;AAAA,QACd,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,UACL,IAAI,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,WAAW,KAAK;AAAA,QAClB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,UAAU;AAAA,UACR,MAAM,QAAQ;AAAA,UACd,UAAU,KAAK,IAAI,IAAI;AAAA,QACzB;AAAA,MACF,CAAC;AAED,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAKO,IAAM,uBAAN,MAA2B;AAAA,EAChC,YAAoBA,QAAoB;AAApB,iBAAAA;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA,EAKzC,MAAM,uBACJ,WACA,SAQC;AACD,UAAM,YAAY,MAAM,KAAK,MAAM,MAAM;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,qBAAqB,UAAU,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,WAAW,CAAC,EAAE;AAEnF,UAAM,eAAe,UAAU,OAAO,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE;AAE7E,UAAM,oBAAoB,UAAU,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,aAAa,CAAC,EAAE;AAEpF,UAAM,cAAc,UAAU,OAAO,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE;AAEtE,UAAM,iBAAiB,UAAU,OAAO,CAAC,MAAM,EAAE,aAAa,UAAU;AAExE,WAAO;AAAA,MACL,aAAa,UAAU;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BACJ,QACA,WACA,SAMC;AACD,UAAM,SAAS,MAAM,KAAK,MAAM,MAAM;AAAA,MACpC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,gBAAgB,OAAO;AAAA,MAC3B,CAAC,KAAK,UAAU;AACd,YAAI,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,KAAK;AAC3C,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AAEnE,WAAO;AAAA,MACL,cAAc,OAAO;AAAA,MACrB;AAAA,MACA;AAAA,MACA,eAAe,OAAO,MAAM,GAAG,EAAE;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,yBACJ,WACA,SAOC;AACD,UAAM,SAAS,MAAM,KAAK,MAAM,MAAM;AAAA,MACpC;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE;AAElE,UAAM,oBAAoB,OAAO;AAAA,MAC/B,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,SAAS;AAAA,IAChD,EAAE;AAEF,UAAM,gBAAgB,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE;AAErE,UAAM,eAAe,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,OAAO,CAAC,EAAE;AAGtE,UAAM,qBAAqB,KAAK,0BAA0B,MAAM;AAEhE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAA0B,QAA+B;AAC/D,QAAI,OAAO,WAAW,EAAG,QAAO;AAGhC,UAAM,SAAS,OAAO;AAAA,MACpB,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AAAA,IAC5E;AAGA,WAAO,OAAO,SAAS;AAAA,EACzB;AACF;AA0BA,eAAsB,eAAe,OAAuB,QAAiC;AAC3F,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,QAAa;AACjD,QAAM,YAAY,KAAK,UAAU;AAAA,IAC/B,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM;AAAA,IACjB,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,EACjB,CAAC;AACD,SAAO,WAAW,UAAU,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AACpE;AAYA,eAAsB,iBACpB,OACA,WACA,QACkB;AAClB,QAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,QAAa;AACtD,QAAM,WAAW,MAAM,eAAe,OAAO,MAAM;AAGnD,MAAI,SAAS,WAAW,UAAU,QAAQ;AACxC,WAAO;AAAA,EACT;AAEA,SAAO,gBAAgB,OAAO,KAAK,QAAQ,GAAG,OAAO,KAAK,SAAS,CAAC;AACtE;AAKO,IAAM,QAAQ,IAAI,YAAY,IAAI,qBAAqB,CAAC;","names":["audit"]}
package/dist/index.d.ts CHANGED
@@ -54,6 +54,11 @@ declare class AuditSystem {
54
54
  private storage;
55
55
  private filters;
56
56
  constructor(storage: AuditStorage);
57
+ /**
58
+ * Replace the backing storage (e.g. swap InMemory for Postgres at startup).
59
+ * Events already written to the old storage are NOT migrated.
60
+ */
61
+ setStorage(storage: AuditStorage): void;
57
62
  /**
58
63
  * Log audit event
59
64
  */
@@ -181,11 +186,154 @@ declare class AuditReportGenerator {
181
186
  */
182
187
  private checkAuditTrailContinuity;
183
188
  }
189
+ /** Fields included in the HMAC signature for tamper detection. */
190
+ interface SignableFields {
191
+ timestamp: string;
192
+ eventType: string;
193
+ severity: string;
194
+ agentId: string;
195
+ payload: unknown;
196
+ }
197
+ /**
198
+ * Compute an HMAC-SHA256 signature over the canonical fields of an audit entry.
199
+ *
200
+ * The signature covers `timestamp`, `eventType`, `severity`, `agentId`, and
201
+ * `payload` — the immutable core of every audit record. Changing any of
202
+ * these fields after signing will cause verification to fail.
203
+ *
204
+ * @param entry - The audit entry fields to sign
205
+ * @param secret - The HMAC secret key
206
+ * @returns Hex-encoded HMAC-SHA256 signature
207
+ */
208
+ declare function signAuditEntry(entry: SignableFields, secret: string): Promise<string>;
209
+ /**
210
+ * Verify an HMAC-SHA256 signature against the canonical fields of an audit entry.
211
+ *
212
+ * Uses timing-safe comparison to prevent timing attacks.
213
+ *
214
+ * @param entry - The audit entry fields to verify
215
+ * @param signature - The hex-encoded HMAC-SHA256 signature to verify
216
+ * @param secret - The HMAC secret key
217
+ * @returns True if the signature is valid
218
+ */
219
+ declare function verifyAuditEntry(entry: SignableFields, signature: string, secret: string): Promise<boolean>;
184
220
  /**
185
221
  * Global audit system
186
222
  */
187
223
  declare const audit: AuditSystem;
188
224
 
225
+ /**
226
+ * Security Alerting Service
227
+ *
228
+ * Evaluates audit events against configurable threshold rules and
229
+ * dispatches alerts through pluggable handlers (logging, audit trail,
230
+ * webhook / SIEM integration).
231
+ */
232
+
233
+ /** A security alert produced when a threshold is breached. */
234
+ interface SecurityAlert {
235
+ /** Alert rule that triggered (e.g. 'failedLogins', 'accountLockout'). */
236
+ type: string;
237
+ /** Severity of the alert. */
238
+ severity: AuditSeverity;
239
+ /** Human-readable description. */
240
+ message: string;
241
+ /** Contextual data attached to the alert. */
242
+ context: Record<string, unknown>;
243
+ /** When the alert was raised (ISO-8601). */
244
+ timestamp: string;
245
+ }
246
+ /** Handler that receives dispatched security alerts. */
247
+ interface AlertHandler {
248
+ /** Process a single alert. */
249
+ handle(alert: SecurityAlert): Promise<void>;
250
+ }
251
+ /** Configuration for a single threshold rule. */
252
+ interface ThresholdRule {
253
+ /** Maximum event count before an alert fires. */
254
+ maxCount: number;
255
+ /** Sliding window duration in milliseconds. */
256
+ windowMs: number;
257
+ /** Severity assigned to alerts from this rule. */
258
+ severity: AuditSeverity;
259
+ /** Human-readable message template — `{count}` is replaced at runtime. */
260
+ messageTemplate: string;
261
+ }
262
+ /** Top-level configuration for the alerting service. */
263
+ interface AlertingConfig {
264
+ /** Threshold rules keyed by rule name. */
265
+ thresholds: Record<string, ThresholdRule>;
266
+ /** Handlers that receive dispatched alerts. */
267
+ handlers: AlertHandler[];
268
+ }
269
+ /** Default threshold rules aligned with SOC2 6.2 requirements. */
270
+ declare const DEFAULT_THRESHOLDS: Record<string, ThresholdRule>;
271
+ /**
272
+ * Logs alerts to the structured security logger.
273
+ */
274
+ declare class LogAlertHandler implements AlertHandler {
275
+ /** Write alert details to the configured security logger. */
276
+ handle(alert: SecurityAlert): Promise<void>;
277
+ }
278
+ /**
279
+ * Writes alerts as critical audit events into the audit log.
280
+ */
281
+ declare class AuditAlertHandler implements AlertHandler {
282
+ /** Record the alert in the audit trail with severity 'critical'. */
283
+ handle(alert: SecurityAlert): Promise<void>;
284
+ }
285
+ /**
286
+ * POSTs alerts to a configurable webhook URL for SIEM integration.
287
+ */
288
+ declare class WebhookAlertHandler implements AlertHandler {
289
+ private url;
290
+ private headers;
291
+ /**
292
+ * Create a webhook alert handler.
293
+ *
294
+ * @param url - The webhook endpoint URL
295
+ * @param headers - Additional HTTP headers (e.g. authorization)
296
+ */
297
+ constructor(url: string, headers?: Record<string, string>);
298
+ /** POST the alert payload to the configured webhook URL. */
299
+ handle(alert: SecurityAlert): Promise<void>;
300
+ }
301
+ /**
302
+ * Evaluates audit events against threshold rules and dispatches alerts.
303
+ *
304
+ * Maintains an in-memory sliding window per rule/group key. When the
305
+ * event count within the window exceeds the threshold, an alert is
306
+ * dispatched to all configured handlers.
307
+ */
308
+ declare class SecurityAlertService {
309
+ private config;
310
+ private windows;
311
+ /**
312
+ * Create a new SecurityAlertService.
313
+ *
314
+ * @param config - Alerting configuration with thresholds and handlers
315
+ */
316
+ constructor(config: AlertingConfig);
317
+ /**
318
+ * Evaluate a single audit event against all threshold rules.
319
+ * If a threshold is breached, dispatches alerts to all handlers.
320
+ *
321
+ * @param event - The audit event to evaluate
322
+ * @returns The alert that was dispatched, or null if no threshold was breached
323
+ */
324
+ evaluateEvent(event: AuditEvent): Promise<SecurityAlert | null>;
325
+ /**
326
+ * Clear all sliding window state. Useful for testing.
327
+ */
328
+ reset(): void;
329
+ /**
330
+ * Dispatch an alert to all configured handlers.
331
+ * Errors in individual handlers are logged but do not prevent
332
+ * other handlers from receiving the alert.
333
+ */
334
+ private dispatchAlert;
335
+ }
336
+
189
337
  /**
190
338
  * Authentication Utilities
191
339
  *
@@ -1356,4 +1504,4 @@ interface SecurityLogger {
1356
1504
  */
1357
1505
  declare function configureSecurityLogger(logger: SecurityLogger): void;
1358
1506
 
1359
- export { type AuditEvent, type AuditEventType, type AuditQuery, AuditReportGenerator, type AuditSeverity, type AuditStorage, AuditSystem, AuditTrail, type AuthorizationContext, AuthorizationSystem, type BreachStorage, type CORSConfig, CORSManager, CORSPresets, CommonRoles, ConsentManager, type ConsentRecord, type ConsentType, type ContentSecurityPolicyConfig, type CookieConsentConfig, CookieConsentManager, DataAnonymization, type DataBreach, DataBreachManager, type DataCategory, type DataDeletionRequest, DataDeletionSystem, DataExportSystem, DataMasking, type DataProcessingPurpose, type EncryptedData, type EncryptionConfig, EncryptionSystem, EnvelopeEncryption, FieldEncryption, type GDPRStorage, type HSTSConfig, InMemoryAuditStorage, InMemoryBreachStorage, InMemoryGDPRStorage, KeyRotationManager, OAuthClient, type OAuthConfig, OAuthProviders, PasswordHasher, type Permission, PermissionBuilder, PermissionCache, type PermissionsPolicyConfig, type PersonalDataExport, type Policy, PolicyBuilder, type PolicyCondition, PrivacyPolicyManager, type ReferrerPolicyValue, RequirePermission, RequireRole, type Role, SecurityHeaders, type SecurityHeadersConfig, type SecurityLogger, SecurityPresets, TokenGenerator, TwoFactorAuth, type User, audit, authorization, canAccessResource, checkAttributeAccess, configureSecurityLogger, cookieConsentManager, createAuditMiddleware, createAuthorizationMiddleware, createConsentManager, createDataBreachManager, createDataDeletionSystem, createSecurityMiddleware, dataExportSystem, encryption, permissionCache, privacyPolicyManager, setRateLimitHeaders };
1507
+ export { type AlertHandler, type AlertingConfig, AuditAlertHandler, type AuditEvent, type AuditEventType, type AuditQuery, AuditReportGenerator, type AuditSeverity, type AuditStorage, AuditSystem, AuditTrail, type AuthorizationContext, AuthorizationSystem, type BreachStorage, type CORSConfig, CORSManager, CORSPresets, CommonRoles, ConsentManager, type ConsentRecord, type ConsentType, type ContentSecurityPolicyConfig, type CookieConsentConfig, CookieConsentManager, DEFAULT_THRESHOLDS, DataAnonymization, type DataBreach, DataBreachManager, type DataCategory, type DataDeletionRequest, DataDeletionSystem, DataExportSystem, DataMasking, type DataProcessingPurpose, type EncryptedData, type EncryptionConfig, EncryptionSystem, EnvelopeEncryption, FieldEncryption, type GDPRStorage, type HSTSConfig, InMemoryAuditStorage, InMemoryBreachStorage, InMemoryGDPRStorage, KeyRotationManager, LogAlertHandler, OAuthClient, type OAuthConfig, OAuthProviders, PasswordHasher, type Permission, PermissionBuilder, PermissionCache, type PermissionsPolicyConfig, type PersonalDataExport, type Policy, PolicyBuilder, type PolicyCondition, PrivacyPolicyManager, type ReferrerPolicyValue, RequirePermission, RequireRole, type Role, type SecurityAlert, SecurityAlertService, SecurityHeaders, type SecurityHeadersConfig, type SecurityLogger, SecurityPresets, type ThresholdRule, TokenGenerator, TwoFactorAuth, type User, WebhookAlertHandler, audit, authorization, canAccessResource, checkAttributeAccess, configureSecurityLogger, cookieConsentManager, createAuditMiddleware, createAuthorizationMiddleware, createConsentManager, createDataBreachManager, createDataDeletionSystem, createSecurityMiddleware, dataExportSystem, encryption, permissionCache, privacyPolicyManager, setRateLimitHeaders, signAuditEntry, verifyAuditEntry };