@serve.zone/dcrouter 11.10.3 → 11.10.7

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 (76) hide show
  1. package/dist_serve/bundle.js +5102 -5102
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/cache/classes.cache.cleaner.js +1 -1
  4. package/dist_ts/cache/classes.cached.document.js +1 -1
  5. package/dist_ts/cache/classes.cachedb.js +1 -1
  6. package/dist_ts/cache/documents/classes.cached.email.js +1 -1
  7. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +1 -1
  8. package/dist_ts/classes.dcrouter.js +3 -3
  9. package/dist_ts/config/classes.route-config-manager.d.ts +1 -1
  10. package/dist_ts/config/validator.js +1 -1
  11. package/dist_ts/errors/base.errors.js +2 -2
  12. package/dist_ts/monitoring/classes.metricsmanager.d.ts +6 -1
  13. package/dist_ts/monitoring/classes.metricsmanager.js +69 -31
  14. package/dist_ts/opsserver/classes.opsserver.js +2 -2
  15. package/dist_ts/opsserver/handlers/admin.handler.js +1 -1
  16. package/dist_ts/opsserver/handlers/certificate.handler.js +1 -1
  17. package/dist_ts/opsserver/handlers/radius.handler.js +1 -1
  18. package/dist_ts/opsserver/handlers/stats.handler.js +1 -1
  19. package/dist_ts/radius/classes.accounting.manager.js +1 -1
  20. package/dist_ts/radius/classes.radius.server.js +1 -1
  21. package/dist_ts/radius/classes.vlan.manager.js +1 -1
  22. package/dist_ts/security/classes.contentscanner.js +3 -3
  23. package/dist_ts/security/classes.ipreputationchecker.js +4 -4
  24. package/dist_ts/security/classes.securitylogger.js +5 -3
  25. package/dist_ts/sms/classes.smsservice.js +2 -2
  26. package/dist_ts/storage/classes.storagemanager.d.ts +1 -1
  27. package/dist_ts/storage/classes.storagemanager.js +2 -4
  28. package/dist_ts_web/00_commitinfo_data.js +1 -1
  29. package/dist_ts_web/appstate.js +9 -6
  30. package/dist_ts_web/elements/ops-dashboard.js +3 -2
  31. package/dist_ts_web/elements/ops-view-certificates.js +1 -1
  32. package/dist_ts_web/elements/ops-view-config.js +1 -1
  33. package/dist_ts_web/elements/ops-view-emails.js +1 -1
  34. package/dist_ts_web/elements/ops-view-network.js +1 -1
  35. package/dist_ts_web/elements/ops-view-remoteingress.js +1 -1
  36. package/dist_ts_web/router.js +1 -1
  37. package/license +21 -0
  38. package/package.json +15 -15
  39. package/readme.hints.md +1 -1
  40. package/readme.md +1 -1
  41. package/ts/00_commitinfo_data.ts +1 -1
  42. package/ts/cache/classes.cache.cleaner.ts +10 -10
  43. package/ts/cache/classes.cached.document.ts +1 -1
  44. package/ts/cache/classes.cachedb.ts +6 -6
  45. package/ts/cache/documents/classes.cached.email.ts +14 -14
  46. package/ts/cache/documents/classes.cached.ip.reputation.ts +10 -10
  47. package/ts/classes.dcrouter.ts +31 -31
  48. package/ts/config/validator.ts +5 -5
  49. package/ts/errors/base.errors.ts +1 -1
  50. package/ts/monitoring/classes.metricsmanager.ts +70 -33
  51. package/ts/opsserver/classes.opsserver.ts +13 -13
  52. package/ts/opsserver/handlers/admin.handler.ts +1 -1
  53. package/ts/opsserver/handlers/certificate.handler.ts +6 -6
  54. package/ts/opsserver/handlers/radius.handler.ts +4 -4
  55. package/ts/opsserver/handlers/stats.handler.ts +1 -1
  56. package/ts/radius/classes.accounting.manager.ts +10 -10
  57. package/ts/radius/classes.radius.server.ts +2 -2
  58. package/ts/radius/classes.vlan.manager.ts +5 -5
  59. package/ts/readme.md +1 -1
  60. package/ts/security/classes.contentscanner.ts +12 -12
  61. package/ts/security/classes.ipreputationchecker.ts +26 -26
  62. package/ts/security/classes.securitylogger.ts +6 -4
  63. package/ts/sms/classes.smsservice.ts +3 -3
  64. package/ts/storage/classes.storagemanager.ts +23 -25
  65. package/ts_apiclient/readme.md +1 -1
  66. package/ts_web/00_commitinfo_data.ts +1 -1
  67. package/ts_web/appstate.ts +136 -133
  68. package/ts_web/elements/ops-dashboard.ts +15 -14
  69. package/ts_web/elements/ops-view-certificates.ts +10 -10
  70. package/ts_web/elements/ops-view-config.ts +8 -8
  71. package/ts_web/elements/ops-view-emails.ts +2 -2
  72. package/ts_web/elements/ops-view-network.ts +2 -2
  73. package/ts_web/elements/ops-view-remoteingress.ts +6 -6
  74. package/ts_web/readme.md +1 -1
  75. package/ts_web/router.ts +3 -3
  76. /package/{npmextra.json → .smartconfig.json} +0 -0
