@serve.zone/dcrouter 17.1.5 → 17.1.6

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 (32) hide show
  1. package/deno.json +1 -1
  2. package/dist_serve/bundle.js +559 -559
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/classes.dcrouter.js +2 -2
  5. package/dist_ts/dns/manager.dns.js +23 -6
  6. package/dist_ts/email/classes.mail-dns-sync.d.ts +18 -0
  7. package/dist_ts/email/classes.mail-dns-sync.js +101 -2
  8. package/dist_ts/monitoring/classes.metricscache.d.ts +2 -0
  9. package/dist_ts/monitoring/classes.metricscache.js +28 -6
  10. package/dist_ts/monitoring/classes.metricsmanager.d.ts +10 -0
  11. package/dist_ts/monitoring/classes.metricsmanager.js +99 -31
  12. package/dist_ts/opsserver/handlers/security.handler.js +24 -6
  13. package/dist_ts/opsserver/handlers/stats.handler.js +2 -3
  14. package/dist_ts/remoteingress/classes.hub-lifecycle.js +2 -2
  15. package/dist_ts_interfaces/requests/stats.d.ts +7 -0
  16. package/dist_ts_migrations/index.js +277 -152
  17. package/dist_ts_web/00_commitinfo_data.js +1 -1
  18. package/dist_ts_web/appstate/network.js +11 -2
  19. package/dist_ts_web/appstate/ui.js +1 -8
  20. package/package.json +2 -2
  21. package/ts/00_commitinfo_data.ts +1 -1
  22. package/ts/classes.dcrouter.ts +3 -1
  23. package/ts/dns/manager.dns.ts +22 -5
  24. package/ts/email/classes.mail-dns-sync.ts +105 -1
  25. package/ts/monitoring/classes.metricscache.ts +36 -8
  26. package/ts/monitoring/classes.metricsmanager.ts +113 -32
  27. package/ts/opsserver/handlers/security.handler.ts +35 -6
  28. package/ts/opsserver/handlers/stats.handler.ts +1 -2
  29. package/ts/remoteingress/classes.hub-lifecycle.ts +3 -1
  30. package/ts_web/00_commitinfo_data.ts +1 -1
  31. package/ts_web/appstate/network.ts +12 -1
  32. package/ts_web/appstate/ui.ts +0 -9
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '17.1.5',
6
+ version: '17.1.6',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsc0JBQXNCO0lBQzVCLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLFdBQVcsRUFBRSwwRUFBMEU7Q0FDeEYsQ0FBQSJ9
@@ -3,6 +3,8 @@ import * as interfaces from '../../dist_ts_interfaces/index.js';
3
3
  import { appState } from './shared.js';
4
4
  import { getActionContext } from './login.js';
5
5
  import { runBackgroundRefresh } from './shared.js';
