@serve.zone/dcrouter 11.0.38 → 11.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist_serve/bundle.js +1 -1
  2. package/dist_ts_web/00_commitinfo_data.js +1 -1
  3. package/package.json +2 -2
  4. package/ts/00_commitinfo_data.ts +1 -1
  5. package/ts_web/00_commitinfo_data.ts +1 -1
  6. package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
  7. package/dist_ts/cache/classes.cache.cleaner.js +0 -130
  8. package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
  9. package/dist_ts/cache/documents/classes.cached.email.js +0 -337
  10. package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
  11. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
  12. package/dist_ts/cache/documents/index.d.ts +0 -2
  13. package/dist_ts/cache/documents/index.js +0 -3
  14. package/dist_ts/cache/index.d.ts +0 -4
  15. package/dist_ts/cache/index.js +0 -7
  16. package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -53
  17. package/dist_ts/classes.cert-provision-scheduler.js +0 -110
  18. package/dist_ts/classes.storage-cert-manager.d.ts +0 -18
  19. package/dist_ts/classes.storage-cert-manager.js +0 -43
  20. package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
  21. package/dist_ts/monitoring/classes.metricscache.js +0 -63
  22. package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
  23. package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
  24. package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
  25. package/dist_ts/opsserver/handlers/config.handler.js +0 -192
  26. package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
  27. package/dist_ts/opsserver/handlers/logs.handler.js +0 -256
  28. package/dist_ts/security/classes.securitylogger.d.ts +0 -144
  29. package/dist_ts/security/classes.securitylogger.js +0 -233
  30. package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
  31. package/dist_ts/storage/classes.storagemanager.js +0 -350
  32. package/dist_ts/storage/index.d.ts +0 -1
  33. package/dist_ts/storage/index.js +0 -3