@@ -518,8 +518,8 @@ export class AccountingManager {
518
518
  if (deletedCount > 0) {
519
519
  logger.log('info', `Cleaned up ${deletedCount} old accounting sessions`);
520
520
  }
521
- } catch (error) {
522
- logger.log('error', `Failed to cleanup old sessions: ${error.message}`);
521
+ } catch (error: unknown) {
522
+ logger.log('error', `Failed to cleanup old sessions: ${(error as Error).message}`);
523
523
  }
524
524
 
525
525
  return deletedCount;
@@ -582,8 +582,8 @@ export class AccountingManager {
582
582
  // Ignore individual errors
583
583
  }
584
584
  }
585
- } catch (error) {
586
- logger.log('warn', `Failed to load active sessions: ${error.message}`);
585
+ } catch (error: unknown) {
586
+ logger.log('warn', `Failed to load active sessions: ${(error as Error).message}`);
587
587
  }
588
588
  }
589
589
 
@@ -598,8 +598,8 @@ export class AccountingManager {
598
598
  const key = `${this.config.storagePrefix}/active/${session.sessionId}.json`;
599
599
  try {
600
600
  await this.storageManager.setJSON(key, session);
601
- } catch (error) {
602
- logger.log('error', `Failed to persist session ${session.sessionId}: ${error.message}`);
601
+ } catch (error: unknown) {
602
+ logger.log('error', `Failed to persist session ${session.sessionId}: ${(error as Error).message}`);
603
603
  }
604
604
  }
605
605
 
@@ -620,8 +620,8 @@ export class AccountingManager {
620
620
  const date = new Date(session.endTime);
621
621
  const archiveKey = `${this.config.storagePrefix}/archive/${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')}/${session.sessionId}.json`;
622
622
  await this.storageManager.setJSON(archiveKey, session);
623
- } catch (error) {
624
- logger.log('error', `Failed to archive session ${session.sessionId}: ${error.message}`);
623
+ } catch (error: unknown) {
624
+ logger.log('error', `Failed to archive session ${session.sessionId}: ${(error as Error).message}`);
625
625
  }
626
626
  }
627
627
 
@@ -653,8 +653,8 @@ export class AccountingManager {
653
653
  // Ignore individual errors
654
654
  }
655
655
  }
656
- } catch (error) {
657
- logger.log('warn', `Failed to get archived sessions: ${error.message}`);
656
+ } catch (error: unknown) {
657
+ logger.log('warn', `Failed to get archived sessions: ${(error as Error).message}`);
658
658
  }
659
659
 
660
660
  return sessions;
@@ -310,8 +310,8 @@ export class RadiusServer {
310
310
  default:
311
311
  logger.log('debug', `RADIUS Acct Unknown status type: ${statusType}`);
312
312
  }