6
+ const IP_INTELLIGENCE_REFRESH_INTERVAL_MS = 60_000;
7
+ let lastIpIntelligenceRefreshAt = 0;
6
8
  export const networkStatePart = await appState.getStatePart('network', {
7
9
  connections: [],
8
10
  connectionsByIP: {},
@@ -25,9 +27,16 @@ export const networkStatePart = await appState.getStatePart('network', {
25
27
  error: null,
26
28
  }, 'soft');
27
29
  export function refreshNetworkIpIntelligence(identity, ipAddresses) {
28
- const ips = [...new Set(ipAddresses.filter(Boolean))].slice(0, 100);
30
+ const ips = [...new Set(ipAddresses.map((ip) => ip.trim()).filter(Boolean))]
31
+ .sort()
32
+ .slice(0, 100);
29
33
  if (ips.length === 0)
30
34
  return;
35
+ const now = Date.now();
36
+ if (now - lastIpIntelligenceRefreshAt < IP_INTELLIGENCE_REFRESH_INTERVAL_MS) {
37
+ return;
38
+ }
39
+ lastIpIntelligenceRefreshAt = now;
31
40
  runBackgroundRefresh('networkIpIntelligence', 'IP intelligence refresh failed:', async () => {
32
41
  const intelligenceRequest = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'listIpIntelligence');
33
42
  const intelligenceResponse = await intelligenceRequest.fire({
@@ -119,4 +128,4 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
119
128
  }
120
129
  });
121
130
  // ============================================================================
122
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9hcHBzdGF0ZS9uZXR3b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sOEJBQThCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBd0JuRCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLFFBQVEsQ0FBQyxZQUFZLENBQ3pELFNBQVMsRUFDVDtJQUNFLFdBQVcsRUFBRSxFQUFFO0lBQ2YsZUFBZSxFQUFFLEVBQUU7SUFDbkIsY0FBYyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLENBQUMsRUFBRTtJQUM3RCxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUU7SUFDN0IsTUFBTSxFQUFFLEVBQUU7SUFDVixpQkFBaUIsRUFBRSxFQUFFO0lBQ3JCLE9BQU8sRUFBRSxFQUFFO0lBQ1gsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixpQkFBaUIsRUFBRSxDQUFDO0lBQ3BCLGFBQWEsRUFBRSxDQUFDO0lBQ2hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osaUJBQWlCLEVBQUUsSUFBSTtJQUN2QixnQkFBZ0IsRUFBRSxJQUFJO0lBQ3RCLFdBQVcsRUFBRSxDQUFDO0lBQ2QsU0FBUyxFQUFFLEtBQUs7SUFDaEIsS0FBSyxFQUFFLElBQUk7Q0FDWixFQUNELE1BQU0sQ0FDUCxD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
131
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9hcHBzdGF0ZS9uZXR3b3JrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sOEJBQThCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRW5ELE1BQU0sbUNBQW1DLEdBQUcsTUFBTSxDQUFDO0FBQ25ELElBQUksMkJBQTJCLEdBQUcsQ0FBQyxDQUFDO0FBd0JwQyxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLFFBQVEsQ0FBQyxZQUFZLENBQ3pELFNBQVMsRUFDVDtJQUNFLFdBQVcsRUFBRSxFQUFFO0lBQ2YsZUFBZSxFQUFFLEVBQUU7SUFDbkIsY0FBYyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLENBQUMsRUFBRTtJQUM3RCxVQUFVLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUU7SUFDN0IsTUFBTSxFQUFFLEVBQUU7SUFDVixpQkFBaUIsRUFBRSxFQUFFO0lBQ3JCLE9BQU8sRUFBRSxFQUFFO0lBQ1gsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsY0FBYyxFQUFFLEVBQUU7SUFDbEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixpQkFBaUIsRUFBRSxDQUFDO0lBQ3BCLGFBQWEsRUFBRSxDQUFDO0lBQ2hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osaUJBQWlCLEVBQUUsSUFBSTtJQUN2QixnQkFBZ0IsRUFBRSxJQUFJO0lBQ3RCLFdBQVcsRUFBRSxD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
@@ -1,5 +1,4 @@
1
1
  import { appState } from './shared.js';
2
- import { networkStatePart, fetchNetworkStatsAction } from './network.js';
3
2
  import { certificateStatePart, fetchCertificateOverviewAction } from './certificates.js';
4
3
  // Determine initial view from URL path
5
4
  const getInitialView = () => {
@@ -34,12 +33,6 @@ export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePart
34
33
  // Set Active View Action
35
34
  export const setActiveViewAction = uiStatePart.createAction(async (statePartArg, viewName) => {
36
35
  const currentState = statePartArg.getState();
37
- // If switching to network view, ensure we fetch network data
38
- if (viewName === 'network' && currentState.activeView !== 'network') {
39
- setTimeout(() => {
40
- networkStatePart.dispatchAction(fetchNetworkStatsAction, null);
41
- }, 100);
42
- }
43
36
  // If switching to the Domains group, ensure we fetch certificate data
44
37
  // (Certificates is a subview of Domains).
45
38
  if (viewName === 'domains' && currentState.activeView !== 'domains') {
@@ -52,4 +45,4 @@ export const setActiveViewAction = uiStatePart.createAction(async (statePartArg,
52
45
  activeView: viewName,
53
46
  };
54
47
  });
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvYXBwc3RhdGUvdWkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLDhCQUE4QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFXekYsdUNBQXVDO0FBQ3ZDLE1BQU0sY0FBYyxHQUFHLEdBQVcsRUFBRTtJQUNsQyxNQUFNLElBQUksR0FBRyxPQUFPLE1BQU0sS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDNUUsTUFBTSxVQUFVLEdBQUcsQ0FBQyxVQUFVLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM3RixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekIsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQztBQUN2RCxDQUFDLENBQUM7QUFFRiwrREFBK0Q7QUFDL0QsTUFBTSxpQkFBaUIsR0FBRyxHQUFrQixFQUFFO0lBQzVDLE1BQU0sSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM1RSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUM7QUFDN0IsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLFlBQVksQ0FDcEQsSUFBSSxFQUNKO0lBQ0UsVUFBVSxFQUFFLGNBQWMsRUFBRTtJQUM1QixhQUFhLEVBQUUsaUJBQWlCLEVBQUU7SUFDbEMsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixXQUFXLEVBQUUsSUFBSTtJQUNqQixlQUFlLEVBQUUsSUFBSSxFQUFFLFdBQVc7SUFDbEMsS0FBSyxFQUFFLE9BQU87Q0FDZixDQUNGLENBQUM7QUFFRiw2QkFBNkI7QUFDN0IsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsV0FBVyxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFxQixFQUFFO0lBQ3hHLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUcsQ0FBQztJQUM5QyxPQUFPO1FBQ0wsR0FBRyxZQUFZO1FBQ2YsV0FBVyxFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVc7S0FDdkMsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDO0FBRUgseUJBQXlCO0FBQ3pCLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQVMsS0FBSyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQXFCLEVBQUU7SUFDdEgsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBRTlDLDZEQUE2RDtJQUM3RCxJQUFJLFFBQVEsS0FBSyxTQUFTLElBQUksWUFBWSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNwRSxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsZ0JBQWdCLENBQUMsY0FBYyxDQUFDLHVCQUF1QixFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNWLENBQUM7SUFFRCxzRUFBc0U7SUFDdEUsMENBQTBDO0lBQzFDLElBQUksUUFBUSxLQUFLLFNBQVMsSUFBSSxZQUFZLENBQUMsVUFBVSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3BFLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxvQkFBb0IsQ0FBQyxjQUFjLENBQUMsOEJBQThCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsQ0FBQztJQUVELE9BQU87UUFDTCxHQUFHLFlBQVk7UUFDZixVQUFVLEVBQUUsUUFBUTtLQUNyQixDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQUMifQ==
48
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvYXBwc3RhdGUvdWkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQVd6Rix1Q0FBdUM7QUFDdkMsTUFBTSxjQUFjLEdBQUcsR0FBVyxFQUFFO0lBQ2xDLE1BQU0sSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUM1RSxNQUFNLFVBQVUsR0FBRyxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzdGLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0FBQ3ZELENBQUMsQ0FBQztBQUVGLCtEQUErRDtBQUMvRCxNQUFNLGlCQUFpQixHQUFHLEdBQWtCLEVBQUU7SUFDNUMsTUFBTSxJQUFJLEdBQUcsT0FBTyxNQUFNLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQzVFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELE9BQU8sUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztBQUM3QixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsWUFBWSxDQUNwRCxJQUFJLEVBQ0o7SUFDRSxVQUFVLEVBQUUsY0FBYyxFQUFFO0lBQzVCLGFBQWEsRUFBRSxpQkFBaUIsRUFBRTtJQUNsQyxnQkFBZ0IsRUFBRSxLQUFLO0lBQ3ZCLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLGVBQWUsRUFBRSxJQUFJLEVBQUUsV0FBVztJQUNsQyxLQUFLLEVBQUUsT0FBTztDQUNmLENBQ0YsQ0FBQztBQUVGLDZCQUE2QjtBQUM3QixNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxXQUFXLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQXFCLEVBQUU7SUFDeEcsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBQzlDLE9BQU87UUFDTCxHQUFHLFlBQVk7UUFDZixXQUFXLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVztLQUN2QyxDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQUM7QUFFSCx5QkFBeUI7QUFDekIsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsV0FBVyxDQUFDLFlBQVksQ0FBUyxLQUFLLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBcUIsRUFBRTtJQUN0SCxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFFOUMsc0VBQXNFO0lBQ3RFLDBDQUEwQztJQUMxQyxJQUFJLFFBQVEsS0FBSyxTQUFTLElBQUksWUFBWSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNwRSxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2Qsb0JBQW9CLENBQUMsY0FBYyxDQUFDLDhCQUE4QixFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzVFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNWLENBQUM7SUFFRCxPQUFPO1FBQ0wsR0FBRyxZQUFZO1FBQ2YsVUFBVSxFQUFFLFFBQVE7S0FDckIsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDIn0=
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@serve.zone/dcrouter",
3
3
  "private": false,
4
- "version": "17.1.5",
4
+ "version": "17.1.6",
5
5
  "description": "A multifaceted routing service handling mail and SMS delivery functions.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -53,7 +53,7 @@
53
53
  "@push.rocks/smartnetwork": "^4.8.0",
54
54
  "@push.rocks/smartpath": "^6.0.0",
55
55
  "@push.rocks/smartpromise": "^4.2.4",
56
- "@push.rocks/smartproxy": "^27.17.6",
56
+ "@push.rocks/smartproxy": "^27.18.0",
57
57
  "@push.rocks/smartradius": "^1.3.0",
58
58
  "@push.rocks/smartrequest": "^5.0.4",
59
59
  "@push.rocks/smartrx": "^3.0.12",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '17.1.5',
6
+ version: '17.1.6',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }
@@ -590,7 +590,9 @@ export class DcRouter {
590
590
  .withStart(async () => {
591
591
  this.remoteIngressManager = new RemoteIngressManager();
592
592
  this.remoteIngressManager.setHubPublicIps([this.options.publicIp]);
593
- this.remoteIngressManager.setOnEdgesChanged((reason) => this.mailDnsSync.requestSync(reason));
593
+ this.remoteIngressManager.setOnEdgesChanged((reason) => (
594
+ this.mailDnsSync.requestEdgeEligibilityCheck(reason)
595
+ ));
594
596
  await this.remoteIngressManager.initialize();
595
597
  })
596
598
  .withStop(async () => {
@@ -690,32 +690,49 @@ export class DnsManager {
690
690
  localByProviderId.set(providerId, record);
691
691
  }
692
692
  const remaining = new Set(existing);
693
+ let mirrorChanged = false;
693
694
  for (let index = 0; index < providerRecords.length; index++) {
694
695
  const pr = providerRecords[index];
695
696
  const providerId = providerIds[index];
696
697
  const match = localByProviderId.get(providerId);
697
698
  if (!match) {
698
699
  await this.createSyncedRecord(id, { ...pr, providerRecordId: providerId }, doc.createdBy);
700
+ mirrorChanged = true;
699
701
  continue;
700
702
  }
701
703
  remaining.delete(match);
702
- match.name = pr.name.toLowerCase();
704
+ const providerName = pr.name.toLowerCase();
705
+ const providerProxied = pr.proxied;
706
+ const changed = match.name !== providerName
707
+ || match.type !== pr.type
708
+ || match.value !== pr.value
709
+ || match.ttl !== pr.ttl
710
+ || (match.proxied ?? false) !== (providerProxied ?? false)
711
+ || match.source !== 'synced'
712
+ || match.providerRecordId !== providerId;
713
+ if (!changed) continue;
714
+
715
+ match.name = providerName;
703
716
  match.type = pr.type;
704
717
  match.value = pr.value;
705
718
  match.ttl = pr.ttl;
706
- match.proxied = pr.proxied;
719
+ match.proxied = providerProxied;
707
720
  match.source = 'synced';
708
721
  match.providerRecordId = providerId;
709
722
  match.updatedAt = Date.now();
710
723
  await match.save();
724
+ mirrorChanged = true;
711
725
  }
712
726
  for (const staleMirror of remaining) {
713
727
  if (staleMirror.source !== 'synced' || !staleMirror.providerRecordId?.trim()) continue;
714
728
  await staleMirror.delete();
729
+ mirrorChanged = true;
730
+ }
731
+ if (mirrorChanged) {
732
+ doc.lastSyncedAt = Date.now();
733
+ doc.updatedAt = doc.lastSyncedAt;
734
+ await doc.save();
715
735
  }
716
- doc.lastSyncedAt = Date.now();
717
- doc.updatedAt = doc.lastSyncedAt;
718
- await doc.save();
719
736
  return {
720
737
  success: true,
721
738
  recordCount: providerRecords.length,
@@ -18,6 +18,7 @@ import {
18
18
  MailEdgeEligibility,
19
19
  ReleasedRemoteIngressEgressIdentitySource,
20
20
  type IEligibleMailEdge,
21
+ type IMailEdgeEligibilityResult,
21
22
  } from './classes.mail-edge-eligibility.js';
22
23
  import {
23
24
  evaluateMailTxtIntent,
@@ -33,6 +34,8 @@ export const MAIL_DNS_SYNC_CREATED_BY = 'mail-dns-reconciler';
33
34
  export const MAIL_DNS_MANAGED_BY = 'mail-dns-reconciler';
34
35
  export const MAIL_DNS_RETRY_INTERVAL_MS = 5 * 60_000;
35
36
  export const MAIL_DNS_MAX_RETRY_INTERVAL_MS = 60 * 60_000;
37
+ export const MAIL_DNS_EDGE_ELIGIBILITY_DEBOUNCE_MS = 250;
38
+ export const MAIL_DNS_EDGE_ELIGIBILITY_COOLDOWN_MS = 5_000;
36
39
  export const MAIL_DNS_PUBLIC_RESOLVER_OPTIONS = {
37
40
  strategy: 'prefer-udp' as const,
38
41
  allowDohFallback: true,
@@ -66,6 +69,28 @@ function normalizeHostname(value: string): string {
66
69
  return value.trim().toLowerCase().replace(/\.$/, '');
67
70
  }
68
71
 
72
+ function mailEdgeEligibilitySignature(result: IMailEdgeEligibilityResult): string {
73
+ const edges = result.edges.map((candidate) => {
74
+ const identities = candidate.identities.map((identity) => ({
75
+ family: identity.family,
76
+ address: identity.address,
77
+ heloHostname: normalizeHostname(identity.heloHostname),
78
+ proof: identity.proof,
79
+ }));
80
+ identities.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
81
+ return {
82
+ id: candidate.edge.id,
83
+ hostname: normalizeHostname(candidate.hostname),
84
+ tags: [...(candidate.edge.tags || [])].sort(),
85
+ publicIp: candidate.edge.publicIp || '',
86
+ publicIpV6: candidate.edge.publicIpV6 || '',
87
+ identities,
88
+ };
89
+ });
90
+ edges.sort((left, right) => left.id.localeCompare(right.id));
91
+ return JSON.stringify({ supported: result.supported, edges });
92
+ }
93
+
69
94
  function normalizeMx(value: string): string {
70
95
  const [priority, exchange = ''] = value.trim().split(/\s+/);
71
96
  return `${Number(priority)} ${normalizeHostname(exchange)}`;
@@ -359,6 +384,13 @@ export class MailDnsSync {
359
384
  private forceAll = false;
360
385
  private forcedDomainIds = new Set<string>();
361
386
  private edgeEligibility: MailEdgeEligibility;
387
+ private edgeEligibilitySignature?: string;
388
+ private edgeEligibilityCheckTimer?: ReturnType<typeof setTimeout>;
389
+ private edgeEligibilityCheckPromise?: Promise<void>;
390
+ private pendingEdgeEligibilityReason?: string;
391
+ private lastEdgeEligibilitySyncAt = 0;
392
+ private edgeEligibilityDebounceMs = MAIL_DNS_EDGE_ELIGIBILITY_DEBOUNCE_MS;
393
+ private edgeEligibilityCooldownMs = MAIL_DNS_EDGE_ELIGIBILITY_COOLDOWN_MS;
362
394
 
363
395
  constructor(
364
396
  private dcRouterRef: DcRouter,
@@ -377,12 +409,18 @@ export class MailDnsSync {
377
409
  }
378
410
  this.started = true;
379
411
  this.stopped = false;
412
+ this.edgeEligibilitySignature = undefined;
413
+ this.pendingEdgeEligibilityReason = undefined;
414
+ this.lastEdgeEligibilitySyncAt = 0;
380
415
  this.queueRequest(undefined, true);
381
416
  try {
382
417
  await this.kick('startup');
383
418
  } catch (error: unknown) {
384
419
  if (this.retryTimer) clearTimeout(this.retryTimer);
385
420
  this.retryTimer = undefined;
421
+ if (this.edgeEligibilityCheckTimer) clearTimeout(this.edgeEligibilityCheckTimer);
422
+ this.edgeEligibilityCheckTimer = undefined;
423
+ this.pendingEdgeEligibilityReason = undefined;
386
424
  this.started = false;
387
425
  this.dirty = false;
388
426
  throw error;
@@ -397,6 +435,12 @@ export class MailDnsSync {
397
435
  clearTimeout(this.retryTimer);
398
436
  this.retryTimer = undefined;
399
437
  }
438
+ if (this.edgeEligibilityCheckTimer) {
439
+ clearTimeout(this.edgeEligibilityCheckTimer);
440
+ this.edgeEligibilityCheckTimer = undefined;
441
+ }
442
+ this.pendingEdgeEligibilityReason = undefined;
443
+ await this.edgeEligibilityCheckPromise?.catch(() => undefined);
400
444
  await this.runPromise?.catch(() => undefined);
401
445
  this.verifier.destroy?.();
402
446
  }
@@ -410,6 +454,65 @@ export class MailDnsSync {
410
454
  });
411
455
  }
412
456
 
457
+ /**
458
+ * RemoteIngress topology events are advisory. Resolve the actual mail-edge
459
+ * eligibility snapshot and only reconcile DNS when its semantic shape
460
+ * changes. Volatile heartbeat/observation timestamps never enter the
461
+ * signature.
462
+ */
463
+ public requestEdgeEligibilityCheck(reason: string): void {
464
+ if (this.stopped || !this.started) return;
465
+ this.pendingEdgeEligibilityReason = reason;
466
+ if (this.edgeEligibilityCheckTimer || this.edgeEligibilityCheckPromise) return;
467
+ this.scheduleEdgeEligibilityCheck();
468
+ }
469
+
470
+ private scheduleEdgeEligibilityCheck(): void {
471
+ if (this.stopped || !this.started || !this.pendingEdgeEligibilityReason) return;
472
+ const cooldownRemaining = Math.max(
473
+ 0,
474
+ this.lastEdgeEligibilitySyncAt + this.edgeEligibilityCooldownMs - Date.now(),
475
+ );
476
+ const delay = Math.max(this.edgeEligibilityDebounceMs, cooldownRemaining);
477
+ this.edgeEligibilityCheckTimer = setTimeout(() => {
478
+ this.edgeEligibilityCheckTimer = undefined;
479
+ this.runEdgeEligibilityCheck().catch((error: unknown) => {
480
+ logger.log('error', `MailDnsSync edge eligibility check failed: ${(error as Error).message}`);
481
+ });
482
+ }, delay);
483
+ this.edgeEligibilityCheckTimer.unref?.();
484
+ }
485
+
486
+ private async runEdgeEligibilityCheck(): Promise<void> {
487
+ if (this.edgeEligibilityCheckPromise) return await this.edgeEligibilityCheckPromise;
488
+ const reason = this.pendingEdgeEligibilityReason;
489
+ this.pendingEdgeEligibilityReason = undefined;
490
+ if (!reason || this.stopped || !this.started) return;
491
+
492
+ this.edgeEligibilityCheckPromise = (async () => {
493
+ const result = await this.edgeEligibility.resolveForDomain();
494
+ const nextSignature = mailEdgeEligibilitySignature(result);
495
+ const previousSignature = this.edgeEligibilitySignature;
496
+ this.edgeEligibilitySignature = nextSignature;
497
+ if (
498
+ previousSignature === undefined
499
+ || previousSignature === nextSignature
500
+ || this.stopped
501
+ || !this.started
502
+ ) {
503
+ return;
504
+ }
505
+ this.lastEdgeEligibilitySyncAt = Date.now();
506
+ this.requestSync(reason);
507
+ })().finally(() => {
508
+ this.edgeEligibilityCheckPromise = undefined;
509
+ if (this.pendingEdgeEligibilityReason && !this.stopped && this.started) {
510
+ this.scheduleEdgeEligibilityCheck();
511
+ }
512
+ });
513
+ return await this.edgeEligibilityCheckPromise;
514
+ }
515
+
413
516
  /** Coalescing entry point used by API actions that need the durable outcome. */
414
517
  public async sync(reason: string, domainIds?: string[]): Promise<void> {
415
518
  if (this.stopped) throw new Error('MailDnsSync is stopped');
@@ -502,7 +605,8 @@ export class MailDnsSync {
502
605
  if (docs.length === 0) return;
503
606
 
504
607
  // Refresh the broad operational status independently from per-domain pins.
505
- await this.edgeEligibility.resolveForDomain();
608
+ const broadEligibility = await this.edgeEligibility.resolveForDomain();
609
+ this.edgeEligibilitySignature = mailEdgeEligibilitySignature(broadEligibility);
506
610
  const plans: IPlannedDomain[] = [];
507
611
  const deletingDocs: EmailDomainDoc[] = [];
508
612
  for (const loadedDoc of docs) {
@@ -1,10 +1,12 @@
1
1
  export interface ICacheEntry<T> {
2
2
  data: T;
3
3
  timestamp: number;
4
+ ttl: number;
4
5
  }
5
6
 
6
7
  export class MetricsCache {
7
8
  private cache = new Map<string, ICacheEntry<any>>();
9
+ private inFlight = new Map<string, Promise<any>>();
8
10
  private readonly defaultTTL: number;
9
11
 
10
12
  constructor(defaultTTL: number = 500) {
@@ -19,20 +21,44 @@ export class MetricsCache {
19
21
  const now = Date.now();
20
22
  const actualTTL = ttl ?? this.defaultTTL;
21
23
 
22
- if (cached && (now - cached.timestamp) < actualTTL) {
24
+ if (cached && (now - cached.timestamp) < cached.ttl) {
23
25
  return cached.data;
24
26
  }
27
+
28
+ if (cached) {
29
+ this.cache.delete(key);
30
+ }
31
+
32
+ const pending = this.inFlight.get(key) as Promise<T> | undefined;
33
+ if (pending) {
34
+ return pending;
35
+ }
25
36
 
26
37
  const result = computeFn();
27
38
 
28
39
  // Handle both sync and async compute functions
29
40
  if (result instanceof Promise) {
30
- return result.then(data => {
31
- this.cache.set(key, { data, timestamp: now });
32
- return data;
33
- });
41
+ let inFlightPromise: Promise<T>;
42
+ inFlightPromise = result.then(
43
+ (data) => {
44
+ if (this.inFlight.get(key) === inFlightPromise) {
45
+ this.inFlight.delete(key);
46
+ this.cache.set(key, { data, timestamp: Date.now(), ttl: actualTTL });
47
+ }
48
+ return data;
49
+ },
50
+ (error: unknown) => {
51
+ if (this.inFlight.get(key) === inFlightPromise) {
52
+ this.inFlight.delete(key);
53
+ this.cache.delete(key);
54
+ }
55
+ throw error;
56
+ },
57
+ );
58
+ this.inFlight.set(key, inFlightPromise);
59
+ return inFlightPromise;
34
60
  } else {
35
- this.cache.set(key, { data: result, timestamp: now });
61
+ this.cache.set(key, { data: result, timestamp: now, ttl: actualTTL });
36
62
  return result;
37
63
  }
38
64
  }
@@ -42,6 +68,7 @@ export class MetricsCache {
42
68
  */
43
69
  public invalidate(key: string): void {
44
70
  this.cache.delete(key);
71
+ this.inFlight.delete(key);
45
72
  }
46
73
 
47
74
  /**
@@ -49,6 +76,7 @@ export class MetricsCache {
49
76
  */
50
77
  public clear(): void {
51
78
  this.cache.clear();
79
+ this.inFlight.clear();
52
80
  }
53
81
 
54
82
  /**
@@ -67,9 +95,9 @@ export class MetricsCache {
67
95
  public cleanup(): void {
68
96
  const now = Date.now();
69
97
  for (const [key, entry] of this.cache.entries()) {
70
- if (now - entry.timestamp > this.defaultTTL) {
98
+ if (now - entry.timestamp > entry.ttl) {
71
99
  this.cache.delete(key);
72
100
  }
73
101
  }
74
102
  }
75
- }
103
+ }