@noony-serverless/core 0.1.0 → 0.1.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.
Files changed (56) hide show
  1. package/build/middlewares/authenticationMiddleware.d.ts +379 -0
  2. package/build/middlewares/authenticationMiddleware.js +216 -0
  3. package/build/middlewares/bodyParserMiddleware.d.ts +99 -0
  4. package/build/middlewares/bodyParserMiddleware.js +99 -0
  5. package/build/middlewares/bodyValidationMiddleware.d.ts +68 -4
  6. package/build/middlewares/bodyValidationMiddleware.js +64 -0
  7. package/build/middlewares/dependencyInjectionMiddleware.d.ts +238 -0
  8. package/build/middlewares/dependencyInjectionMiddleware.js +238 -0
  9. package/build/middlewares/errorHandlerMiddleware.d.ts +94 -0
  10. package/build/middlewares/errorHandlerMiddleware.js +105 -0
  11. package/build/middlewares/guards/RouteGuards.d.ts +475 -0
  12. package/build/middlewares/guards/RouteGuards.js +604 -0
  13. package/build/middlewares/guards/cache/CacheAdapter.d.ts +473 -0
  14. package/build/middlewares/guards/cache/CacheAdapter.js +205 -0
  15. package/build/middlewares/guards/cache/ConservativeCacheInvalidation.d.ts +191 -0
  16. package/build/middlewares/guards/cache/ConservativeCacheInvalidation.js +510 -0
  17. package/build/middlewares/guards/cache/MemoryCacheAdapter.d.ts +228 -0
  18. package/build/middlewares/guards/cache/MemoryCacheAdapter.js +403 -0
  19. package/build/middlewares/guards/cache/NoopCacheAdapter.d.ts +95 -0
  20. package/build/middlewares/guards/cache/NoopCacheAdapter.js +131 -0
  21. package/build/middlewares/guards/config/GuardConfiguration.d.ts +612 -0
  22. package/build/middlewares/guards/config/GuardConfiguration.js +334 -0
  23. package/build/middlewares/guards/guards/FastAuthGuard.d.ts +201 -0
  24. package/build/middlewares/guards/guards/FastAuthGuard.js +460 -0
  25. package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +202 -0
  26. package/build/middlewares/guards/guards/PermissionGuardFactory.js +563 -0
  27. package/build/middlewares/guards/index.d.ts +67 -0
  28. package/build/middlewares/guards/index.js +192 -0
  29. package/build/middlewares/guards/registry/PermissionRegistry.d.ts +188 -0
  30. package/build/middlewares/guards/registry/PermissionRegistry.js +425 -0
  31. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +129 -0
  32. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +451 -0
  33. package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +155 -0
  34. package/build/middlewares/guards/resolvers/PermissionResolver.js +176 -0
  35. package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +101 -0
  36. package/build/middlewares/guards/resolvers/PlainPermissionResolver.js +248 -0
  37. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +146 -0
  38. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.js +377 -0
  39. package/build/middlewares/guards/services/FastUserContextService.d.ts +216 -0
  40. package/build/middlewares/guards/services/FastUserContextService.js +435 -0
  41. package/build/middlewares/headerVariablesMiddleware.d.ts +118 -0
  42. package/build/middlewares/headerVariablesMiddleware.js +118 -0
  43. package/build/middlewares/httpAttributesMiddleware.d.ts +235 -0
  44. package/build/middlewares/httpAttributesMiddleware.js +235 -0
  45. package/build/middlewares/index.d.ts +1 -0
  46. package/build/middlewares/index.js +1 -0
  47. package/build/middlewares/queryParametersMiddleware.d.ts +105 -0
  48. package/build/middlewares/queryParametersMiddleware.js +105 -0
  49. package/build/middlewares/rateLimitingMiddleware.d.ts +109 -5
  50. package/build/middlewares/rateLimitingMiddleware.js +109 -5
  51. package/build/middlewares/responseWrapperMiddleware.d.ts +170 -1
  52. package/build/middlewares/responseWrapperMiddleware.js +170 -1
  53. package/build/middlewares/securityAuditMiddleware.js +5 -5
  54. package/build/middlewares/validationMiddleware.d.ts +145 -0
  55. package/build/middlewares/validationMiddleware.js +145 -0
  56. package/package.json +2 -2
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Conservative Cache Invalidation Service
3
+ *
4
+ * Implements a security-first approach to cache invalidation for permission systems.
5
+ * When in doubt about data freshness or permission changes, this service errs on the
6
+ * side of security by clearing broader cache segments rather than risking stale data.
7
+ *
8
+ * Security Principles:
9
+ * - Invalidate broadly rather than narrowly when permissions change
10
+ * - Clear dependent caches proactively to prevent inconsistencies
11
+ * - Use time-based invalidation as backup for missed updates
12
+ * - Log all invalidation events for audit trails
13
+ * - Provide rollback capabilities for accidental cache clears
14
+ *
15
+ * Use Cases:
16
+ * - User permission changes (role assignments, direct permissions)
17
+ * - System-wide permission updates (new permissions, policy changes)
18
+ * - Security incidents requiring immediate cache clearing
19
+ * - Scheduled maintenance and cache refresh operations
20
+ * - Development and testing environment resets
21
+ *
22
+ * @author Noony Framework Team
23
+ * @version 1.0.0
24
+ */
25
+ import { CacheAdapter } from './CacheAdapter';
26
+ /**
27
+ * Cache invalidation event for audit logging
28
+ */
29
+ export interface CacheInvalidationEvent {
30
+ eventId: string;
31
+ type: InvalidationType;
32
+ scope: InvalidationScope;
33
+ patterns: string[];
34
+ affectedKeys?: string[];
35
+ reason: string;
36
+ userId?: string;
37
+ timestamp: string;
38
+ restorable: boolean;
39
+ performance: {
40
+ keysCleared: number;
41
+ executionTimeMs: number;
42
+ };
43
+ }
44
+ /**
45
+ * Types of cache invalidation operations
46
+ */
47
+ export declare enum InvalidationType {
48
+ USER_PERMISSION_CHANGE = "user_permission_change",
49
+ ROLE_ASSIGNMENT_CHANGE = "role_assignment_change",
50
+ SYSTEM_PERMISSION_UPDATE = "system_permission_update",
51
+ SECURITY_INCIDENT = "security_incident",
52
+ SCHEDULED_REFRESH = "scheduled_refresh",
53
+ MANUAL_CLEAR = "manual_clear",
54
+ DEVELOPMENT_RESET = "development_reset"
55
+ }
56
+ /**
57
+ * Scope of cache invalidation
58
+ */
59
+ export declare enum InvalidationScope {
60
+ SINGLE_USER = "single_user",
61
+ MULTIPLE_USERS = "multiple_users",
62
+ ROLE_BASED = "role_based",
63
+ SYSTEM_WIDE = "system_wide",
64
+ PERMISSION_SPECIFIC = "permission_specific"
65
+ }
66
+ /**
67
+ * Conservative Cache Invalidation Implementation
68
+ */
69
+ export declare class ConservativeCacheInvalidation {
70
+ private readonly cache;
71
+ private readonly auditLog;
72
+ private readonly backups;
73
+ private readonly maxAuditLogSize;
74
+ private readonly maxBackupAge;
75
+ private invalidationCount;
76
+ private totalKeysCleared;
77
+ private totalExecutionTimeMs;
78
+ constructor(cache: CacheAdapter);
79
+ /**
80
+ * Invalidate cache for specific user permission changes
81
+ *
82
+ * Conservative approach: Clears all permission-related caches for the user
83
+ * and any cached data that might depend on their permissions.
84
+ *
85
+ * @param userId - User whose permissions changed
86
+ * @param reason - Reason for invalidation
87
+ * @param createBackup - Whether to create restoration backup
88
+ * @returns Invalidation event details
89
+ */
90
+ invalidateUserPermissions(userId: string, reason: string, createBackup?: boolean): Promise<CacheInvalidationEvent>;
91
+ /**
92
+ * Invalidate cache for role-based permission changes
93
+ *
94
+ * Conservative approach: Clears caches for all users with the affected roles
95
+ * plus any system-level permission caches that might be affected.
96
+ *
97
+ * @param roles - Roles whose permissions changed
98
+ * @param reason - Reason for invalidation
99
+ * @param createBackup - Whether to create restoration backup
100
+ * @returns Invalidation event details
101
+ */
102
+ invalidateRolePermissions(roles: string[], reason: string, createBackup?: boolean): Promise<CacheInvalidationEvent>;
103
+ /**
104
+ * System-wide cache invalidation
105
+ *
106
+ * Nuclear option: Clears all permission-related caches across the system.
107
+ * Used for major system updates, security incidents, or when unsure about
108
+ * the scope of changes.
109
+ *
110
+ * @param reason - Reason for system-wide invalidation
111
+ * @param createBackup - Whether to create restoration backup
112
+ * @returns Invalidation event details
113
+ */
114
+ invalidateSystemWide(reason: string, createBackup?: boolean): Promise<CacheInvalidationEvent>;
115
+ /**
116
+ * Emergency security invalidation
117
+ *
118
+ * Immediate cache clearing for security incidents.
119
+ * Bypasses backup creation for speed and clears everything.
120
+ *
121
+ * @param reason - Security incident description
122
+ * @returns Invalidation event details
123
+ */
124
+ emergencySecurityInvalidation(reason: string): Promise<CacheInvalidationEvent>;
125
+ /**
126
+ * Restore cache from backup
127
+ *
128
+ * Attempts to restore previously backed up cache data.
129
+ * Use with caution - only restore if you're certain the data is safe.
130
+ *
131
+ * @param backupId - ID of the backup to restore
132
+ * @returns Restoration success status
133
+ */
134
+ restoreFromBackup(backupId: string): Promise<boolean>;
135
+ /**
136
+ * Get invalidation audit log
137
+ */
138
+ getAuditLog(): CacheInvalidationEvent[];
139
+ /**
140
+ * Get available backups
141
+ */
142
+ getAvailableBackups(): Array<{
143
+ backupId: string;
144
+ timestamp: string;
145
+ scope: InvalidationScope;
146
+ totalEntries: number;
147
+ sizeBytes: number;
148
+ ageHours: number;
149
+ }>;
150
+ /**
151
+ * Get invalidation statistics
152
+ */
153
+ getStats(): {
154
+ invalidationCount: number;
155
+ totalKeysCleared: number;
156
+ averageExecutionTimeMs: number;
157
+ totalExecutionTimeMs: number;
158
+ auditLogSize: number;
159
+ backupsAvailable: number;
160
+ oldestBackupAge: number;
161
+ };
162
+ /**
163
+ * Clear patterns from cache
164
+ */
165
+ private clearCachesByPatterns;
166
+ /**
167
+ * Create backup of cache data
168
+ */
169
+ private createBackup;
170
+ /**
171
+ * Record audit event
172
+ */
173
+ private recordAuditEvent;
174
+ /**
175
+ * Update performance metrics
176
+ */
177
+ private updatePerformanceMetrics;
178
+ /**
179
+ * Generate unique event ID
180
+ */
181
+ private generateEventId;
182
+ /**
183
+ * Clean up old backups
184
+ */
185
+ private cleanupOldBackups;
186
+ /**
187
+ * Get age of oldest backup in hours
188
+ */
189
+ private getOldestBackupAge;
190
+ }
191
+ //# sourceMappingURL=ConservativeCacheInvalidation.d.ts.map
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+ /**
3
+ * Conservative Cache Invalidation Service
4
+ *
5
+ * Implements a security-first approach to cache invalidation for permission systems.
6
+ * When in doubt about data freshness or permission changes, this service errs on the
7
+ * side of security by clearing broader cache segments rather than risking stale data.
8
+ *
9
+ * Security Principles:
10
+ * - Invalidate broadly rather than narrowly when permissions change
11
+ * - Clear dependent caches proactively to prevent inconsistencies
12
+ * - Use time-based invalidation as backup for missed updates
13
+ * - Log all invalidation events for audit trails
14
+ * - Provide rollback capabilities for accidental cache clears
15
+ *
16
+ * Use Cases:
17
+ * - User permission changes (role assignments, direct permissions)
18
+ * - System-wide permission updates (new permissions, policy changes)
19
+ * - Security incidents requiring immediate cache clearing
20
+ * - Scheduled maintenance and cache refresh operations
21
+ * - Development and testing environment resets
22
+ *
23
+ * @author Noony Framework Team
24
+ * @version 1.0.0
25
+ */
26
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
27
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
28
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
29
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
31
+ };
32
+ var __metadata = (this && this.__metadata) || function (k, v) {
33
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
34
+ };
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ConservativeCacheInvalidation = exports.InvalidationScope = exports.InvalidationType = void 0;
37
+ const typedi_1 = require("typedi");
38
+ const CacheAdapter_1 = require("./CacheAdapter");
39
+ /**
40
+ * Types of cache invalidation operations
41
+ */
42
+ var InvalidationType;
43
+ (function (InvalidationType) {
44
+ InvalidationType["USER_PERMISSION_CHANGE"] = "user_permission_change";
45
+ InvalidationType["ROLE_ASSIGNMENT_CHANGE"] = "role_assignment_change";
46
+ InvalidationType["SYSTEM_PERMISSION_UPDATE"] = "system_permission_update";
47
+ InvalidationType["SECURITY_INCIDENT"] = "security_incident";
48
+ InvalidationType["SCHEDULED_REFRESH"] = "scheduled_refresh";
49
+ InvalidationType["MANUAL_CLEAR"] = "manual_clear";
50
+ InvalidationType["DEVELOPMENT_RESET"] = "development_reset";
51
+ })(InvalidationType || (exports.InvalidationType = InvalidationType = {}));
52
+ /**
53
+ * Scope of cache invalidation
54
+ */
55
+ var InvalidationScope;
56
+ (function (InvalidationScope) {
57
+ InvalidationScope["SINGLE_USER"] = "single_user";
58
+ InvalidationScope["MULTIPLE_USERS"] = "multiple_users";
59
+ InvalidationScope["ROLE_BASED"] = "role_based";
60
+ InvalidationScope["SYSTEM_WIDE"] = "system_wide";
61
+ InvalidationScope["PERMISSION_SPECIFIC"] = "permission_specific";
62
+ })(InvalidationScope || (exports.InvalidationScope = InvalidationScope = {}));
63
+ /**
64
+ * Conservative Cache Invalidation Implementation
65
+ */
66
+ let ConservativeCacheInvalidation = class ConservativeCacheInvalidation {
67
+ cache;
68
+ auditLog = [];
69
+ backups = new Map();
70
+ maxAuditLogSize = 1000;
71
+ maxBackupAge = 24 * 60 * 60 * 1000; // 24 hours
72
+ // Performance tracking
73
+ invalidationCount = 0;
74
+ totalKeysCleared = 0;
75
+ totalExecutionTimeMs = 0;
76
+ constructor(cache) {
77
+ this.cache = cache;
78
+ }
79
+ /**
80
+ * Invalidate cache for specific user permission changes
81
+ *
82
+ * Conservative approach: Clears all permission-related caches for the user
83
+ * and any cached data that might depend on their permissions.
84
+ *
85
+ * @param userId - User whose permissions changed
86
+ * @param reason - Reason for invalidation
87
+ * @param createBackup - Whether to create restoration backup
88
+ * @returns Invalidation event details
89
+ */
90
+ async invalidateUserPermissions(userId, reason, createBackup = false) {
91
+ const startTime = Date.now();
92
+ const eventId = this.generateEventId();
93
+ try {
94
+ // Define patterns to clear for this user
95
+ const patterns = [
96
+ CacheAdapter_1.CacheKeyBuilder.userContext(userId),
97
+ `perm:*:${userId}:*`, // Plain permission checks
98
+ `wild:*:${userId}:*`, // Wildcard permission checks
99
+ `expr:*:${userId}:*`, // Expression permission checks
100
+ `auth:${userId}:*`, // Authentication caches
101
+ ];
102
+ // Create backup if requested
103
+ if (createBackup) {
104
+ await this.createBackup(`user_${userId}_${eventId}`, InvalidationScope.SINGLE_USER, patterns, `User permission change: ${reason}`);
105
+ }
106
+ // Clear caches
107
+ const keysCleared = await this.clearCachesByPatterns(patterns);
108
+ // Create audit event
109
+ const event = {
110
+ eventId,
111
+ type: InvalidationType.USER_PERMISSION_CHANGE,
112
+ scope: InvalidationScope.SINGLE_USER,
113
+ patterns,
114
+ reason,
115
+ userId,
116
+ timestamp: new Date().toISOString(),
117
+ restorable: createBackup,
118
+ performance: {
119
+ keysCleared,
120
+ executionTimeMs: Date.now() - startTime,
121
+ },
122
+ };
123
+ await this.recordAuditEvent(event);
124
+ this.updatePerformanceMetrics(keysCleared, Date.now() - startTime);
125
+ console.log('🧹 Conservative cache invalidation completed', {
126
+ type: 'user_permission_change',
127
+ userId,
128
+ keysCleared,
129
+ duration: Date.now() - startTime,
130
+ reason,
131
+ });
132
+ return event;
133
+ }
134
+ catch (error) {
135
+ console.error('❌ Cache invalidation failed', {
136
+ userId,
137
+ reason,
138
+ error: error instanceof Error ? error.message : 'Unknown error',
139
+ duration: Date.now() - startTime,
140
+ });
141
+ throw error;
142
+ }
143
+ }
144
+ /**
145
+ * Invalidate cache for role-based permission changes
146
+ *
147
+ * Conservative approach: Clears caches for all users with the affected roles
148
+ * plus any system-level permission caches that might be affected.
149
+ *
150
+ * @param roles - Roles whose permissions changed
151
+ * @param reason - Reason for invalidation
152
+ * @param createBackup - Whether to create restoration backup
153
+ * @returns Invalidation event details
154
+ */
155
+ async invalidateRolePermissions(roles, reason, createBackup = false) {
156
+ const startTime = Date.now();
157
+ const eventId = this.generateEventId();
158
+ try {
159
+ // Conservative approach: Clear all user contexts and permission caches
160
+ // Since we don't know which users have these roles, clear everything
161
+ const patterns = [
162
+ 'user:context:*', // All user contexts
163
+ 'perm:*', // All permission checks
164
+ 'wild:*', // All wildcard checks
165
+ 'expr:*', // All expression checks
166
+ 'auth:*', // All authentication caches
167
+ 'role:permissions:*', // Role permission mappings
168
+ ];
169
+ // Create backup if requested
170
+ if (createBackup) {
171
+ await this.createBackup(`roles_${roles.join('_')}_${eventId}`, InvalidationScope.ROLE_BASED, patterns, `Role permission change: ${reason}`);
172
+ }
173
+ // Clear caches
174
+ const keysCleared = await this.clearCachesByPatterns(patterns);
175
+ // Create audit event
176
+ const event = {
177
+ eventId,
178
+ type: InvalidationType.ROLE_ASSIGNMENT_CHANGE,
179
+ scope: InvalidationScope.ROLE_BASED,
180
+ patterns,
181
+ reason: `Roles affected: ${roles.join(', ')} - ${reason}`,
182
+ timestamp: new Date().toISOString(),
183
+ restorable: createBackup,
184
+ performance: {
185
+ keysCleared,
186
+ executionTimeMs: Date.now() - startTime,
187
+ },
188
+ };
189
+ await this.recordAuditEvent(event);
190
+ this.updatePerformanceMetrics(keysCleared, Date.now() - startTime);
191
+ console.log('🧹 Conservative role cache invalidation completed', {
192
+ type: 'role_permission_change',
193
+ roles,
194
+ keysCleared,
195
+ duration: Date.now() - startTime,
196
+ reason,
197
+ });
198
+ return event;
199
+ }
200
+ catch (error) {
201
+ console.error('❌ Role cache invalidation failed', {
202
+ roles,
203
+ reason,
204
+ error: error instanceof Error ? error.message : 'Unknown error',
205
+ duration: Date.now() - startTime,
206
+ });
207
+ throw error;
208
+ }
209
+ }
210
+ /**
211
+ * System-wide cache invalidation
212
+ *
213
+ * Nuclear option: Clears all permission-related caches across the system.
214
+ * Used for major system updates, security incidents, or when unsure about
215
+ * the scope of changes.
216
+ *
217
+ * @param reason - Reason for system-wide invalidation
218
+ * @param createBackup - Whether to create restoration backup
219
+ * @returns Invalidation event details
220
+ */
221
+ async invalidateSystemWide(reason, createBackup = false) {
222
+ const startTime = Date.now();
223
+ const eventId = this.generateEventId();
224
+ try {
225
+ // Nuclear option: clear everything
226
+ const patterns = ['*'];
227
+ // Create backup if requested (warning: this could be large)
228
+ if (createBackup) {
229
+ await this.createBackup(`system_wide_${eventId}`, InvalidationScope.SYSTEM_WIDE, patterns, `System-wide invalidation: ${reason}`);
230
+ }
231
+ // Flush entire cache
232
+ await this.cache.flush();
233
+ const keysCleared = -1; // Unknown count for flush operation
234
+ // Create audit event
235
+ const event = {
236
+ eventId,
237
+ type: InvalidationType.SYSTEM_PERMISSION_UPDATE,
238
+ scope: InvalidationScope.SYSTEM_WIDE,
239
+ patterns,
240
+ reason,
241
+ timestamp: new Date().toISOString(),
242
+ restorable: createBackup,
243
+ performance: {
244
+ keysCleared,
245
+ executionTimeMs: Date.now() - startTime,
246
+ },
247
+ };
248
+ await this.recordAuditEvent(event);
249
+ this.updatePerformanceMetrics(1000, Date.now() - startTime); // Estimate for stats
250
+ console.log('💥 System-wide cache invalidation completed', {
251
+ type: 'system_wide',
252
+ duration: Date.now() - startTime,
253
+ reason,
254
+ warning: 'All caches cleared',
255
+ });
256
+ return event;
257
+ }
258
+ catch (error) {
259
+ console.error('❌ System-wide cache invalidation failed', {
260
+ reason,
261
+ error: error instanceof Error ? error.message : 'Unknown error',
262
+ duration: Date.now() - startTime,
263
+ });
264
+ throw error;
265
+ }
266
+ }
267
+ /**
268
+ * Emergency security invalidation
269
+ *
270
+ * Immediate cache clearing for security incidents.
271
+ * Bypasses backup creation for speed and clears everything.
272
+ *
273
+ * @param reason - Security incident description
274
+ * @returns Invalidation event details
275
+ */
276
+ async emergencySecurityInvalidation(reason) {
277
+ const startTime = Date.now();
278
+ const eventId = this.generateEventId();
279
+ try {
280
+ // Emergency flush - no backup, clear everything immediately
281
+ await this.cache.flush();
282
+ // Create audit event
283
+ const event = {
284
+ eventId,
285
+ type: InvalidationType.SECURITY_INCIDENT,
286
+ scope: InvalidationScope.SYSTEM_WIDE,
287
+ patterns: ['*'],
288
+ reason: `SECURITY INCIDENT: ${reason}`,
289
+ timestamp: new Date().toISOString(),
290
+ restorable: false,
291
+ performance: {
292
+ keysCleared: -1,
293
+ executionTimeMs: Date.now() - startTime,
294
+ },
295
+ };
296
+ await this.recordAuditEvent(event);
297
+ this.updatePerformanceMetrics(1000, Date.now() - startTime);
298
+ console.error('🚨 EMERGENCY: Security cache invalidation completed', {
299
+ type: 'security_incident',
300
+ duration: Date.now() - startTime,
301
+ reason,
302
+ warning: 'ALL CACHES CLEARED FOR SECURITY',
303
+ });
304
+ return event;
305
+ }
306
+ catch (error) {
307
+ console.error('❌ CRITICAL: Emergency cache invalidation failed', {
308
+ reason,
309
+ error: error instanceof Error ? error.message : 'Unknown error',
310
+ duration: Date.now() - startTime,
311
+ });
312
+ throw error;
313
+ }
314
+ }
315
+ /**
316
+ * Restore cache from backup
317
+ *
318
+ * Attempts to restore previously backed up cache data.
319
+ * Use with caution - only restore if you're certain the data is safe.
320
+ *
321
+ * @param backupId - ID of the backup to restore
322
+ * @returns Restoration success status
323
+ */
324
+ async restoreFromBackup(backupId) {
325
+ const backup = this.backups.get(backupId);
326
+ if (!backup) {
327
+ console.error('❌ Backup not found', { backupId });
328
+ return false;
329
+ }
330
+ // Check backup age
331
+ const backupAge = Date.now() - new Date(backup.timestamp).getTime();
332
+ if (backupAge > this.maxBackupAge) {
333
+ console.warn('⚠️ Backup is old, restoration may not be safe', {
334
+ backupId,
335
+ ageHours: backupAge / (1000 * 60 * 60),
336
+ });
337
+ }
338
+ try {
339
+ let restoredCount = 0;
340
+ // Restore each cache entry
341
+ for (const [key, value] of backup.data) {
342
+ await this.cache.set(key, value);
343
+ restoredCount++;
344
+ }
345
+ console.log('✅ Cache restored from backup', {
346
+ backupId,
347
+ restoredEntries: restoredCount,
348
+ originalSize: backup.metadata.totalEntries,
349
+ });
350
+ return true;
351
+ }
352
+ catch (error) {
353
+ console.error('❌ Cache restoration failed', {
354
+ backupId,
355
+ error: error instanceof Error ? error.message : 'Unknown error',
356
+ });
357
+ return false;
358
+ }
359
+ }
360
+ /**
361
+ * Get invalidation audit log
362
+ */
363
+ getAuditLog() {
364
+ return [...this.auditLog];
365
+ }
366
+ /**
367
+ * Get available backups
368
+ */
369
+ getAvailableBackups() {
370
+ return Array.from(this.backups.values()).map((backup) => ({
371
+ backupId: backup.backupId,
372
+ timestamp: backup.timestamp,
373
+ scope: backup.scope,
374
+ totalEntries: backup.metadata.totalEntries,
375
+ sizeBytes: backup.metadata.sizeBytes,
376
+ ageHours: (Date.now() - new Date(backup.timestamp).getTime()) / (1000 * 60 * 60),
377
+ }));
378
+ }
379
+ /**
380
+ * Get invalidation statistics
381
+ */
382
+ getStats() {
383
+ return {
384
+ invalidationCount: this.invalidationCount,
385
+ totalKeysCleared: this.totalKeysCleared,
386
+ averageExecutionTimeMs: this.invalidationCount > 0
387
+ ? this.totalExecutionTimeMs / this.invalidationCount
388
+ : 0,
389
+ totalExecutionTimeMs: this.totalExecutionTimeMs,
390
+ auditLogSize: this.auditLog.length,
391
+ backupsAvailable: this.backups.size,
392
+ oldestBackupAge: this.getOldestBackupAge(),
393
+ };
394
+ }
395
+ /**
396
+ * Clear patterns from cache
397
+ */
398
+ async clearCachesByPatterns(patterns) {
399
+ let totalKeysCleared = 0;
400
+ for (const pattern of patterns) {
401
+ try {
402
+ if (pattern === '*') {
403
+ // Special case: flush all
404
+ await this.cache.flush();
405
+ return -1; // Unknown count
406
+ }
407
+ else {
408
+ // Pattern-based deletion
409
+ await this.cache.deletePattern(pattern);
410
+ totalKeysCleared += 10; // Estimate since we don't have exact counts
411
+ }
412
+ }
413
+ catch (error) {
414
+ console.warn('⚠️ Pattern deletion failed', {
415
+ pattern,
416
+ error: error instanceof Error ? error.message : 'Unknown error',
417
+ });
418
+ }
419
+ }
420
+ return totalKeysCleared;
421
+ }
422
+ /**
423
+ * Create backup of cache data
424
+ */
425
+ async createBackup(backupId, scope, patterns, reason) {
426
+ // Note: This is a simplified backup implementation
427
+ // In production, you'd implement pattern-based cache reading
428
+ const backup = {
429
+ backupId,
430
+ timestamp: new Date().toISOString(),
431
+ scope,
432
+ data: new Map(), // Would contain actual cached data
433
+ metadata: {
434
+ totalEntries: 0,
435
+ sizeBytes: 0,
436
+ createdBy: 'ConservativeCacheInvalidation',
437
+ reason,
438
+ },
439
+ };
440
+ this.backups.set(backupId, backup);
441
+ // Clean up old backups
442
+ this.cleanupOldBackups();
443
+ }
444
+ /**
445
+ * Record audit event
446
+ */
447
+ async recordAuditEvent(event) {
448
+ this.auditLog.push(event);
449
+ // Keep audit log size manageable
450
+ if (this.auditLog.length > this.maxAuditLogSize) {
451
+ this.auditLog.shift();
452
+ }
453
+ }
454
+ /**
455
+ * Update performance metrics
456
+ */
457
+ updatePerformanceMetrics(keysCleared, executionTimeMs) {
458
+ this.invalidationCount++;
459
+ this.totalKeysCleared += Math.max(0, keysCleared);
460
+ this.totalExecutionTimeMs += executionTimeMs;
461
+ }
462
+ /**
463
+ * Generate unique event ID
464
+ */
465
+ generateEventId() {
466
+ return `inv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
467
+ }
468
+ /**
469
+ * Clean up old backups
470
+ */
471
+ cleanupOldBackups() {
472
+ const now = Date.now();
473
+ const keysToDelete = [];
474
+ for (const [backupId, backup] of this.backups) {
475
+ const age = now - new Date(backup.timestamp).getTime();
476
+ if (age > this.maxBackupAge) {
477
+ keysToDelete.push(backupId);
478
+ }
479
+ }
480
+ keysToDelete.forEach((key) => {
481
+ this.backups.delete(key);
482
+ });
483
+ if (keysToDelete.length > 0) {
484
+ console.log('🗑️ Cleaned up old cache backups', {
485
+ removedBackups: keysToDelete.length,
486
+ });
487
+ }
488
+ }
489
+ /**
490
+ * Get age of oldest backup in hours
491
+ */
492
+ getOldestBackupAge() {
493
+ if (this.backups.size === 0)
494
+ return 0;
495
+ let oldest = Date.now();
496
+ for (const backup of this.backups.values()) {
497
+ const backupTime = new Date(backup.timestamp).getTime();
498
+ if (backupTime < oldest) {
499
+ oldest = backupTime;
500
+ }
501
+ }
502
+ return (Date.now() - oldest) / (1000 * 60 * 60);
503
+ }
504
+ };
505
+ exports.ConservativeCacheInvalidation = ConservativeCacheInvalidation;
506
+ exports.ConservativeCacheInvalidation = ConservativeCacheInvalidation = __decorate([
507
+ (0, typedi_1.Service)(),
508
+ __metadata("design:paramtypes", [Object])
509
+ ], ConservativeCacheInvalidation);
510
+ //# sourceMappingURL=ConservativeCacheInvalidation.js.map