313
- } catch (error) {
314
- logger.log('error', `RADIUS accounting error: ${error.message}`);
313
+ } catch (error: unknown) {
314
+ logger.log('error', `RADIUS accounting error: ${(error as Error).message}`);
315
315
  }
316
316
 
317
317
  return { code: plugins.smartradius.ERadiusCode.AccountingResponse };
@@ -104,7 +104,7 @@ export class VlanManager {
104
104
  if (this.normalizedMacCache.size > 10000) {
105
105
  const iterator = this.normalizedMacCache.keys();
106
106
  for (let i = 0; i < 1000; i++) {
107
- this.normalizedMacCache.delete(iterator.next().value);
107
+ this.normalizedMacCache.delete(iterator.next().value!);
108
108
  }
109
109
  }
110
110
 
@@ -348,8 +348,8 @@ export class VlanManager {
348
348
  }
349
349
  logger.log('info', `Loaded ${data.length} VLAN mappings from storage`);
350
350
  }
351
- } catch (error) {
352
- logger.log('warn', `Failed to load VLAN mappings from storage: ${error.message}`);
351
+ } catch (error: unknown) {
352
+ logger.log('warn', `Failed to load VLAN mappings from storage: ${(error as Error).message}`);
353
353
  }
354
354
  }
355
355
 
@@ -364,8 +364,8 @@ export class VlanManager {
364
364
  try {
365
365
  const mappings = Array.from(this.mappings.values());
366
366
  await this.storageManager.setJSON(this.config.storagePrefix, mappings);
367
- } catch (error) {
368
- logger.log('error', `Failed to save VLAN mappings to storage: ${error.message}`);
367
+ } catch (error: unknown) {
368
+ logger.log('error', `Failed to save VLAN mappings to storage: ${(error as Error).message}`);
369
369
  }
370
370
  }
371
371
  }
package/ts/readme.md CHANGED
@@ -136,7 +136,7 @@ Manages the Rust-based RemoteIngressHub lifecycle. Syncs allowed edges, tracks c
136
136
 
137
137
  ## License and Legal Information
138
138
 
139
- This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](../LICENSE) file.
139
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](../license) file.
140
140
 
141
141
  **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
142
142
 
@@ -60,7 +60,7 @@ export enum ThreatCategory {
60
60
  * Content Scanner for detecting malicious email content
61
61
  */
62
62
  export class ContentScanner {
63
- private static instance: ContentScanner;
63
+ private static instance: ContentScanner | undefined;
64
64
  private scanCache: LRUCache<string, IScanResult>;
65
65
  private options: Required<IContentScannerOptions>;
66
66
 
@@ -258,12 +258,12 @@ export class ContentScanner {
258
258
  }
259
259
 
260
260
  return result;
261
- } catch (error) {
262
- logger.log('error', `Error scanning email: ${error.message}`, {
261
+ } catch (error: unknown) {
262
+ logger.log('error', `Error scanning email: ${(error as Error).message}`, {
263
263
  messageId: email.getMessageId(),
264
- error: error.stack
264
+ error: (error as Error).stack
265
265
  });
266
-
266
+
267
267
  // Return a safe default with error indication
268
268
  return {
269
269
  isClean: true, // Let it pass if scanner fails (configure as desired)
@@ -271,7 +271,7 @@ export class ContentScanner {
271
271
  scannedElements: ['error'],
272
272
  timestamp: Date.now(),
273
273
  threatType: 'scan_error',
274
- threatDetails: `Scan error: ${error.message}`
274
+ threatDetails: `Scan error: ${(error as Error).message}`
275
275
  };
276
276
  }
277
277
  }
@@ -625,8 +625,8 @@ export class ContentScanner {
625
625
  return sample.toString('utf8')
626
626
  .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, '') // Remove control chars
627
627
  .replace(/\uFFFD/g, ''); // Remove replacement char
628
- } catch (error) {
629
- logger.log('warn', `Error extracting text from buffer: ${error.message}`);
628
+ } catch (error: unknown) {
629
+ logger.log('warn', `Error extracting text from buffer: ${(error as Error).message}`);
630
630
  return '';
631
631
  }
632
632
  }
@@ -699,10 +699,10 @@ export class ContentScanner {
699
699
  subject: email.subject
700
700
  },
701
701
  success: false,
702
- domain: email.getFromDomain()
702
+ domain: email.getFromDomain() ?? undefined
703
703
  });