@@ -1,256 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import * as interfaces from '../../../dist_ts_interfaces/index.js';
3
- import { logBuffer, baseLogger } from '../../logger.js';
4
- // Module-level singleton: the log push destination is added once and reuses
5
- // the current OpsServer reference so it survives OpsServer restarts without
6
- // accumulating duplicate destinations.
7
- let logPushDestinationInstalled = false;
8
- let currentOpsServerRef = null;
9
- export class LogsHandler {
10
- opsServerRef;
11
- activeStreamStops = new Set();
12
- constructor(opsServerRef) {
13
- this.opsServerRef = opsServerRef;
14
- this.registerHandlers();
15
- this.setupLogPushDestination();
16
- }
17
- /**
18
- * Clean up all active log streams and deactivate the push destination.
19
- * Called when OpsServer stops.
20
- */
21
- cleanup() {
22
- // Stop all active follow-mode log streams
23
- for (const stop of this.activeStreamStops) {
24
- stop();
25
- }
26
- this.activeStreamStops.clear();
27
- // Deactivate the push destination (it stays registered but becomes a no-op)
28
- currentOpsServerRef = null;
29
- }
30
- registerHandlers() {
31
- // All log endpoints register directly on viewRouter (valid identity required via middleware)
32
- const router = this.opsServerRef.viewRouter;
33
- // Get Recent Logs Handler
34
- router.addTypedHandler(new plugins.typedrequest.TypedHandler('getRecentLogs', async (dataArg, toolsArg) => {
35
- const logs = await this.getRecentLogs(dataArg.level, dataArg.category, dataArg.limit || 100, dataArg.offset || 0, dataArg.search, dataArg.timeRange);
36
- return {
37
- logs,
38
- total: logs.length,
39
- hasMore: false,
40
- };
41
- }));
42
- // Get Log Stream Handler
43
- router.addTypedHandler(new plugins.typedrequest.TypedHandler('getLogStream', async (dataArg, toolsArg) => {
44
- // Create a virtual stream for log streaming
45
- const virtualStream = new plugins.typedrequest.VirtualStream();
46
- // Set up log streaming
47
- const streamLogs = this.setupLogStream(virtualStream, dataArg.filters?.level, dataArg.filters?.category, dataArg.follow);
48
- // Start streaming
49
- streamLogs.start();
50
- // Track the stop function so we can clean up on shutdown
51
- this.activeStreamStops.add(streamLogs.stop);
52
- return {
53
- logStream: virtualStream,
54
- };
55
- }));
56
- }
57
- static mapLogLevel(smartlogLevel) {
58
- switch (smartlogLevel) {
59
- case 'silly':
60
- case 'debug':
61
- return 'debug';
62
- case 'warn':
63
- return 'warn';
64
- case 'error':
65
- return 'error';
66
- default:
67
- return 'info';
68
- }
69
- }
70
- static deriveCategory(zone, message) {
71
- const msg = (message || '').toLowerCase();
72
- if (msg.includes('[security:') || msg.includes('security'))
73
- return 'security';
74
- if (zone === 'email' || msg.includes('email') || msg.includes('smtp') || msg.includes('mta'))
75
- return 'email';
76
- if (zone === 'dns' || msg.includes('dns'))
77
- return 'dns';
78
- if (msg.includes('smtp'))
79
- return 'smtp';
80
- return 'system';
81
- }
82
- async getRecentLogs(level, category, limit = 100, offset = 0, search, timeRange) {
83
- // Compute a timestamp cutoff from timeRange
84
- let since;
85
- if (timeRange) {
86
- const rangeMs = {
87
- '1h': 3600000,
88
- '6h': 21600000,
89
- '24h': 86400000,
90
- '7d': 604800000,
91
- '30d': 2592000000,
92
- };
93
- since = Date.now() - (rangeMs[timeRange] || 86400000);
94
- }
95
- // Map the UI level to smartlog levels for filtering
96
- const smartlogLevels = level
97
- ? level === 'debug'
98
- ? ['debug', 'silly']
99
- : level === 'info'
100
- ? ['info', 'ok', 'success', 'note', 'lifecycle']
101
- : [level]
102
- : undefined;
103
- // Fetch a larger batch from buffer, then apply category filter client-side
104
- const rawEntries = logBuffer.getEntries({
105
- level: smartlogLevels,
106
- search,
107
- since,
108
- limit: limit * 3, // over-fetch to compensate for category filtering
109
- offset: 0,
110
- });
111
- // Map ILogPackage → UI log format and apply category filter
112
- const mapped = [];
113
- for (const pkg of rawEntries) {
114
- const uiLevel = LogsHandler.mapLogLevel(pkg.level);
115
- const uiCategory = LogsHandler.deriveCategory(pkg.context?.zone, pkg.message);
116
- if (category && uiCategory !== category)
117
- continue;
118
- mapped.push({
119
- timestamp: pkg.timestamp,
120
- level: uiLevel,
121
- category: uiCategory,
122
- message: pkg.message,
123
- metadata: pkg.data,
124
- });
125
- if (mapped.length >= limit)
126
- break;
127
- }
128
- return mapped;
129
- }
130
- /**
131
- * Add a log destination to the base logger that pushes entries
132
- * to all connected ops_dashboard TypedSocket clients.
133
- *
134
- * Uses a module-level singleton so the destination is added only once,
135
- * even across OpsServer restart cycles. The destination reads
136
- * `currentOpsServerRef` dynamically so it always uses the active server.
137
- */
138
- setupLogPushDestination() {
139
- // Update the module-level reference so the existing destination uses the new server
140
- currentOpsServerRef = this.opsServerRef;
141
- if (logPushDestinationInstalled) {
142
- return; // destination already registered — just updated the ref
143
- }
144
- logPushDestinationInstalled = true;
145
- baseLogger.addLogDestination({
146
- async handleLog(logPackage) {
147
- const opsServer = currentOpsServerRef;
148
- if (!opsServer)
149
- return;
150
- const typedsocket = opsServer.server?.typedserver?.typedsocket;
151
- if (!typedsocket)
152
- return;
153
- let connections;
154
- try {
155
- connections = await typedsocket.findAllTargetConnectionsByTag('role', 'ops_dashboard');
156
- }
157
- catch {
158
- return;
159
- }
160
- if (connections.length === 0)
161
- return;
162
- const entry = {
163
- timestamp: logPackage.timestamp || Date.now(),
164
- level: LogsHandler.mapLogLevel(logPackage.level),
165
- category: LogsHandler.deriveCategory(logPackage.context?.zone, logPackage.message),
166
- message: logPackage.message,
167
- metadata: logPackage.data,
168
- };
169
- for (const conn of connections) {
170
- try {
171
- const push = typedsocket.createTypedRequest('pushLogEntry', conn);
172
- push.fire({ entry }).catch(() => { }); // fire-and-forget
173
- }
174
- catch {
175
- // connection may have closed
176
- }
177
- }
178
- },
179
- });
180
- }
181
- setupLogStream(virtualStream, levelFilter, categoryFilter, follow = true) {
182
- let intervalId = null;
183
- let stopped = false;
184
- let logIndex = 0;
185
- const stop = () => {
186
- stopped = true;
187
- if (intervalId) {
188
- clearInterval(intervalId);
189
- intervalId = null;
190
- }
191
- this.activeStreamStops.delete(stop);
192
- };
193
- const start = () => {
194
- if (!follow) {
195
- // Send existing logs and close
196
- this.getRecentLogs(levelFilter?.[0], categoryFilter?.[0], 100, 0).then(logs => {
197
- logs.forEach(log => {
198
- const logData = JSON.stringify(log);
199
- const encoder = new TextEncoder();
200
- virtualStream.sendData(encoder.encode(logData));
201
- });
202
- });
203
- return;
204
- }
205
- // For follow mode, simulate real-time log streaming
206
- intervalId = setInterval(async () => {
207
- if (stopped) {
208
- // Guard: clear interval if stop() was called between ticks
209
- clearInterval(intervalId);
210
- intervalId = null;
211
- return;
212
- }
213
- const categories = ['smtp', 'dns', 'security', 'system', 'email'];
214
- const levels = ['info', 'warn', 'error', 'debug'];
215
- const mockCategory = categories[Math.floor(Math.random() * categories.length)];
216
- const mockLevel = levels[Math.floor(Math.random() * levels.length)];
217
- // Filter by requested criteria
218
- if (levelFilter && !levelFilter.includes(mockLevel))
219
- return;
220
- if (categoryFilter && !categoryFilter.includes(mockCategory))
221
- return;
222
- const logEntry = {
223
- timestamp: Date.now(),
224
- level: mockLevel,
225
- category: mockCategory,
226
- message: `Real-time log ${logIndex++} from ${mockCategory}`,
227
- metadata: {
228
- requestId: plugins.uuid.v4(),
229
- },
230
- };
231
- const logData = JSON.stringify(logEntry);
232
- const encoder = new TextEncoder();
233
- try {
234
- // Use a timeout to detect hung streams (sendData can hang if the
235
- // VirtualStream's keepAlive loop has ended)
236
- let timeoutHandle;
237
- await Promise.race([
238
- virtualStream.sendData(encoder.encode(logData)).then((result) => {
239
- clearTimeout(timeoutHandle);
240
- return result;
241
- }),
242
- new Promise((_, reject) => {
243
- timeoutHandle = setTimeout(() => reject(new Error('stream send timeout')), 10_000);
244
- }),
245
- ]);
246
- }
247
- catch {
248
- // Stream closed, errored, or timed out — clean up
249
- stop();
250
- }
251
- }, 2000);
252
- };
253
- return { start, stop };
254
- }
255
- }
256
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9ncy5oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvb3Bzc2VydmVyL2hhbmRsZXJzL2xvZ3MuaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV4RCw0RUFBNEU7QUFDNUUsNEVBQTRFO0FBQzVFLHVDQUF1QztBQUN2QyxJQUFJLDJCQUEyQixHQUFHLEtBQUssQ0FBQztBQUN4QyxJQUFJLG1CQUFtQixHQUFxQixJQUFJLENBQUM7QUFFakQsTUFBTSxPQUFPLFdBQVc7SUFHRjtJQUZaLGlCQUFpQixHQUFvQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRXZELFlBQW9CLFlBQXVCO1FBQXZCLGlCQUFZLEdBQVosWUFBWSxDQUFXO1FBQ3pDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxPQUFPO1FBQ1osMENBQTBDO1FBQzFDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDMUMsSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQy9CLDRFQUE0RTtRQUM1RSxtQkFBbUIsR0FBRyxJQUFJLENBQUM7SUFDN0IsQ0FBQztJQUVPLGdCQUFnQjtRQUN0Qiw2RkFBNkY7UUFDN0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUM7UUFFNUMsMEJBQTBCO1FBQzFCLE1BQU0sQ0FBQyxlQUFlLENBQ3BCLElBQUksT0FBTyxD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
@@ -1,144 +0,0 @@
1
- /**
2
- * Log level for security events
3
- */
4
- export declare enum SecurityLogLevel {
5
- INFO = "info",
6
- WARN = "warn",
7
- ERROR = "error",
8
- CRITICAL = "critical"
9
- }
10
- /**
11
- * Security event types for categorization
12
- */
13
- export declare enum SecurityEventType {
14
- AUTHENTICATION = "authentication",
15
- ACCESS_CONTROL = "access_control",
16
- EMAIL_VALIDATION = "email_validation",
17
- EMAIL_PROCESSING = "email_processing",
18
- EMAIL_FORWARDING = "email_forwarding",
19
- EMAIL_DELIVERY = "email_delivery",
20
- DKIM = "dkim",
21
- SPF = "spf",
22
- DMARC = "dmarc",
23
- RATE_LIMIT = "rate_limit",
24
- RATE_LIMITING = "rate_limiting",
25
- SPAM = "spam",
26
- MALWARE = "malware",
27
- CONNECTION = "connection",
28
- DATA_EXPOSURE = "data_exposure",
29
- CONFIGURATION = "configuration",
30
- IP_REPUTATION = "ip_reputation",
31
- REJECTED_CONNECTION = "rejected_connection"
32
- }
33
- /**
34
- * Security event interface
35
- */
36
- export interface ISecurityEvent {
37
- timestamp: number;
38
- level: SecurityLogLevel;
39
- type: SecurityEventType;
40
- message: string;
41
- details?: any;
42
- ipAddress?: string;
43
- userId?: string;
44
- sessionId?: string;
45
- emailId?: string;
46
- domain?: string;
47
- action?: string;
48
- result?: string;
49
- success?: boolean;
50
- }
51
- /**
52
- * Security logger for enhanced security monitoring
53
- */
54
- export declare class SecurityLogger {
55
- private static instance;
56
- private securityEvents;
57
- private maxEventHistory;
58
- private enableNotifications;
59
- private constructor();
60
- /**
61
- * Get singleton instance
62
- */
63
- static getInstance(options?: {
64
- maxEventHistory?: number;
65
- enableNotifications?: boolean;
66
- }): SecurityLogger;
67
- /**
68
- * Reset the singleton instance (for shutdown/testing)
69
- */
70
- static resetInstance(): void;
71
- /**
72
- * Log a security event
73
- * @param event The security event to log
74
- */
75
- logEvent(event: Omit<ISecurityEvent, 'timestamp'>): void;
76
- /**
77
- * Get recent security events
78
- * @param limit Maximum number of events to return
79
- * @param filter Filter for specific event types
80
- * @returns Recent security events
81
- */
82
- getRecentEvents(limit?: number, filter?: {
83
- level?: SecurityLogLevel;
84
- type?: SecurityEventType;
85
- fromTimestamp?: number;
86
- toTimestamp?: number;
87
- }): ISecurityEvent[];
88
- /**
89
- * Get events by security level
90
- * @param level The security level to filter by
91
- * @param limit Maximum number of events to return
92
- * @returns Security events matching the level
93
- */
94
- getEventsByLevel(level: SecurityLogLevel, limit?: number): ISecurityEvent[];
95
- /**
96
- * Get events by security type
97
- * @param type The event type to filter by
98
- * @param limit Maximum number of events to return
99
- * @returns Security events matching the type
100
- */
101
- getEventsByType(type: SecurityEventType, limit?: number): ISecurityEvent[];
102
- /**
103
- * Get security events for a specific IP address
104
- * @param ipAddress The IP address to filter by
105
- * @param limit Maximum number of events to return
106
- * @returns Security events for the IP address
107
- */
108
- getEventsByIP(ipAddress: string, limit?: number): ISecurityEvent[];
109
- /**
110
- * Get security events for a specific domain
111
- * @param domain The domain to filter by
112
- * @param limit Maximum number of events to return
113
- * @returns Security events for the domain
114
- */
115
- getEventsByDomain(domain: string, limit?: number): ISecurityEvent[];
116
- /**
117
- * Send a notification for critical security events
118
- * @param event The security event to notify about
119
- * @private
120
- */
121
- private sendNotification;
122
- /**
123
- * Clear event history
124
- */
125
- clearEvents(): void;
126
- /**
127
- * Get statistical summary of security events
128
- * @param timeWindow Optional time window in milliseconds
129
- * @returns Summary of security events
130
- */
131
- getEventsSummary(timeWindow?: number): {
132
- total: number;
133
- byLevel: Record<SecurityLogLevel, number>;
134
- byType: Record<SecurityEventType, number>;
135
- topIPs: Array<{
136
- ip: string;
137
- count: number;
138
- }>;
139
- topDomains: Array<{
140
- domain: string;
141
- count: number;
142
- }>;
143
- };
144
- }
@@ -1,233 +0,0 @@
1
- import * as plugins from '../plugins.js';
2
- import { logger } from '../logger.js';
3
- /**
4
- * Log level for security events
5
- */
6
- export var SecurityLogLevel;
7
- (function (SecurityLogLevel) {
8
- SecurityLogLevel["INFO"] = "info";
9
- SecurityLogLevel["WARN"] = "warn";
10
- SecurityLogLevel["ERROR"] = "error";
11
- SecurityLogLevel["CRITICAL"] = "critical";
12
- })(SecurityLogLevel || (SecurityLogLevel = {}));
13
- /**
14
- * Security event types for categorization
15
- */
16
- export var SecurityEventType;
17
- (function (SecurityEventType) {
18
- SecurityEventType["AUTHENTICATION"] = "authentication";
19
- SecurityEventType["ACCESS_CONTROL"] = "access_control";
20
- SecurityEventType["EMAIL_VALIDATION"] = "email_validation";
21
- SecurityEventType["EMAIL_PROCESSING"] = "email_processing";
22
- SecurityEventType["EMAIL_FORWARDING"] = "email_forwarding";
23
- SecurityEventType["EMAIL_DELIVERY"] = "email_delivery";
24
- SecurityEventType["DKIM"] = "dkim";
25
- SecurityEventType["SPF"] = "spf";
26
- SecurityEventType["DMARC"] = "dmarc";
27
- SecurityEventType["RATE_LIMIT"] = "rate_limit";
28
- SecurityEventType["RATE_LIMITING"] = "rate_limiting";
29
- SecurityEventType["SPAM"] = "spam";
30
- SecurityEventType["MALWARE"] = "malware";
31
- SecurityEventType["CONNECTION"] = "connection";
32
- SecurityEventType["DATA_EXPOSURE"] = "data_exposure";
33
- SecurityEventType["CONFIGURATION"] = "configuration";
34
- SecurityEventType["IP_REPUTATION"] = "ip_reputation";
35
- SecurityEventType["REJECTED_CONNECTION"] = "rejected_connection";
36
- })(SecurityEventType || (SecurityEventType = {}));
37
- /**
38
- * Security logger for enhanced security monitoring
39
- */
40
- export class SecurityLogger {
41
- static instance;
42
- securityEvents = [];
43
- maxEventHistory;
44
- enableNotifications;
45
- constructor(options) {
46
- this.maxEventHistory = options?.maxEventHistory || 1000;
47
- this.enableNotifications = options?.enableNotifications || false;
48
- }
49
- /**
50
- * Get singleton instance
51
- */
52
- static getInstance(options) {
53
- if (!SecurityLogger.instance) {
54
- SecurityLogger.instance = new SecurityLogger(options);
55
- }
56
- return SecurityLogger.instance;
57
- }
58
- /**
59
- * Reset the singleton instance (for shutdown/testing)
60
- */
61
- static resetInstance() {
62
- SecurityLogger.instance = undefined;
63
- }
64
- /**
65
- * Log a security event
66
- * @param event The security event to log
67
- */
68
- logEvent(event) {
69
- const fullEvent = {
70
- ...event,
71
- timestamp: Date.now()
72
- };
73
- // Store in memory buffer
74
- this.securityEvents.push(fullEvent);
75
- // Trim history if needed
76
- if (this.securityEvents.length > this.maxEventHistory) {
77
- this.securityEvents.shift();
78
- }
79
- // Log to regular logger with appropriate level
80
- switch (event.level) {
81
- case SecurityLogLevel.INFO:
82
- logger.log('info', `[SECURITY:${event.type}] ${event.message}`, event.details);
83
- break;
84
- case SecurityLogLevel.WARN:
85
- logger.log('warn', `[SECURITY:${event.type}] ${event.message}`, event.details);
86
- break;
87
- case SecurityLogLevel.ERROR:
88
- case SecurityLogLevel.CRITICAL:
89
- logger.log('error', `[SECURITY:${event.type}] ${event.message}`, event.details);
90
- // Send notification for critical events if enabled
91
- if (event.level === SecurityLogLevel.CRITICAL && this.enableNotifications) {
92
- this.sendNotification(fullEvent);
93
- }
94
- break;
95
- }
96
- }
97
- /**
98
- * Get recent security events
99
- * @param limit Maximum number of events to return
100
- * @param filter Filter for specific event types
101
- * @returns Recent security events
102
- */
103
- getRecentEvents(limit = 100, filter) {
104
- let filteredEvents = this.securityEvents;
105
- // Apply filters
106
- if (filter) {
107
- if (filter.level) {
108
- filteredEvents = filteredEvents.filter(event => event.level === filter.level);
109
- }
110
- if (filter.type) {
111
- filteredEvents = filteredEvents.filter(event => event.type === filter.type);
112
- }
113
- if (filter.fromTimestamp) {
114
- filteredEvents = filteredEvents.filter(event => event.timestamp >= filter.fromTimestamp);
115
- }
116
- if (filter.toTimestamp) {
117
- filteredEvents = filteredEvents.filter(event => event.timestamp <= filter.toTimestamp);
118
- }
119
- }
120
- // Return most recent events up to limit (slice first to avoid mutating source)
121
- return filteredEvents
122
- .slice()
123
- .sort((a, b) => b.timestamp - a.timestamp)
124
- .slice(0, limit);
125
- }
126
- /**
127
- * Get events by security level
128
- * @param level The security level to filter by
129
- * @param limit Maximum number of events to return
130
- * @returns Security events matching the level
131
- */
132
- getEventsByLevel(level, limit = 100) {
133
- return this.getRecentEvents(limit, { level });
134
- }
135
- /**
136
- * Get events by security type
137
- * @param type The event type to filter by
138
- * @param limit Maximum number of events to return
139
- * @returns Security events matching the type
140
- */
141
- getEventsByType(type, limit = 100) {
142
- return this.getRecentEvents(limit, { type });
143
- }
144
- /**
145
- * Get security events for a specific IP address
146
- * @param ipAddress The IP address to filter by
147
- * @param limit Maximum number of events to return
148
- * @returns Security events for the IP address
149
- */
150
- getEventsByIP(ipAddress, limit = 100) {
151
- return this.securityEvents
152
- .filter(event => event.ipAddress === ipAddress)
153
- .sort((a, b) => b.timestamp - a.timestamp)
154
- .slice(0, limit);
155
- }
156
- /**
157
- * Get security events for a specific domain
158
- * @param domain The domain to filter by
159
- * @param limit Maximum number of events to return
160
- * @returns Security events for the domain
161
- */
162
- getEventsByDomain(domain, limit = 100) {
163
- return this.securityEvents
164
- .filter(event => event.domain === domain)
165
- .sort((a, b) => b.timestamp - a.timestamp)
166
- .slice(0, limit);
167
- }
168
- /**
169
- * Send a notification for critical security events
170
- * @param event The security event to notify about
171
- * @private
172
- */
173
- sendNotification(event) {
174
- // In a production environment, this would integrate with a notification service
175
- // For now, we'll just log that we would send a notification
176
- logger.log('error', `[SECURITY NOTIFICATION] ${event.message}`, {
177
- ...event,
178
- notificationSent: true
179
- });
180
- // Future integration with alerting systems would go here
181
- }
182
- /**
183
- * Clear event history
184
- */
185
- clearEvents() {
186
- this.securityEvents = [];
187
- }
188
- /**
189
- * Get statistical summary of security events
190
- * @param timeWindow Optional time window in milliseconds
191
- * @returns Summary of security events
192
- */
193
- getEventsSummary(timeWindow) {
194
- const cutoff = timeWindow ? Date.now() - timeWindow : 0;
195
- // Initialize counters
196
- const byLevel = {};
197
- for (const level of Object.values(SecurityLogLevel)) {
198
- byLevel[level] = 0;
199
- }
200
- const byType = {};
201
- for (const type of Object.values(SecurityEventType)) {
202
- byType[type] = 0;
203
- }
204
- const ipCounts = new Map();
205
- const domainCounts = new Map();
206
- // Single pass over all events
207
- let total = 0;
208
- for (const e of this.securityEvents) {
209
- if (cutoff && e.timestamp < cutoff)
210
- continue;
211
- total++;
212
- byLevel[e.level]++;
213
- byType[e.type]++;
214
- if (e.ipAddress) {
215
- ipCounts.set(e.ipAddress, (ipCounts.get(e.ipAddress) || 0) + 1);
216
- }
217
- if (e.domain) {
218
- domainCounts.set(e.domain, (domainCounts.get(e.domain) || 0) + 1);
219
- }
220
- }
221
- // Sort and limit top entries
222
- const topIPs = Array.from(ipCounts.entries())
223
- .map(([ip, count]) => ({ ip, count }))
224
- .sort((a, b) => b.count - a.count)
225
- .slice(0, 10);
226
- const topDomains = Array.from(domainCounts.entries())
227
- .map(([domain, count]) => ({ domain, count }))
228
- .sort((a, b) => b.count - a.count)
229
- .slice(0, 10);
230
- return { total, byLevel, byType, topIPs, topDomains };
231
- }
232
- }
233
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZWN1cml0eWxvZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3NlY3VyaXR5L2NsYXNzZXMuc2VjdXJpdHlsb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUV0Qzs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGdCQUtYO0FBTEQsV0FBWSxnQkFBZ0I7SUFDMUIsaUNBQWEsQ0FBQTtJQUNiLGlDQUFhLENBQUE7SUFDYixtQ0FBZSxDQUFBO0lBQ2YseUNBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQUxXLGdCQUFnQixLQUFoQixnQkFBZ0IsUUFLM0I7QUFFRDs7R0FFRztBQUNILE1BQU0sQ0FBTixJQUFZLGlCQW1CWDtBQW5CRCxXQUFZLGlCQUFpQjtJQUMzQixzREFBaUMsQ0FBQTtJQUNqQyxzREFBaUMsQ0FBQTtJQUNqQywwREFBcUMsQ0FBQTtJQUNyQywwREFBcUMsQ0FBQTtJQUNyQywwREFBcUMsQ0FBQTtJQUNyQyxzREFBaUMsQ0FBQTtJQUNqQyxrQ0FBYSxDQUFBO0lBQ2IsZ0NBQVcsQ0FBQTtJQUNYLG9DQUFlLENBQUE7SUFDZiw4Q0FBeUIsQ0FBQTtJQUN6QixvREFBK0IsQ0FBQTtJQUMvQixrQ0FBYSxDQUFBO0lBQ2Isd0NBQW1CLENBQUE7SUFDbkIsOENBQXlCLENBQUE7SUFDekIsb0RBQStCLENBQUE7SUFDL0Isb0RBQStCLENBQUE7SUFDL0Isb0RBQStCLENBQUE7SUFDL0IsZ0VBQTJDLENBQUE7QUFDN0MsQ0FBQyxFQW5CVyxpQkFBaUIsS0FBakIsaUJBQWlCLFFBbUI1QjtBQXFCRDs7R0FFRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBQ2pCLE1BQU0sQ0FBQyxRQUFRLENBQWlCO0lBQ2hDLGNBQWMsR0FBcUIsRUFBRSxDQUFDO0lBQ3RDLGVBQWUs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