@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.
- package/dist/audit-UF7PIYBU.js +21 -0
- package/dist/audit-UF7PIYBU.js.map +1 -0
- package/dist/chunk-Q5KAPSST.js +429 -0
- package/dist/chunk-Q5KAPSST.js.map +1 -0
- package/dist/index.d.ts +149 -1
- package/dist/index.js +199 -370
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,394 +1,227 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {
|
|
2
|
+
AuditReportGenerator,
|
|
3
|
+
AuditSystem,
|
|
4
|
+
AuditTrail,
|
|
5
|
+
InMemoryAuditStorage,
|
|
6
|
+
audit,
|
|
7
|
+
createAuditMiddleware,
|
|
8
|
+
signAuditEntry,
|
|
9
|
+
verifyAuditEntry
|
|
10
|
+
} from "./chunk-Q5KAPSST.js";
|
|
11
|
+
|
|
12
|
+
// src/logger.ts
|
|
13
|
+
var securityLogger = console;
|
|
14
|
+
function configureSecurityLogger(logger) {
|
|
15
|
+
securityLogger = logger;
|
|
16
|
+
}
|
|
17
|
+
function getSecurityLogger() {
|
|
18
|
+
return securityLogger;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/alerting.ts
|
|
22
|
+
var DEFAULT_THRESHOLDS = {
|
|
23
|
+
failedLogins: {
|
|
24
|
+
maxCount: 10,
|
|
25
|
+
windowMs: 15 * 60 * 1e3,
|
|
26
|
+
severity: "high",
|
|
27
|
+
messageTemplate: "Excessive failed logins detected: {count} attempts in 15 minutes"
|
|
28
|
+
},
|
|
29
|
+
privilegeEscalation: {
|
|
30
|
+
maxCount: 1,
|
|
31
|
+
windowMs: 60 * 60 * 1e3,
|
|
32
|
+
severity: "critical",
|
|
33
|
+
messageTemplate: "Privilege escalation detected: role changed to admin"
|
|
34
|
+
},
|
|
35
|
+
massDataExport: {
|
|
36
|
+
maxCount: 100,
|
|
37
|
+
windowMs: 60 * 60 * 1e3,
|
|
38
|
+
severity: "high",
|
|
39
|
+
messageTemplate: "Mass data export detected: {count} exports in 1 hour"
|
|
40
|
+
},
|
|
41
|
+
accountLockout: {
|
|
42
|
+
maxCount: 1,
|
|
43
|
+
windowMs: 60 * 60 * 1e3,
|
|
44
|
+
severity: "high",
|
|
45
|
+
messageTemplate: "Account lockout triggered"
|
|
46
|
+
},
|
|
47
|
+
mfaDisabled: {
|
|
48
|
+
maxCount: 1,
|
|
49
|
+
windowMs: 60 * 60 * 1e3,
|
|
50
|
+
severity: "critical",
|
|
51
|
+
messageTemplate: "MFA disabled on account"
|
|
7
52
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!shouldLog) {
|
|
19
|
-
return;
|
|
53
|
+
};
|
|
54
|
+
var LogAlertHandler = class {
|
|
55
|
+
/** Write alert details to the configured security logger. */
|
|
56
|
+
async handle(alert) {
|
|
57
|
+
const logger = getSecurityLogger();
|
|
58
|
+
const prefix = `[SecurityAlert:${alert.type}]`;
|
|
59
|
+
if (alert.severity === "critical") {
|
|
60
|
+
logger.error(`${prefix} ${alert.message}`, alert.context);
|
|
61
|
+
} else {
|
|
62
|
+
logger.warn(`${prefix} ${alert.message}`, alert.context);
|
|
20
63
|
}
|
|
21
|
-
await this.storage.write(fullEvent);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Log authentication event
|
|
25
|
-
*/
|
|
26
|
-
async logAuth(type, actorId, result, metadata) {
|
|
27
|
-
await this.log({
|
|
28
|
-
type,
|
|
29
|
-
severity: result === "failure" ? "medium" : "low",
|
|
30
|
-
actor: {
|
|
31
|
-
id: actorId,
|
|
32
|
-
type: "user"
|
|
33
|
-
},
|
|
34
|
-
action: type.replace("auth.", ""),
|
|
35
|
-
result,
|
|
36
|
-
metadata
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Log data access event
|
|
41
|
-
*/
|
|
42
|
-
async logDataAccess(action, actorId, resourceType, resourceId, result, changes) {
|
|
43
|
-
await this.log({
|
|
44
|
-
type: `data.${action}`,
|
|
45
|
-
severity: action === "delete" ? "high" : "medium",
|
|
46
|
-
actor: {
|
|
47
|
-
id: actorId,
|
|
48
|
-
type: "user"
|
|
49
|
-
},
|
|
50
|
-
resource: {
|
|
51
|
-
type: resourceType,
|
|
52
|
-
id: resourceId
|
|
53
|
-
},
|
|
54
|
-
action,
|
|
55
|
-
result,
|
|
56
|
-
changes
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Log permission change
|
|
61
|
-
*/
|
|
62
|
-
async logPermissionChange(action, actorId, targetUserId, permission, result) {
|
|
63
|
-
await this.log({
|
|
64
|
-
type: `permission.${action}`,
|
|
65
|
-
severity: "high",
|
|
66
|
-
actor: {
|
|
67
|
-
id: actorId,
|
|
68
|
-
type: "user"
|
|
69
|
-
},
|
|
70
|
-
resource: {
|
|
71
|
-
type: "user",
|
|
72
|
-
id: targetUserId
|
|
73
|
-
},
|
|
74
|
-
action,
|
|
75
|
-
result,
|
|
76
|
-
metadata: {
|
|
77
|
-
permission
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Log security event
|
|
83
|
-
*/
|
|
84
|
-
async logSecurityEvent(type, severity, actorId, message, metadata) {
|
|
85
|
-
await this.log({
|
|
86
|
-
type: `security.${type}`,
|
|
87
|
-
severity,
|
|
88
|
-
actor: {
|
|
89
|
-
id: actorId,
|
|
90
|
-
type: "user"
|
|
91
|
-
},
|
|
92
|
-
action: type,
|
|
93
|
-
result: "failure",
|
|
94
|
-
message,
|
|
95
|
-
metadata
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Log GDPR event
|
|
100
|
-
*/
|
|
101
|
-
async logGDPREvent(type, actorId, result, metadata) {
|
|
102
|
-
await this.log({
|
|
103
|
-
type: `gdpr.${type}`,
|
|
104
|
-
severity: "high",
|
|
105
|
-
actor: {
|
|
106
|
-
id: actorId,
|
|
107
|
-
type: "user"
|
|
108
|
-
},
|
|
109
|
-
action: type,
|
|
110
|
-
result,
|
|
111
|
-
metadata
|
|
112
|
-
});
|
|
113
64
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
async
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
65
|
+
};
|
|
66
|
+
var AuditAlertHandler = class {
|
|
67
|
+
/** Record the alert in the audit trail with severity 'critical'. */
|
|
68
|
+
async handle(alert) {
|
|
69
|
+
try {
|
|
70
|
+
const { audit: audit2 } = await import("./audit-UF7PIYBU.js");
|
|
71
|
+
await audit2.logSecurityEvent(
|
|
72
|
+
"alert",
|
|
73
|
+
"critical",
|
|
74
|
+
alert.context.actorId ?? "system",
|
|
75
|
+
alert.message,
|
|
76
|
+
{ alertType: alert.type, ...alert.context }
|
|
77
|
+
);
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
125
80
|
}
|
|
81
|
+
};
|
|
82
|
+
var WebhookAlertHandler = class {
|
|
83
|
+
url;
|
|
84
|
+
headers;
|
|
126
85
|
/**
|
|
127
|
-
*
|
|
86
|
+
* Create a webhook alert handler.
|
|
87
|
+
*
|
|
88
|
+
* @param url - The webhook endpoint URL
|
|
89
|
+
* @param headers - Additional HTTP headers (e.g. authorization)
|
|
128
90
|
*/
|
|
129
|
-
|
|
130
|
-
this.
|
|
91
|
+
constructor(url, headers = {}) {
|
|
92
|
+
this.url = url;
|
|
93
|
+
this.headers = headers;
|
|
131
94
|
}
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
95
|
+
/** POST the alert payload to the configured webhook URL. */
|
|
96
|
+
async handle(alert) {
|
|
97
|
+
try {
|
|
98
|
+
await fetch(this.url, {
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers: {
|
|
101
|
+
"Content-Type": "application/json",
|
|
102
|
+
...this.headers
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify(alert)
|
|
105
|
+
});
|
|
106
|
+
} catch {
|
|
107
|
+
const logger = getSecurityLogger();
|
|
108
|
+
logger.error(`[WebhookAlertHandler] Failed to POST alert to ${this.url}`);
|
|
139
109
|
}
|
|
140
110
|
}
|
|
141
111
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
constructor(maxEvents = 1e4) {
|
|
146
|
-
this.maxEvents = maxEvents;
|
|
147
|
-
}
|
|
148
|
-
async write(event) {
|
|
149
|
-
this.events.push(event);
|
|
150
|
-
if (this.events.length > this.maxEvents) {
|
|
151
|
-
this.events.shift();
|
|
152
|
-
}
|
|
112
|
+
function mapEventToRule(event) {
|
|
113
|
+
if (event.type === "auth.failed_login") {
|
|
114
|
+
return "failedLogins";
|
|
153
115
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (
|
|
157
|
-
|
|
116
|
+
if (event.type === "role.assign") {
|
|
117
|
+
const newRole = event.changes?.after?.role ?? event.metadata?.role;
|
|
118
|
+
if (newRole === "admin") {
|
|
119
|
+
return "privilegeEscalation";
|
|
158
120
|
}
|
|
159
|
-
if (query.actorId) {
|
|
160
|
-
results = results.filter((e) => e.actor.id === query.actorId);
|
|
161
|
-
}
|
|
162
|
-
if (query.resourceType) {
|
|
163
|
-
results = results.filter((e) => e.resource?.type === query.resourceType);
|
|
164
|
-
}
|
|
165
|
-
if (query.resourceId) {
|
|
166
|
-
results = results.filter((e) => e.resource?.id === query.resourceId);
|
|
167
|
-
}
|
|
168
|
-
if (query.startDate) {
|
|
169
|
-
const startDate = query.startDate;
|
|
170
|
-
results = results.filter((e) => new Date(e.timestamp) >= startDate);
|
|
171
|
-
}
|
|
172
|
-
if (query.endDate) {
|
|
173
|
-
const endDate = query.endDate;
|
|
174
|
-
results = results.filter((e) => new Date(e.timestamp) <= endDate);
|
|
175
|
-
}
|
|
176
|
-
if (query.severity && query.severity.length > 0) {
|
|
177
|
-
results = results.filter((e) => query.severity?.includes(e.severity));
|
|
178
|
-
}
|
|
179
|
-
if (query.result && query.result.length > 0) {
|
|
180
|
-
results = results.filter((e) => query.result?.includes(e.result));
|
|
181
|
-
}
|
|
182
|
-
results.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
183
|
-
const offset = query.offset || 0;
|
|
184
|
-
const limit = query.limit || 100;
|
|
185
|
-
return results.slice(offset, offset + limit);
|
|
186
121
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return results.length;
|
|
122
|
+
if (event.type === "data.export") {
|
|
123
|
+
return "massDataExport";
|
|
190
124
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
*/
|
|
194
|
-
clear() {
|
|
195
|
-
this.events = [];
|
|
125
|
+
if (event.action === "account_locked") {
|
|
126
|
+
return "accountLockout";
|
|
196
127
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
*/
|
|
200
|
-
getAll() {
|
|
201
|
-
return [...this.events];
|
|
128
|
+
if (event.type === "auth.mfa_disabled") {
|
|
129
|
+
return "mfaDisabled";
|
|
202
130
|
}
|
|
203
|
-
|
|
204
|
-
function AuditTrail(type, action, options) {
|
|
205
|
-
return (_target, _propertyKey, descriptor) => {
|
|
206
|
-
const originalMethod = descriptor.value;
|
|
207
|
-
descriptor.value = async function(...args) {
|
|
208
|
-
const actorId = this.user?.id || "system";
|
|
209
|
-
const before = options?.captureChanges ? args[0] : void 0;
|
|
210
|
-
let result = "success";
|
|
211
|
-
let error;
|
|
212
|
-
try {
|
|
213
|
-
const returnValue = await originalMethod.apply(this, args);
|
|
214
|
-
if (this.audit) {
|
|
215
|
-
await this.audit.log({
|
|
216
|
-
type,
|
|
217
|
-
severity: options?.severity || "medium",
|
|
218
|
-
actor: {
|
|
219
|
-
id: actorId,
|
|
220
|
-
type: "user"
|
|
221
|
-
},
|
|
222
|
-
resource: options?.resourceType ? {
|
|
223
|
-
type: options.resourceType,
|
|
224
|
-
id: args[0]?.id || "unknown"
|
|
225
|
-
} : void 0,
|
|
226
|
-
action,
|
|
227
|
-
result,
|
|
228
|
-
changes: options?.captureChanges ? {
|
|
229
|
-
before,
|
|
230
|
-
after: returnValue
|
|
231
|
-
} : void 0
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
return returnValue;
|
|
235
|
-
} catch (err) {
|
|
236
|
-
result = "failure";
|
|
237
|
-
error = err;
|
|
238
|
-
if (this.audit) {
|
|
239
|
-
await this.audit.log({
|
|
240
|
-
type,
|
|
241
|
-
severity: "high",
|
|
242
|
-
actor: {
|
|
243
|
-
id: actorId,
|
|
244
|
-
type: "user"
|
|
245
|
-
},
|
|
246
|
-
resource: options?.resourceType ? {
|
|
247
|
-
type: options.resourceType,
|
|
248
|
-
id: args[0]?.id || "unknown"
|
|
249
|
-
} : void 0,
|
|
250
|
-
action,
|
|
251
|
-
result,
|
|
252
|
-
message: error.message
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
throw error;
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
return descriptor;
|
|
259
|
-
};
|
|
131
|
+
return null;
|
|
260
132
|
}
|
|
261
|
-
function
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const startTime = Date.now();
|
|
265
|
-
try {
|
|
266
|
-
const response = await next();
|
|
267
|
-
await audit2.log({
|
|
268
|
-
type: "data.read",
|
|
269
|
-
severity: "low",
|
|
270
|
-
actor: {
|
|
271
|
-
id: user.id,
|
|
272
|
-
type: "user",
|
|
273
|
-
ip: user.ip,
|
|
274
|
-
userAgent: user.userAgent
|
|
275
|
-
},
|
|
276
|
-
action: request.method,
|
|
277
|
-
result: "success",
|
|
278
|
-
metadata: {
|
|
279
|
-
path: request.url,
|
|
280
|
-
duration: Date.now() - startTime,
|
|
281
|
-
status: response.status
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
return response;
|
|
285
|
-
} catch (error) {
|
|
286
|
-
await audit2.log({
|
|
287
|
-
type: "data.read",
|
|
288
|
-
severity: "medium",
|
|
289
|
-
actor: {
|
|
290
|
-
id: user.id,
|
|
291
|
-
type: "user",
|
|
292
|
-
ip: user.ip,
|
|
293
|
-
userAgent: user.userAgent
|
|
294
|
-
},
|
|
295
|
-
action: request.method,
|
|
296
|
-
result: "failure",
|
|
297
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
298
|
-
metadata: {
|
|
299
|
-
path: request.url,
|
|
300
|
-
duration: Date.now() - startTime
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
var AuditReportGenerator = class {
|
|
308
|
-
constructor(audit2) {
|
|
309
|
-
this.audit = audit2;
|
|
133
|
+
function getGroupKey(event, ruleName) {
|
|
134
|
+
if (ruleName === "failedLogins") {
|
|
135
|
+
return `${ruleName}:${event.actor.id}`;
|
|
310
136
|
}
|
|
137
|
+
if (ruleName === "massDataExport") {
|
|
138
|
+
return ruleName;
|
|
139
|
+
}
|
|
140
|
+
return `${ruleName}:${event.actor.id}`;
|
|
141
|
+
}
|
|
142
|
+
var SecurityAlertService = class {
|
|
143
|
+
config;
|
|
144
|
+
windows = /* @__PURE__ */ new Map();
|
|
311
145
|
/**
|
|
312
|
-
*
|
|
146
|
+
* Create a new SecurityAlertService.
|
|
147
|
+
*
|
|
148
|
+
* @param config - Alerting configuration with thresholds and handlers
|
|
313
149
|
*/
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
startDate,
|
|
317
|
-
endDate
|
|
318
|
-
});
|
|
319
|
-
const securityViolations = allEvents.filter((e) => e.type.startsWith("security.")).length;
|
|
320
|
-
const failedLogins = allEvents.filter((e) => e.type === "auth.failed_login").length;
|
|
321
|
-
const permissionChanges = allEvents.filter((e) => e.type.startsWith("permission.")).length;
|
|
322
|
-
const dataExports = allEvents.filter((e) => e.type === "data.export").length;
|
|
323
|
-
const criticalEvents = allEvents.filter((e) => e.severity === "critical");
|
|
324
|
-
return {
|
|
325
|
-
totalEvents: allEvents.length,
|
|
326
|
-
securityViolations,
|
|
327
|
-
failedLogins,
|
|
328
|
-
permissionChanges,
|
|
329
|
-
dataExports,
|
|
330
|
-
criticalEvents
|
|
331
|
-
};
|
|
150
|
+
constructor(config) {
|
|
151
|
+
this.config = config;
|
|
332
152
|
}
|
|
333
153
|
/**
|
|
334
|
-
*
|
|
154
|
+
* Evaluate a single audit event against all threshold rules.
|
|
155
|
+
* If a threshold is breached, dispatches alerts to all handlers.
|
|
156
|
+
*
|
|
157
|
+
* @param event - The audit event to evaluate
|
|
158
|
+
* @returns The alert that was dispatched, or null if no threshold was breached
|
|
335
159
|
*/
|
|
336
|
-
async
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
160
|
+
async evaluateEvent(event) {
|
|
161
|
+
const ruleName = mapEventToRule(event);
|
|
162
|
+
if (!ruleName) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
const rule = this.config.thresholds[ruleName];
|
|
166
|
+
if (!rule) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const groupKey = getGroupKey(event, ruleName);
|
|
170
|
+
const now = Date.now();
|
|
171
|
+
const cutoff = now - rule.windowMs;
|
|
172
|
+
let entry = this.windows.get(groupKey);
|
|
173
|
+
if (!entry) {
|
|
174
|
+
entry = { timestamps: [], lastAlertAt: 0 };
|
|
175
|
+
this.windows.set(groupKey, entry);
|
|
176
|
+
}
|
|
177
|
+
entry.timestamps.push(now);
|
|
178
|
+
entry.timestamps = entry.timestamps.filter((ts) => ts > cutoff);
|
|
179
|
+
if (entry.timestamps.length < rule.maxCount) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
if (entry.lastAlertAt > cutoff) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
entry.lastAlertAt = now;
|
|
186
|
+
const message = rule.messageTemplate.includes("{count}") ? rule.messageTemplate.split("{count}").join(String(entry.timestamps.length)) : rule.messageTemplate;
|
|
187
|
+
const alert = {
|
|
188
|
+
type: ruleName,
|
|
189
|
+
severity: rule.severity,
|
|
190
|
+
message,
|
|
191
|
+
context: {
|
|
192
|
+
actorId: event.actor.id,
|
|
193
|
+
eventType: event.type,
|
|
194
|
+
count: entry.timestamps.length,
|
|
195
|
+
windowMs: rule.windowMs
|
|
346
196
|
},
|
|
347
|
-
|
|
348
|
-
);
|
|
349
|
-
const failedActions = events.filter((e) => e.result === "failure").length;
|
|
350
|
-
return {
|
|
351
|
-
totalActions: events.length,
|
|
352
|
-
actionsByType,
|
|
353
|
-
failedActions,
|
|
354
|
-
recentActions: events.slice(0, 10)
|
|
197
|
+
timestamp: new Date(now).toISOString()
|
|
355
198
|
};
|
|
199
|
+
await this.dispatchAlert(alert);
|
|
200
|
+
return alert;
|
|
356
201
|
}
|
|
357
202
|
/**
|
|
358
|
-
*
|
|
203
|
+
* Clear all sliding window state. Useful for testing.
|
|
359
204
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
startDate,
|
|
363
|
-
endDate
|
|
364
|
-
});
|
|
365
|
-
const dataAccesses = events.filter((e) => e.type === "data.read").length;
|
|
366
|
-
const dataModifications = events.filter(
|
|
367
|
-
(e) => e.type === "data.update" || e.type === "data.create"
|
|
368
|
-
).length;
|
|
369
|
-
const dataDeletions = events.filter((e) => e.type === "data.delete").length;
|
|
370
|
-
const gdprRequests = events.filter((e) => e.type.startsWith("gdpr.")).length;
|
|
371
|
-
const auditTrailComplete = this.checkAuditTrailContinuity(events);
|
|
372
|
-
return {
|
|
373
|
-
dataAccesses,
|
|
374
|
-
dataModifications,
|
|
375
|
-
dataDeletions,
|
|
376
|
-
gdprRequests,
|
|
377
|
-
auditTrailComplete
|
|
378
|
-
};
|
|
205
|
+
reset() {
|
|
206
|
+
this.windows.clear();
|
|
379
207
|
}
|
|
380
208
|
/**
|
|
381
|
-
*
|
|
209
|
+
* Dispatch an alert to all configured handlers.
|
|
210
|
+
* Errors in individual handlers are logged but do not prevent
|
|
211
|
+
* other handlers from receiving the alert.
|
|
382
212
|
*/
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
213
|
+
async dispatchAlert(alert) {
|
|
214
|
+
const results = this.config.handlers.map(async (handler) => {
|
|
215
|
+
try {
|
|
216
|
+
await handler.handle(alert);
|
|
217
|
+
} catch {
|
|
218
|
+
const logger = getSecurityLogger();
|
|
219
|
+
logger.error(`[SecurityAlertService] Handler failed for alert type=${alert.type}`);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
await Promise.all(results);
|
|
389
223
|
}
|
|
390
224
|
};
|
|
391
|
-
var audit = new AuditSystem(new InMemoryAuditStorage());
|
|
392
225
|
|
|
393
226
|
// src/auth.ts
|
|
394
227
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
@@ -1506,17 +1339,6 @@ var TokenGenerator = {
|
|
|
1506
1339
|
|
|
1507
1340
|
// src/gdpr.ts
|
|
1508
1341
|
import { createHash, createHmac as createHmac2 } from "crypto";
|
|
1509
|
-
|
|
1510
|
-
// src/logger.ts
|
|
1511
|
-
var securityLogger = console;
|
|
1512
|
-
function configureSecurityLogger(logger) {
|
|
1513
|
-
securityLogger = logger;
|
|
1514
|
-
}
|
|
1515
|
-
function getSecurityLogger() {
|
|
1516
|
-
return securityLogger;
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
// src/gdpr.ts
|
|
1520
1342
|
var ConsentManager = class {
|
|
1521
1343
|
storage;
|
|
1522
1344
|
consentVersion = "1.0.0";
|
|
@@ -2400,6 +2222,7 @@ function setRateLimitHeaders(response, limit, remaining, reset) {
|
|
|
2400
2222
|
response.headers.set("X-RateLimit-Reset", reset.toString());
|
|
2401
2223
|
}
|
|
2402
2224
|
export {
|
|
2225
|
+
AuditAlertHandler,
|
|
2403
2226
|
AuditReportGenerator,
|
|
2404
2227
|
AuditSystem,
|
|
2405
2228
|
AuditTrail,
|
|
@@ -2409,6 +2232,7 @@ export {
|
|
|
2409
2232
|
CommonRoles,
|
|
2410
2233
|
ConsentManager,
|
|
2411
2234
|
CookieConsentManager,
|
|
2235
|
+
DEFAULT_THRESHOLDS,
|
|
2412
2236
|
DataAnonymization,
|
|
2413
2237
|
DataBreachManager,
|
|
2414
2238
|
DataDeletionSystem,
|
|
@@ -2421,6 +2245,7 @@ export {
|
|
|
2421
2245
|
InMemoryBreachStorage,
|
|
2422
2246
|
InMemoryGDPRStorage,
|
|
2423
2247
|
KeyRotationManager,
|
|
2248
|
+
LogAlertHandler,
|
|
2424
2249
|
OAuthClient,
|
|
2425
2250
|
OAuthProviders,
|
|
2426
2251
|
PasswordHasher,
|
|
@@ -2430,10 +2255,12 @@ export {
|
|
|
2430
2255
|
PrivacyPolicyManager,
|
|
2431
2256
|
RequirePermission,
|
|
2432
2257
|
RequireRole,
|
|
2258
|
+
SecurityAlertService,
|
|
2433
2259
|
SecurityHeaders,
|
|
2434
2260
|
SecurityPresets,
|
|
2435
2261
|
TokenGenerator,
|
|
2436
2262
|
TwoFactorAuth,
|
|
2263
|
+
WebhookAlertHandler,
|
|
2437
2264
|
audit,
|
|
2438
2265
|
authorization,
|
|
2439
2266
|
canAccessResource,
|
|
@@ -2450,6 +2277,8 @@ export {
|
|
|
2450
2277
|
encryption,
|
|
2451
2278
|
permissionCache,
|
|
2452
2279
|
privacyPolicyManager,
|
|
2453
|
-
setRateLimitHeaders
|
|
2280
|
+
setRateLimitHeaders,
|
|
2281
|
+
signAuditEntry,
|
|
2282
|
+
verifyAuditEntry
|
|
2454
2283
|
};
|
|
2455
2284
|
//# sourceMappingURL=index.js.map
|