704
704
  }
705
-
705
+
706
706
  /**
707
707
  * Log a threat finding to the security logger
708
708
  * @param email The email containing the threat
@@ -722,10 +722,10 @@ export class ContentScanner {
722
722
  subject: email.subject
723
723
  },
724
724
  success: false,
725
- domain: email.getFromDomain()
725
+ domain: email.getFromDomain() ?? undefined
726
726
  });
727
727
  }
728
-
728
+
729
729
  /**
730
730
  * Get threat level description based on score
731
731
  * @param score Threat score
@@ -61,7 +61,7 @@ export interface IIPReputationOptions {
61
61
  * Class for checking IP reputation of inbound email senders
62
62
  */
63
63
  export class IPReputationChecker {
64
- private static instance: IPReputationChecker;
64
+ private static instance: IPReputationChecker | undefined;
65
65
  private reputationCache: LRUCache<string, IReputationResult>;
66
66
  private options: Required<IIPReputationOptions>;
67
67
  private storageManager?: any; // StorageManager instance
@@ -127,8 +127,8 @@ export class IPReputationChecker {
127
127
  // Load cache from disk if enabled
128
128
  if (this.options.enableLocalCache) {
129
129
  // Fire and forget the load operation
130
- this.loadCache().catch(error => {
131
- logger.log('error', `Failed to load IP reputation cache during initialization: ${error.message}`);
130
+ this.loadCache().catch((error: unknown) => {
131
+ logger.log('error', `Failed to load IP reputation cache during initialization: ${(error as Error).message}`);
132
132
  });
133
133
  }
134
134
  }
@@ -237,13 +237,13 @@ export class IPReputationChecker {
237
237
  this.logReputationCheck(ip, result);
238
238
 
239
239
  return result;
240
- } catch (error) {
241
- logger.log('error', `Error checking IP reputation for ${ip}: ${error.message}`, {
240
+ } catch (error: unknown) {
241
+ logger.log('error', `Error checking IP reputation for ${ip}: ${(error as Error).message}`, {
242
242
  ip,
243
- stack: error.stack
243
+ stack: (error as Error).stack
244
244
  });
245
-
246
- return this.createErrorResult(ip, error.message);
245
+
246
+ return this.createErrorResult(ip, (error as Error).message);
247
247
  }
248
248
  }
249
249
 
@@ -266,8 +266,8 @@ export class IPReputationChecker {
266
266
  const lookupDomain = `${reversedIP}.${server}`;
267
267
  await plugins.dns.promises.resolve(lookupDomain);
268
268
  return server; // IP is listed in this DNSBL
269
- } catch (error) {
270
- if (error.code === 'ENOTFOUND') {
269
+ } catch (error: unknown) {
270
+ if ((error as any).code === 'ENOTFOUND') {
271
271
  return null; // IP is not listed in this DNSBL
272
272
  }
273
273
  throw error; // Other error
@@ -286,8 +286,8 @@ export class IPReputationChecker {
286
286
  listCount: lists.length,
287
287
  lists
288
288
  };
289
- } catch (error) {
290
- logger.log('error', `Error checking DNSBL for ${ip}: ${error.message}`);
289
+ } catch (error: unknown) {
290
+ logger.log('error', `Error checking DNSBL for ${ip}: ${(error as Error).message}`);
291
291
  return {
292
292
  listCount: 0,
293
293
  lists: []
@@ -349,8 +349,8 @@ export class IPReputationChecker {
349
349
  org: this.determineOrg(ip), // Simplified, would use real org data
350
350
  type
351
351
  };
352
- } catch (error) {
353
- logger.log('error', `Error getting IP info for ${ip}: ${error.message}`);
352
+ } catch (error: unknown) {
353
+ logger.log('error', `Error getting IP info for ${ip}: ${(error as Error).message}`);
354
354
  return {
355
355
  type: IPType.UNKNOWN
356
356
  };
@@ -468,8 +468,8 @@ export class IPReputationChecker {
468
468
  }
469
469
  this.saveCacheTimer = setTimeout(() => {
470
470
  this.saveCacheTimer = null;
471
- this.saveCache().catch(error => {
472
- logger.log('error', `Failed to save IP reputation cache: ${error.message}`);
471
+ this.saveCache().catch((error: unknown) => {
472
+ logger.log('error', `Failed to save IP reputation cache: ${(error as Error).message}`);
473
473
  });
474
474
  }, IPReputationChecker.SAVE_CACHE_DEBOUNCE_MS);
475
475
  }
@@ -506,11 +506,11 @@ export class IPReputationChecker {
506
506
 
507
507
  logger.log('info', `Saved ${entries.length} IP reputation cache entries to disk`);
508
508
  }
509
- } catch (error) {
510
- logger.log('error', `Failed to save IP reputation cache: ${error.message}`);
509
+ } catch (error: unknown) {
510
+ logger.log('error', `Failed to save IP reputation cache: ${(error as Error).message}`);
511
511
  }
512
512
  }
513
-
513
+
514
514
  /**
515
515
  * Load cache from disk or storage manager
516
516
  */
@@ -542,12 +542,12 @@ export class IPReputationChecker {
542
542
  plugins.fs.unlinkSync(cacheFile);
543
543
  logger.log('info', 'Old cache file removed after migration');
544
544
  } catch (deleteError) {
545
- logger.log('warn', `Could not delete old cache file: ${deleteError.message}`);
545
+ logger.log('warn', `Could not delete old cache file: ${(deleteError as Error).message}`);
546
546
  }
547
547
  }
548
548
  }
549
- } catch (error) {
550
- logger.log('error', `Error loading from StorageManager: ${error.message}`);
549
+ } catch (error: unknown) {
550
+ logger.log('error', `Error loading from StorageManager: ${(error as Error).message}`);
551
551
  }
552
552
  } else {
553
553
  // No storage manager, load from filesystem
@@ -578,8 +578,8 @@ export class IPReputationChecker {
578
578
  const source = fromFilesystem ? 'disk' : 'StorageManager';
579
579
  logger.log('info', `Loaded ${validEntries.length} IP reputation cache entries from ${source}`);
580
580
  }
581
- } catch (error) {
582
- logger.log('error', `Failed to load IP reputation cache: ${error.message}`);
581
+ } catch (error: unknown) {
582
+ logger.log('error', `Failed to load IP reputation cache: ${(error as Error).message}`);
583
583
  }
584
584
  }
585
585
 
@@ -611,8 +611,8 @@ export class IPReputationChecker {
611
611
 
612
612
  // If cache is enabled and we have entries, save them to the new storage manager
613
613
  if (this.options.enableLocalCache && this.reputationCache.size > 0) {
614
- this.saveCache().catch(error => {
615
- logger.log('error', `Failed to save cache to new storage manager: ${error.message}`);
614
+ this.saveCache().catch((error: unknown) => {
615
+ logger.log('error', `Failed to save cache to new storage manager: ${(error as Error).message}`);
616
616
  });
617
617
  }
618
618
  }
@@ -58,7 +58,7 @@ export interface ISecurityEvent {
58
58
  * Security logger for enhanced security monitoring
59
59
  */
60
60
  export class SecurityLogger {
61
- private static instance: SecurityLogger;
61
+ private static instance: SecurityLogger | undefined;
62
62
  private securityEvents: ISecurityEvent[] = [];
63
63
  private maxEventHistory: number;
64
64
  private enableNotifications: boolean;
@@ -154,11 +154,13 @@ export class SecurityLogger {
154
154
  }
155
155
 
156
156
  if (filter.fromTimestamp) {
157
- filteredEvents = filteredEvents.filter(event => event.timestamp >= filter.fromTimestamp);
157
+ const fromTs = filter.fromTimestamp;
158
+ filteredEvents = filteredEvents.filter(event => event.timestamp >= fromTs);
158
159
  }
159
-
160
+
160
161
  if (filter.toTimestamp) {
161
- filteredEvents = filteredEvents.filter(event => event.timestamp <= filter.toTimestamp);
162
+ const toTs = filter.toTimestamp;
163
+ filteredEvents = filteredEvents.filter(event => event.timestamp <= toTs);
162
164
  }
163
165
  }
164
166
 
@@ -7,7 +7,7 @@ import { smsConfigSchema } from './config/sms.schema.js';
7
7
  import { ConfigValidator } from '../config/validator.js';
8
8
 
9
9
  export class SmsService {
10
- public projectinfo: plugins.projectinfo.ProjectInfo;
10
+ public projectinfo!: plugins.projectinfo.ProjectInfo;
11
11
  public typedrouter = new plugins.typedrequest.TypedRouter();
12
12
  public config: ISmsConfig;
13
13
 
@@ -16,7 +16,7 @@ export class SmsService {
16
16
  const validationResult = ConfigValidator.validate(options, smsConfigSchema);
17
17
 
18
18
  if (!validationResult.valid) {
19
- logger.warn(`SMS service configuration has validation errors: ${validationResult.errors.join(', ')}`);
19
+ logger.warn(`SMS service configuration has validation errors: ${validationResult.errors!.join(', ')}`);
20
20
  }
21
21
 
22
22
  // Set configuration with defaults
@@ -30,7 +30,7 @@ export class SmsService {
30
30
  */
31
31
  public async start() {
32
32
  logger.log('info', `starting sms service`);
33
- this.projectinfo = new plugins.projectinfo.ProjectInfo(paths.packageDir);
33
+ this.projectinfo = await plugins.projectinfo.ProjectInfo.create(paths.packageDir);
34
34
  this.typedrouter.addTypedHandler(
35
35
  new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.platformservice.sms.IRequest_SendSms>(
36
36
  'sendSms',
@@ -15,7 +15,7 @@ export interface IStorageConfig {
15
15
  /** Filesystem path for storage */
16
16
  fsPath?: string;
17
17
  /** Custom read function */
18
- readFunction?: (key: string) => Promise<string>;
18
+ readFunction?: (key: string) => Promise<string | null>;
19
19
  /** Custom write function */
20
20
  writeFunction?: (key: string, value: string) => Promise<void>;
21
21
  }
@@ -57,9 +57,7 @@ export class StorageManager {
57
57
  this.ensureDirectory(this.fsBasePath);
58
58
 
59
59
  // Set up internal filesystem read/write functions
60
- this.config.readFunction = async (key: string) => {
61
- return this.fsRead(key);
62
- };
60
+ this.config.readFunction = (key: string): Promise<string | null> => this.fsRead(key);
63
61
  this.config.writeFunction = async (key: string, value: string) => {
64
62
  await this.fsWrite(key, value);
65
63
  };
@@ -88,8 +86,8 @@ export class StorageManager {
88
86
  private async ensureDirectory(dirPath: string): Promise<void> {
89
87
  try {
90
88
  await plugins.fsUtils.ensureDir(dirPath);
91
- } catch (error) {
92
- logger.log('error', `Failed to create storage directory: ${error.message}`);
89
+ } catch (error: unknown) {
90
+ logger.log('error', `Failed to create storage directory: ${(error as Error).message}`);
93
91
  throw error;
94
92
  }
95
93
  }
@@ -129,19 +127,19 @@ export class StorageManager {
129
127
  /**
130
128
  * Internal filesystem read function
131
129
  */
132
- private async fsRead(key: string): Promise<string> {
130
+ private async fsRead(key: string): Promise<string | null> {
133
131
  const filePath = this.keyToPath(key);
134
132
  try {
135
133
  const content = await readFile(filePath, 'utf8');
136
134
  return content;
137
- } catch (error) {
138
- if (error.code === 'ENOENT') {
135
+ } catch (error: unknown) {
136
+ if ((error as any).code === 'ENOENT') {
139
137
  return null;
140
138
  }
141
139
  throw error;
142
140
  }
143
141
  }
144
-
142
+
145
143
  /**
146
144
  * Internal filesystem write function
147
145
  */
@@ -186,8 +184,8 @@ export class StorageManager {
186
184
  default:
187
185
  throw new Error(`Unknown backend: ${this.backend}`);
188
186
  }
189
- } catch (error) {
190
- logger.log('error', `Storage get error for key ${key}: ${error.message}`);
187
+ } catch (error: unknown) {
188
+ logger.log('error', `Storage get error for key ${key}: ${(error as Error).message}`);
191
189
  throw error;
192
190
  }
193
191
  }
@@ -230,7 +228,7 @@ export class StorageManager {
230
228
  this.memoryStore.set(key, value);
231
229
  // Evict oldest entries if memory store exceeds limit
232
230
  while (this.memoryStore.size > StorageManager.MAX_MEMORY_ENTRIES) {
233
- const firstKey = this.memoryStore.keys().next().value;
231
+ const firstKey = this.memoryStore.keys().next().value!;
234
232
  this.memoryStore.delete(firstKey);
235
233
  }
236
234
  break;
@@ -239,8 +237,8 @@ export class StorageManager {
239
237
  default:
240
238
  throw new Error(`Unknown backend: ${this.backend}`);
241
239
  }
242
- } catch (error) {
243
- logger.log('error', `Storage set error for key ${key}: ${error.message}`);
240
+ } catch (error: unknown) {
241
+ logger.log('error', `Storage set error for key ${key}: ${(error as Error).message}`);
244
242
  throw error;
245
243
  }
246
244
  }
@@ -257,8 +255,8 @@ export class StorageManager {
257
255
  const filePath = this.keyToPath(key);
258
256
  try {
259
257
  await unlink(filePath);
260
- } catch (error) {
261
- if (error.code !== 'ENOENT') {
258
+ } catch (error: unknown) {
259
+ if ((error as any).code !== 'ENOENT') {
262
260
  throw error;
263
261
  }
264
262
  }
@@ -281,8 +279,8 @@ export class StorageManager {
281
279
  default:
282
280
  throw new Error(`Unknown backend: ${this.backend}`);
283
281
  }
284
- } catch (error) {
285
- logger.log('error', `Storage delete error for key ${key}: ${error.message}`);
282
+ } catch (error: unknown) {
283
+ logger.log('error', `Storage delete error for key ${key}: ${(error as Error).message}`);
286
284
  throw error;
287
285
  }
288
286
  }
@@ -319,8 +317,8 @@ export class StorageManager {
319
317
  }
320
318
  }
321
319
  }
322
- } catch (error) {
323
- if (error.code !== 'ENOENT') {
320
+ } catch (error: unknown) {
321
+ if ((error as any).code !== 'ENOENT') {
324
322
  throw error;
325
323
  }
326
324
  }
@@ -348,8 +346,8 @@ export class StorageManager {
348
346
  default:
349
347
  throw new Error(`Unknown backend: ${this.backend}`);
350
348
  }
351
- } catch (error) {
352
- logger.log('error', `Storage list error for prefix ${prefix}: ${error.message}`);
349
+ } catch (error: unknown) {
350
+ logger.log('error', `Storage list error for prefix ${prefix}: ${(error as Error).message}`);
353
351
  throw error;
354
352
  }
355
353
  }
@@ -390,8 +388,8 @@ export class StorageManager {
390
388
 
391
389
  try {
392
390
  return JSON.parse(value) as T;
393
- } catch (error) {
394
- logger.log('error', `Failed to parse JSON for key ${key}: ${error.message}`);
391
+ } catch (error: unknown) {
392
+ logger.log('error', `Failed to parse JSON for key ${key}: ${(error as Error).message}`);
395
393
  throw error;
396
394
  }
397
395
  }
@@ -259,7 +259,7 @@ Resource classes (`Route`, `Certificate`, `ApiToken`, `RemoteIngress`, `Email`)
259
259
 
260
260
  ## License and Legal Information
261
261
 
262
- This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](../LICENSE) file.
262
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](../license) file.
263
263
 
264
264
  **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
265
265
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '11.10.3',
6
+ version: '11.10.7',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }