@serve.zone/dcrouter 18.6.2 → 18.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +4 -1
- package/dist_ts/dns/manager.dns.d.ts +16 -0
- package/dist_ts/dns/manager.dns.js +192 -39
- package/dist_ts/dns/providers/cloudflare.provider.d.ts +5 -0
- package/dist_ts/dns/providers/cloudflare.provider.js +78 -23
- package/dist_ts/dns/providers/interfaces.d.ts +2 -0
- package/dist_ts/email/classes.email-domain.manager.d.ts +1 -0
- package/dist_ts/email/classes.email-domain.manager.js +36 -8
- package/dist_ts/email/classes.mail-dns-sync.d.ts +8 -0
- package/dist_ts/email/classes.mail-dns-sync.js +239 -55
- package/dist_ts/email/classes.mail-edge-eligibility.js +44 -17
- package/dist_ts/email/classes.mail-egress-coordinator.js +13 -3
- package/dist_ts/email/reconcile-mail-dns-singleton.d.ts +1 -0
- package/dist_ts/email/reconcile-mail-dns-singleton.js +6 -2
- package/dist_ts/opsserver/handlers/dns-provider.handler.js +3 -1
- package/dist_ts/opsserver/handlers/dns-record.handler.js +44 -35
- package/dist_ts/opsserver/handlers/domain.handler.js +13 -2
- package/dist_ts/remoteingress/classes.hub-lifecycle.js +2 -1
- package/dist_ts_interfaces/data/email-domain.d.ts +2 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +3 -3
- package/readme.md +7 -7
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +4 -0
- package/ts/dns/manager.dns.ts +234 -34
- package/ts/dns/providers/cloudflare.provider.ts +93 -26
- package/ts/dns/providers/interfaces.ts +3 -0
- package/ts/email/classes.email-domain.manager.ts +38 -6
- package/ts/email/classes.mail-dns-sync.ts +246 -53
- package/ts/email/classes.mail-edge-eligibility.ts +53 -15
- package/ts/email/classes.mail-egress-coordinator.ts +18 -4
- package/ts/email/reconcile-mail-dns-singleton.ts +8 -1
- package/ts/opsserver/handlers/dns-provider.handler.ts +2 -0
- package/ts/opsserver/handlers/dns-record.handler.ts +58 -49
- package/ts/opsserver/handlers/domain.handler.ts +11 -1
- package/ts/remoteingress/classes.hub-lifecycle.ts +1 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -150,6 +150,7 @@ export class RemoteIngressHubLifecycle {
|
|
|
150
150
|
this.dcRouterRef.tunnelManager = undefined;
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
this.dcRouterRef.mailDnsSync.requestEdgeEligibilityCheck('RemoteIngress hub stopped');
|
|
153
154
|
}
|
|
154
155
|
async restartTunnelHubLocked() {
|
|
155
156
|
const generation = ++this.generation;
|
|
@@ -239,4 +240,4 @@ export class RemoteIngressHubLifecycle {
|
|
|
239
240
|
return tlsConfig;
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5odWItbGlmZWN5Y2xlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcmVtb3RlaW5ncmVzcy9jbGFzc2VzLmh1Yi1saWZlY3ljbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFxQyxNQUFNLG9DQUFvQyxDQUFDO0FBQzdHLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUk1RDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHlCQUF5QjtJQUtoQjtJQUpaLGNBQWMsR0FBa0IsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xELFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDakIsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUV2QixZQUFvQixXQUFxQjtRQUFyQixnQkFBVyxHQUFYLFdBQVcsQ0FBVTtJQUFHLENBQUM7SUFFdEMsS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixDQUFDO1FBQ25FLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQzFCLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsb0JBQW9CLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDO1lBQ3BFLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUN0QixNQUFNLFVBQVUsR0FBRyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUM7UUFFckMsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLHFCQUFxQixFQUFFLDRCQUE0QixFQUFFLENBQUM7UUFDcEcsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsb0JBQW9CLENBQUMsRUFBRSxDQUFDO1lBQ2hFLE9BQU87UUFDVCxDQUFDO1FBQ0Qsb0JBQW9CLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFdkQsZ0ZBQWdGO1FBQ2hGLGdGQUFnRjtRQUNoRiw2Q0FBNkM7UUFDN0Msb0JBQW9CLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsK0JBQStCLEVBQVcsQ0FBQyxDQUFDO1FBRTVGLHdEQUF3RDtRQUN4RCxzRkFBc0Y7UUFDdEYsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDeEMsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzFELENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLENBQUM7WUFDaEUsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDOUIsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLENBQUM7WUFDaEUsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFNBQVMsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFDNUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsc0NBQXNDLFdBQVcsQ0FBQyxVQUFVLFNBQVMsU0FBUyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFILENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDOUIsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQztZQUM1RCxJQUFJLG9CQUFvQixFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2xDLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztvQkFDNUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO2dCQUM3QyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxXQUFXLENBQ3RCLFFBQXVELEVBQ3ZELGdCQUFnQixHQUFHLElBQUk7UUFFdkIsT0FBTyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDckMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUMvQyxDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQztZQUN0RCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1lBQ2xELENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN2QyxJQUFJLGdCQUFnQixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3ZELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMxRCxDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUE4QjtRQUN0RCxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDOUIsSUFBSSxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBQzFCLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMxRCxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUNuQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUQsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxjQUF3RDtRQUN2RixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDOUIsSUFBSSxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBQzFCLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzFFLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ25DLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMxRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLGlCQUFpQixDQUM1QixPQUF3QyxFQUN4QyxTQUFpQjtRQUVqQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixDQUFDO1FBQ3RELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDbEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sY0FBYyxHQUFHLGdCQUFnQixDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsT0FBTyxDQUFDO1FBRXJFLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUM5QixNQUFNLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ25DLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksY0FBYyxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLHlDQUF5QyxFQUFFLENBQUM7UUFDckUsQ0FBQztRQUVELElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3JCLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDOUIsTUFBTSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUN0QyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRU8sbUJBQW1CLENBQUMsVUFBa0IsRUFBRSxPQUE2QjtRQUMzRSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVE7ZUFDaEIsVUFBVSxLQUFLLElBQUksQ0FBQyxVQUFVO2VBQzlCLElBQUksQ0FBQyxXQUFXLENBQUMsb0JBQW9CLEtBQUssT0FBTyxDQUFDO0lBQ3pELENBQUM7SUFFTyxTQUFTLENBQUksSUFBc0I7UUFDekMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNqRSxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxLQUFLLENBQUMsbUJBQW1CO1FBQy9CLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDO1FBQzVELElBQUksb0JBQW9CLEVBQUUsQ0FBQztZQUN6QixNQUFNLG9CQUFvQixDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2xDLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztnQkFDNUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1lBQzdDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxzQkFBc0I7UUFDbEMsTUFBTSxVQUFVLEdBQUcsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ3JDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsb0JBQW9CLEVBQUUsY0FBYyxFQUFFLENBQUM7UUFDNUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsb0JBQW9CLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNyRixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUM7UUFDNUQsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEMsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsS0FBSyxvQkFBb0IsRUFBRSxDQUFDO2dCQUM1RCxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7WUFDN0MsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksVUFBVSxLQUFLLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNwRCxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFTyxLQUFLLENBQUMsb0JBQW9CLENBQUMsVUFBa0I7UUFDbkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQztRQUN0RCxNQUFNLFdBQVcsR0FBRyxPQUFPLEVBQUUsY0FBYyxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxPQUFPLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3pGLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLHFCQUFxQixFQUFFLDRCQUE0QixFQUFFLENBQUM7UUFDcEcsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLFVBQVUsS0FBSyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsb0JBQW9CLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDekcsT0FBTztRQUNULENBQUM7UUFDRCxPQUFPLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFMUMsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JFLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ3pHLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsT0FBTyxFQUFFO1lBQy9DLFVBQVUsRUFBRSxXQUFXLENBQUMsVUFBVTtZQUNsQyxVQUFVLEVBQUUsV0FBVztZQUN2QixHQUFHLEVBQUUsU0FBUztZQUNkLFdBQVcsRUFBRSxPQUFPLENBQUMsdUJBQXVCLEVBQUU7U0FDL0MsQ0FBQyxDQUFDO1FBQ0gsYUFBYSxDQUFDLG9CQUFvQixDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUM3QyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQywyQkFBMkIsQ0FBQyxNQUFNLENBQUMsQ0FDakUsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDO1lBQ0gsTUFBTSxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixNQUFNLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0MsTUFBTSxHQUFHLENBQUM7UUFDWixDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLFVBQVUsS0FBSyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsb0JBQW9CLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDekcsTUFBTSxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ3ZDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGtEQUFtRCxHQUFhLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNqRyxDQUFDLENBQUMsQ0FBQztZQUNILE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO0lBQ2pELENBQUM7SUFFTyxLQUFLLENBQUMsZ0JBQWdCLENBQzVCLFNBQWtCO1FBRWxCLGlHQUFpRztRQUNqRyxJQUFJLFNBQTBELENBQUM7UUFFL0QsMkNBQTJDO1FBQzNDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLG1CQUFtQixFQUFFLEdBQUcsQ0FBQztRQUN0RSxJQUFJLFdBQVcsRUFBRSxRQUFRLElBQUksV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDO1lBQ2xELElBQUksQ0FBQztnQkFDSCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUN0RSxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUNwRSxTQUFTLEdBQUcsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLHNEQUFzRCxDQUFDLENBQUM7WUFDN0UsQ0FBQztZQUFDLE9BQU8sR0FBWSxFQUFFLENBQUM7Z0JBQ3RCLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLG9EQUFxRCxHQUFhLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNuRyxDQUFDO1FBQ0gsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxJQUFJLENBQUMsU0FBUyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQztnQkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFlBQVksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzFELElBQUksTUFBTSxFQUFFLFNBQVMsSUFBSSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUM7b0JBQzVDLFNBQVMsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7b0JBQ3JFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLHdEQUF3RCxTQUFTLEVBQUUsQ0FBQyxDQUFDO2dCQUMxRixDQUFDO1lBQ0gsQ0FBQztZQUFDLE1BQU0sQ0FBQyxDQUFDLGtDQUFrQyxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLG9GQUFvRixDQUFDLENBQUM7UUFDM0csQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7Q0FDRiJ9
|
|
243
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5odWItbGlmZWN5Y2xlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcmVtb3RlaW5ncmVzcy9jbGFzc2VzLmh1Yi1saWZlY3ljbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUFxQyxNQUFNLG9DQUFvQyxDQUFDO0FBQzdHLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUk1RDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHlCQUF5QjtJQUtoQjtJQUpaLGNBQWMsR0FBa0IsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xELFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDakIsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUV2QixZQUFvQixXQUFxQjtRQUFyQixnQkFBVyxHQUFYLFdBQVcsQ0FBVTtJQUFHLENBQUM7SUFFdEMsS0FBSyxDQUFDLEtBQUs7UUFDaEIsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLG9CQUFvQixDQUFDO1FBQ25FLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQzFCLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsb0JBQW9CLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN6QixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDO1lBQ3BFLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztRQUN2RCxJ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
|
|
@@ -86,6 +86,8 @@ export interface IEmailDomainReconciliation {
|
|
|
86
86
|
lastSuccessAt?: string;
|
|
87
87
|
retryAt?: string;
|
|
88
88
|
deletingAt?: string;
|
|
89
|
+
/** Provider record ids whose absence must be confirmed before a deletion tombstone can finalize. */
|
|
90
|
+
deletingProviderRecordIds?: string[];
|
|
89
91
|
}
|
|
90
92
|
/**
|
|
91
93
|
* An email domain managed by dcrouter.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/dcrouter',
|
|
6
|
-
version: '18.
|
|
6
|
+
version: '18.7.0',
|
|
7
7
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsc0JBQXNCO0lBQzVCLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLFdBQVcsRUFBRSwwRUFBMEU7Q0FDeEYsQ0FBQSJ9
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serve.zone/dcrouter",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "18.
|
|
4
|
+
"version": "18.7.0",
|
|
5
5
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@git.zone/tsbundle": "^2.11.3",
|
|
20
20
|
"@git.zone/tsdeno": "^1.7.0",
|
|
21
21
|
"@git.zone/tsdocker": "^3.1.0",
|
|
22
|
-
"@git.zone/tsrun": "^2.0.
|
|
22
|
+
"@git.zone/tsrun": "^2.0.6",
|
|
23
23
|
"@git.zone/tstest": "^3.6.7",
|
|
24
24
|
"@git.zone/tswatch": "^3.3.5",
|
|
25
25
|
"@types/node": "26.1.1",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@api.global/typedrequest-interfaces": "^3.0.19",
|
|
31
31
|
"@api.global/typedserver": "^8.6.4",
|
|
32
32
|
"@api.global/typedsocket": "^5.0.0",
|
|
33
|
-
"@apiclient.xyz/cloudflare": "^
|
|
33
|
+
"@apiclient.xyz/cloudflare": "^8.0.0",
|
|
34
34
|
"@design.estate/dees-catalog": "^3.99.0",
|
|
35
35
|
"@design.estate/dees-element": "^2.4.0",
|
|
36
36
|
"@idp.global/sdk": "^14.3.0",
|
package/readme.md
CHANGED
|
@@ -121,7 +121,7 @@ Bootstrap behavior:
|
|
|
121
121
|
| `baseDir` | Root directory for dcrouter runtime data. Defaults to `~/.serve.zone/dcrouter`. |
|
|
122
122
|
| `coreTrafficConfig` | Main CoreTraffic route configuration for HTTP/HTTPS/TCP/SNI traffic. `smartProxyConfig` remains accepted as a legacy alias. |
|
|
123
123
|
| `emailConfig` | UnifiedEmailServer configuration: hostname, ports, domains, and mail routes. |
|
|
124
|
-
| `emailOutboundMode` | Outbound SMTP mode. Defaults to `
|
|
124
|
+
| `emailOutboundMode` | Outbound SMTP mode. Defaults to `remoteIngress`; explicit `direct` mode lets unmanaged/static senders dial from the hub. |
|
|
125
125
|
| `emailPortConfig` | External-to-internal email port mapping and received-email storage path. |
|
|
126
126
|
| `tls` | Legacy/static TLS and ACME contact settings used to seed certificate config. |
|
|
127
127
|
| `dnsNsDomains` | Nameserver hostnames used for generated NS records and DoH routes. A zone becomes authoritative by having its public NS records observed naming one of these. |
|
|
@@ -495,7 +495,7 @@ from the destination server.
|
|
|
495
495
|
|
|
496
496
|
### RemoteIngress SMTP Egress
|
|
497
497
|
|
|
498
|
-
The email settings API and Ops UI expose `outboundMode`. Keep it at `direct` to let
|
|
498
|
+
The email settings API and Ops UI expose `outboundMode`. Keep it at `direct` to let unmanaged/static senders dial destination MX hosts from the dcrouter hub; managed sender domains are always rejected in direct mode. Set it to `remoteIngress` to make SmartMTA request a one-shot RemoteIngress TCP egress proxy for each outbound SMTP connection while keeping the logical MX host and port for SMTP/TLS identity. Direct mode is explicit operator policy, never an automatic fallback.
|
|
499
499
|
|
|
500
500
|
RemoteIngress edge create/update APIs accept an `egress` policy. Egress is default-disabled and is propagated to the hub only when `egress.enabled === true`.
|
|
501
501
|
|
|
@@ -510,17 +510,17 @@ Supported egress policy fields:
|
|
|
510
510
|
| `deniedCidrs` | CIDRs denied after edge-side DNS resolution. |
|
|
511
511
|
| `maxConcurrentStreams` | Optional concurrent outbound SMTP stream cap for the edge. |
|
|
512
512
|
|
|
513
|
-
RemoteIngress status responses include `capabilities`, `egressEnabled`, and source-bound egress identity. A mail edge is eligible only when it is enabled, carries the `mail` tag, permits destination port `25`, is connected with a fresh heartbeat, uses native QUIC without TCP fallback, advertises both `egressTcpV1` and `egressIdentityV1`, and reports a fresh non-stale `localSocketBind` identity.
|
|
513
|
+
RemoteIngress status responses include `capabilities`, `egressEnabled`, and source-bound egress identity. A mail edge is eligible only when it is enabled, carries the `mail` tag, permits destination port `25`, is connected with a fresh heartbeat, uses native QUIC without TCP fallback, advertises both `egressTcpV1` and `egressIdentityV1`, and reports a fresh non-stale `localSocketBind` identity. Every configured address family must have exactly one matching fresh proof: configuring both `publicIp` and `publicIpV6` requires valid IPv4 and IPv6 identities. Each identity must match the edge's declared address, the edge must have a `mailHostname`, its PTR must resolve exactly to that hostname, and the hostname's A/AAAA set must contain the source address. Domain edge filters narrow this pool and remain fail-closed when they match nothing.
|
|
514
514
|
|
|
515
515
|
RemoteIngress v5 edge runtimes must configure `egressSourceIpv4` and/or `egressSourceIpv6` with concrete addresses assigned to the edge host. The equivalent CLI flags are `--egress-source-ipv4` and `--egress-source-ipv6`; the environment variables are `REMOTEINGRESS_EGRESS_SOURCE_IPV4` and `REMOTEINGRESS_EGRESS_SOURCE_IPV6`. These addresses must match dcrouter's declared edge IPs. Every outbound socket is bound to the matching family, and a missing or unbindable family fails closed. There is no OS-selected address or direct-hub fallback in `remoteIngress` mode.
|
|
516
516
|
|
|
517
|
-
Managed email domains use the durable lifecycle `pending -> active | failed -> deleting`; the document is removed only after deletion cleanup completes. Creation must obtain a usable DKIM key before persistence, then automatically reconciles and validates MX, SPF, DKIM, DMARC, and direct per-edge A/AAAA records. Inbound acceptance is independent and remains available while outbound SMTP credentials and sending are gated until the domain has a validated `activeRevision` and
|
|
517
|
+
Managed email domains use the durable lifecycle `pending -> active | failed -> deleting`; the document is removed only after deletion cleanup completes. Creation must obtain a usable DKIM key before persistence, then automatically reconciles and validates MX, SPF, DKIM, DMARC, and direct per-edge A/AAAA records. Inbound acceptance is independent and remains available while outbound SMTP credentials and sending are gated until the domain has a validated `activeRevision` and both selected MX edges are live.
|
|
518
518
|
|
|
519
|
-
|
|
519
|
+
Managed domains require two eligible edges with distinct hostnames. The reconciler selects stable priority 10 and priority 20 targets and uses that same two-edge set for direct A/AAAA records, public validation, the active revision, and outbound egress. Zero or one eligible edge produces no partial desired MX/SPF set and never falls back to the hub. SPF uses `-all`; steady state authorizes the selected pair, while a make-before-break transition temporarily authorizes both the active and pending pairs until activation triggers immediate contraction. Activation requires the complete MX RRset, all record intents, and exact PTR plus forward-confirmed A/AAAA validation. Topology replacement validates the desired state before activation, then removes stale owned records; an incomplete pinned topology withdraws the previous owned MX/SPF state.
|
|
520
520
|
|
|
521
|
-
The reconciler is globally serialized and coalesces concurrent triggers. It runs at startup, every five minutes, and
|
|
521
|
+
The reconciler is globally serialized and coalesces concurrent triggers. It runs at startup, schedules desired-state checks no more often than every five minutes, and reacts to relevant domain, DNS, DKIM, topology, or egress-identity changes. Failed domains honor persisted `retryAt` state with exponential backoff up to one hour. Provider state is refreshed on each pass; only records marked `managedBy: 'mail-dns-reconciler'` are mutated or deleted. Unmanaged SPF, DMARC, DKIM, or MX conflicts fail visibly instead of being overwritten. Each domain persists desired and active revisions, per-record intent status, provider/validation errors, attempt and validation timestamps, capability state, and `retryAt`. Provider/API failures propagate through the email-domain API and never become false provisioning success. Provider deletion retains local ownership until the provider returns an explicit not-found response or a complete provider-ID listing confirms absence; DNS domain migration/deletion and forced provider deletion are refused while managed email references or reconciler-owned mail records remain.
|
|
522
522
|
|
|
523
|
-
DKIM generation failure is atomic. Automatic rotation defaults to 90 days with a 30-day retiring-selector overlap. dcrouter publishes and validates a staged selector, requires SmartMTA's selector-correct signing capability, promotes it for signing only after the DNS revision validates, retains the previous selector for the overlap, and
|
|
523
|
+
DKIM generation failure is atomic. Automatic rotation defaults to 90 days with a 30-day retiring-selector overlap; `rotationIntervalDays` must be a positive integer. dcrouter publishes and validates a staged selector, requires SmartMTA's selector-correct signing capability, promotes it for signing only after the DNS revision validates, retains the previous selector for the overlap, and schedules retirement at `retireAfter`. Retiring metadata is pruned only after the owned DNS record has been removed successfully.
|
|
524
524
|
|
|
525
525
|
The additive public contracts include `IEmailDomainActionResult`, `IEmailDomain.reconciliation`, lifecycle/error/capability/retry fields, active/pending/retiring DKIM material, DNS intents and revisions, and edge identities. For mutation requests, `success: true` means the operation was accepted and durably recorded; `lifecycleStatus: 'pending'` or `'deleting'` still means activation or cleanup has not completed.
|
|
526
526
|
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -1891,6 +1891,10 @@ export class DcRouter {
|
|
|
1891
1891
|
// final durable authentication-event and email-traffic drain.
|
|
1892
1892
|
await this.stopOpsServer();
|
|
1893
1893
|
|
|
1894
|
+
// Mail DNS reconciliation may legitimately outlive ServiceManager's
|
|
1895
|
+
// non-cancelling per-service timeout. Drain it before dependency teardown.
|
|
1896
|
+
await this.mailDnsSync.stop();
|
|
1897
|
+
|
|
1894
1898
|
// ServiceManager handles reverse-dependency-ordered shutdown
|
|
1895
1899
|
await this.serviceManager.stop();
|
|
1896
1900
|
|
package/ts/dns/manager.dns.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DnsProviderDoc,
|
|
5
5
|
DomainDoc,
|
|
6
6
|
DnsRecordDoc,
|
|
7
|
+
EmailDomainDoc,
|
|
7
8
|
} from '../db/documents/index.js';
|
|
8
9
|
import type { IDcRouterOptions } from '../classes.dcrouter.js';
|
|
9
10
|
import type { IDnsProviderClient, IProviderRecord } from './providers/interfaces.js';
|
|
@@ -41,6 +42,12 @@ export interface IDnsRuntimeRegistration {
|
|
|
41
42
|
origin: TDnsRuntimeRegistrationOrigin;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
export interface IDnsRecordDeleteResult {
|
|
46
|
+
id: string;
|
|
47
|
+
success: boolean;
|
|
48
|
+
message?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
/**
|
|
45
52
|
* DnsManager — owns runtime DNS state on top of the embedded DnsServer.
|
|
46
53
|
*
|
|
@@ -83,11 +90,29 @@ export class DnsManager {
|
|
|
83
90
|
*/
|
|
84
91
|
private runtimeRegistrations = new Map<string, Map<string, IDnsRuntimeRegistration>>();
|
|
85
92
|
|
|
93
|
+
/** Serializes managed-mail reconciliation with destructive domain/provider deletion. */
|
|
94
|
+
private managedMailDnsMutationChain: Promise<void> = Promise.resolve();
|
|
95
|
+
private acceptsManagedMailDnsMutations = true;
|
|
96
|
+
|
|
86
97
|
/** Supplies the effective authority set (bootstrap ∪ delegation-verified). */
|
|
87
98
|
private authorityZonesResolver?: () => string[];
|
|
88
99
|
|
|
89
100
|
constructor(private options: IDcRouterOptions) {}
|
|
90
101
|
|
|
102
|
+
public async runManagedMailDnsMutationExclusive<T>(task: () => Promise<T>): Promise<T> {
|
|
103
|
+
if (!this.acceptsManagedMailDnsMutations) {
|
|
104
|
+
throw new Error('DnsManager is stopping; managed mail DNS mutations are closed');
|
|
105
|
+
}
|
|
106
|
+
const run = this.managedMailDnsMutationChain.then(async () => {
|
|
107
|
+
if (!this.acceptsManagedMailDnsMutations) {
|
|
108
|
+
throw new Error('DnsManager stopped before the managed mail DNS mutation could run');
|
|
109
|
+
}
|
|
110
|
+
return await task();
|
|
111
|
+
});
|
|
112
|
+
this.managedMailDnsMutationChain = run.then(() => undefined, () => undefined);
|
|
113
|
+
return await run;
|
|
114
|
+
}
|
|
115
|
+
|
|
91
116
|
// ==========================================================================
|
|
92
117
|
// Runtime registration registry
|
|
93
118
|
// ==========================================================================
|
|
@@ -161,10 +186,13 @@ export class DnsManager {
|
|
|
161
186
|
// ==========================================================================
|
|
162
187
|
|
|
163
188
|
public async start(): Promise<void> {
|
|
189
|
+
this.acceptsManagedMailDnsMutations = true;
|
|
164
190
|
logger.log('info', 'DnsManager: starting');
|
|
165
191
|
}
|
|
166
192
|
|
|
167
193
|
public async stop(): Promise<void> {
|
|
194
|
+
this.acceptsManagedMailDnsMutations = false;
|
|
195
|
+
await this.managedMailDnsMutationChain;
|
|
168
196
|
this.providerClients.clear();
|
|
169
197
|
this.runtimeRegistrations.clear();
|
|
170
198
|
this.dnsServer = undefined;
|
|
@@ -760,6 +788,15 @@ export class DnsManager {
|
|
|
760
788
|
}
|
|
761
789
|
|
|
762
790
|
public async deleteProvider(id: string, force: boolean): Promise<{ success: boolean; message?: string }> {
|
|
791
|
+
return await this.runManagedMailDnsMutationExclusive(
|
|
792
|
+
async () => await this.deleteProviderUnlocked(id, force),
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
private async deleteProviderUnlocked(
|
|
797
|
+
id: string,
|
|
798
|
+
force: boolean,
|
|
799
|
+
): Promise<{ success: boolean; message?: string }> {
|
|
763
800
|
const doc = await DnsProviderDoc.findById(id);
|
|
764
801
|
if (!doc) return { success: false, message: 'Provider not found' };
|
|
765
802
|
const linkedDomains = await DomainDoc.findByProviderId(id);
|
|
@@ -772,7 +809,16 @@ export class DnsManager {
|
|
|
772
809
|
// If forcing, also delete the linked domains and their records.
|
|
773
810
|
if (force) {
|
|
774
811
|
for (const domain of linkedDomains) {
|
|
775
|
-
await this.
|
|
812
|
+
const references = await this.getManagedMailDnsReferences(domain.id);
|
|
813
|
+
if (references.emailDomains.length > 0 || references.managedRecordCount > 0) {
|
|
814
|
+
return {
|
|
815
|
+
success: false,
|
|
816
|
+
message: this.managedMailDnsReferenceMessage(domain.name, references),
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
for (const domain of linkedDomains) {
|
|
821
|
+
await this.deleteDomainUnlocked(domain.id);
|
|
776
822
|
}
|
|
777
823
|
}
|
|
778
824
|
await doc.delete();
|
|
@@ -950,8 +996,18 @@ export class DnsManager {
|
|
|
950
996
|
* domain's own recorded registrations are removed.
|
|
951
997
|
*/
|
|
952
998
|
public async deleteDomain(id: string): Promise<boolean> {
|
|
999
|
+
return await this.runManagedMailDnsMutationExclusive(
|
|
1000
|
+
async () => await this.deleteDomainUnlocked(id),
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
private async deleteDomainUnlocked(id: string): Promise<boolean> {
|
|
953
1005
|
const doc = await DomainDoc.findById(id);
|
|
954
1006
|
if (!doc) return false;
|
|
1007
|
+
const references = await this.getManagedMailDnsReferences(id);
|
|
1008
|
+
if (references.emailDomains.length > 0 || references.managedRecordCount > 0) {
|
|
1009
|
+
throw new Error(this.managedMailDnsReferenceMessage(doc.name, references));
|
|
1010
|
+
}
|
|
955
1011
|
// Tear runtime state down before the durable rows go away: the registry is
|
|
956
1012
|
// the authority on what to remove, so this does not depend on the records
|
|
957
1013
|
// still being readable.
|
|
@@ -972,6 +1028,28 @@ export class DnsManager {
|
|
|
972
1028
|
return true;
|
|
973
1029
|
}
|
|
974
1030
|
|
|
1031
|
+
private async getManagedMailDnsReferences(domainId: string): Promise<{
|
|
1032
|
+
emailDomains: EmailDomainDoc[];
|
|
1033
|
+
managedRecordCount: number;
|
|
1034
|
+
}> {
|
|
1035
|
+
const emailDomains = (await EmailDomainDoc.findAll()).filter((emailDomain) => (
|
|
1036
|
+
emailDomain.linkedDomainId === domainId
|
|
1037
|
+
|| emailDomain.reconciliation?.providerZoneIds?.includes(domainId)
|
|
1038
|
+
|| emailDomain.reconciliation?.intents.some((intent) => intent.domainId === domainId)
|
|
1039
|
+
));
|
|
1040
|
+
const managedRecordCount = (await DnsRecordDoc.findByDomainId(domainId)).filter((record) => (
|
|
1041
|
+
record.managedBy === 'mail-dns-reconciler'
|
|
1042
|
+
)).length;
|
|
1043
|
+
return { emailDomains, managedRecordCount };
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
private managedMailDnsReferenceMessage(
|
|
1047
|
+
domainName: string,
|
|
1048
|
+
references: { emailDomains: EmailDomainDoc[]; managedRecordCount: number },
|
|
1049
|
+
): string {
|
|
1050
|
+
return `DNS domain ${domainName} is referenced by ${references.emailDomains.length} managed email domain(s) and ${references.managedRecordCount} managed mail DNS record(s); delete those email domains first`;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
975
1053
|
/**
|
|
976
1054
|
* Force-resync a provider-managed domain: re-pull all records from the
|
|
977
1055
|
* provider API, replacing the cached DnsRecordDocs.
|
|
@@ -992,8 +1070,12 @@ export class DnsManager {
|
|
|
992
1070
|
return { success: false, message: 'Provider client unavailable' };
|
|
993
1071
|
}
|
|
994
1072
|
let providerRecords: IProviderRecord[];
|
|
1073
|
+
let allProviderIds: string[];
|
|
995
1074
|
try {
|
|
996
|
-
providerRecords = await
|
|
1075
|
+
[providerRecords, allProviderIds] = await Promise.all([
|
|
1076
|
+
client.listRecords(doc.name),
|
|
1077
|
+
client.listRecordIds(doc.name),
|
|
1078
|
+
]);
|
|
997
1079
|
} catch (error: unknown) {
|
|
998
1080
|
return { success: false, message: `Provider list failed: ${(error as Error).message}` };
|
|
999
1081
|
}
|
|
@@ -1004,6 +1086,17 @@ export class DnsManager {
|
|
|
1004
1086
|
if (new Set(providerIds).size !== providerIds.length) {
|
|
1005
1087
|
return { success: false, message: 'Provider returned duplicate provider record ids' };
|
|
1006
1088
|
}
|
|
1089
|
+
allProviderIds = allProviderIds.map((providerId) => providerId.trim());
|
|
1090
|
+
if (allProviderIds.some((providerId) => !providerId)) {
|
|
1091
|
+
return { success: false, message: 'Provider returned a record without a non-empty provider id' };
|
|
1092
|
+
}
|
|
1093
|
+
if (new Set(allProviderIds).size !== allProviderIds.length) {
|
|
1094
|
+
return { success: false, message: 'Provider returned duplicate provider record ids' };
|
|
1095
|
+
}
|
|
1096
|
+
const allProviderIdSet = new Set(allProviderIds);
|
|
1097
|
+
if (providerIds.some((providerId) => !allProviderIdSet.has(providerId))) {
|
|
1098
|
+
return { success: false, message: 'Provider record listings returned inconsistent record ids' };
|
|
1099
|
+
}
|
|
1007
1100
|
|
|
1008
1101
|
// Provider ids are the only identity proof. Tuple matching could adopt an
|
|
1009
1102
|
// operator replacement and transfer reconciler ownership to the wrong row.
|
|
@@ -1064,7 +1157,7 @@ export class DnsManager {
|
|
|
1064
1157
|
return {
|
|
1065
1158
|
success: true,
|
|
1066
1159
|
recordCount: providerRecords.length,
|
|
1067
|
-
listedProviderRecordIds:
|
|
1160
|
+
listedProviderRecordIds: allProviderIds,
|
|
1068
1161
|
};
|
|
1069
1162
|
}
|
|
1070
1163
|
|
|
@@ -1094,20 +1187,29 @@ export class DnsManager {
|
|
|
1094
1187
|
targetProviderId?: string;
|
|
1095
1188
|
deleteExistingProviderRecords?: boolean;
|
|
1096
1189
|
}): Promise<{ success: boolean; recordsMigrated?: number; message?: string }> {
|
|
1097
|
-
|
|
1098
|
-
|
|
1190
|
+
return await this.runManagedMailDnsMutationExclusive(async () => {
|
|
1191
|
+
const domain = await DomainDoc.findById(args.id);
|
|
1192
|
+
if (!domain) return { success: false, message: 'Domain not found' };
|
|
1099
1193
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1194
|
+
const references = await this.getManagedMailDnsReferences(domain.id);
|
|
1195
|
+
if (references.emailDomains.length > 0 || references.managedRecordCount > 0) {
|
|
1196
|
+
return { success: false, message: this.managedMailDnsReferenceMessage(domain.name, references) };
|
|
1197
|
+
}
|
|
1198
|
+
if (domain.source === args.targetSource && domain.providerId === args.targetProviderId) {
|
|
1199
|
+
return { success: false, message: 'Domain is already in the target configuration' };
|
|
1200
|
+
}
|
|
1105
1201
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1202
|
+
const records = await DnsRecordDoc.findByDomainId(domain.id);
|
|
1203
|
+
if (args.targetSource === 'provider') {
|
|
1204
|
+
return await this.migrateToDnsProvider(
|
|
1205
|
+
domain,
|
|
1206
|
+
records,
|
|
1207
|
+
args.targetProviderId!,
|
|
1208
|
+
args.deleteExistingProviderRecords ?? false,
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
return await this.migrateToDcrouter(domain, records);
|
|
1212
|
+
});
|
|
1111
1213
|
}
|
|
1112
1214
|
|
|
1113
1215
|
/**
|
|
@@ -1345,6 +1447,7 @@ export class DnsManager {
|
|
|
1345
1447
|
public async updateRecord(args: {
|
|
1346
1448
|
id: string;
|
|
1347
1449
|
name?: string;
|
|
1450
|
+
type?: TDnsRecordType;
|
|
1348
1451
|
value?: string;
|
|
1349
1452
|
ttl?: number;
|
|
1350
1453
|
proxied?: boolean;
|
|
@@ -1357,6 +1460,7 @@ export class DnsManager {
|
|
|
1357
1460
|
const previousName = doc.name;
|
|
1358
1461
|
const previousType = doc.type;
|
|
1359
1462
|
if (args.name !== undefined) doc.name = args.name.toLowerCase();
|
|
1463
|
+
if (args.type !== undefined) doc.type = args.type;
|
|
1360
1464
|
if (args.value !== undefined) doc.value = args.value;
|
|
1361
1465
|
if (args.ttl !== undefined) doc.ttl = args.ttl;
|
|
1362
1466
|
if (args.proxied !== undefined) doc.proxied = args.proxied;
|
|
@@ -1384,7 +1488,7 @@ export class DnsManager {
|
|
|
1384
1488
|
await doc.save();
|
|
1385
1489
|
if (domain.source === 'dcrouter') {
|
|
1386
1490
|
await this.refreshLocalRrset(doc.domainId, previousName, previousType);
|
|
1387
|
-
if (previousName.toLowerCase() !== doc.name.toLowerCase()) {
|
|
1491
|
+
if (previousName.toLowerCase() !== doc.name.toLowerCase() || previousType !== doc.type) {
|
|
1388
1492
|
await this.refreshLocalRrset(doc.domainId, doc.name, doc.type);
|
|
1389
1493
|
}
|
|
1390
1494
|
}
|
|
@@ -1392,30 +1496,126 @@ export class DnsManager {
|
|
|
1392
1496
|
}
|
|
1393
1497
|
|
|
1394
1498
|
public async deleteRecord(id: string): Promise<{ success: boolean; message?: string }> {
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1499
|
+
const [result] = await this.deleteRecords([id]);
|
|
1500
|
+
return result.message
|
|
1501
|
+
? { success: result.success, message: result.message }
|
|
1502
|
+
: { success: result.success };
|
|
1503
|
+
}
|
|
1399
1504
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1505
|
+
public async deleteRecords(ids: string[]): Promise<IDnsRecordDeleteResult[]> {
|
|
1506
|
+
const results = new Map<string, IDnsRecordDeleteResult>();
|
|
1507
|
+
const providerGroups = new Map<string, {
|
|
1508
|
+
domain: DomainDoc;
|
|
1509
|
+
client: IDnsProviderClient;
|
|
1510
|
+
records: DnsRecordDoc[];
|
|
1511
|
+
}>();
|
|
1512
|
+
|
|
1513
|
+
for (const id of [...new Set(ids)]) {
|
|
1514
|
+
const doc = await DnsRecordDoc.findById(id);
|
|
1515
|
+
if (!doc) {
|
|
1516
|
+
results.set(id, { id, success: false, message: 'Record not found' });
|
|
1517
|
+
continue;
|
|
1403
1518
|
}
|
|
1404
|
-
const
|
|
1405
|
-
if (!
|
|
1406
|
-
|
|
1519
|
+
const domain = await DomainDoc.findById(doc.domainId);
|
|
1520
|
+
if (!domain) {
|
|
1521
|
+
results.set(id, { id, success: false, message: 'Parent domain not found' });
|
|
1522
|
+
continue;
|
|
1407
1523
|
}
|
|
1408
|
-
|
|
1409
|
-
await
|
|
1410
|
-
|
|
1411
|
-
|
|
1524
|
+
if (domain.source !== 'provider') {
|
|
1525
|
+
await doc.delete();
|
|
1526
|
+
await this.refreshLocalRrset(doc.domainId, doc.name, doc.type);
|
|
1527
|
+
results.set(id, { id, success: true });
|
|
1528
|
+
continue;
|
|
1529
|
+
}
|
|
1530
|
+
if (!domain.providerId || !doc.providerRecordId?.trim()) {
|
|
1531
|
+
results.set(id, { id, success: false, message: 'Provider record metadata missing' });
|
|
1532
|
+
continue;
|
|
1533
|
+
}
|
|
1534
|
+
let group = providerGroups.get(domain.id);
|
|
1535
|
+
if (!group) {
|
|
1536
|
+
const client = await this.getProviderClientById(domain.providerId);
|
|
1537
|
+
if (!client) {
|
|
1538
|
+
results.set(id, { id, success: false, message: 'Provider client unavailable' });
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
group = { domain, client, records: [] };
|
|
1542
|
+
providerGroups.set(domain.id, group);
|
|
1412
1543
|
}
|
|
1544
|
+
group.records.push(doc);
|
|
1413
1545
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1546
|
+
|
|
1547
|
+
for (const { domain, client, records } of providerGroups.values()) {
|
|
1548
|
+
const deleteErrors = new Map<string, Error>();
|
|
1549
|
+
for (const record of records) {
|
|
1550
|
+
try {
|
|
1551
|
+
await client.deleteRecord(domain.name, record.providerRecordId!);
|
|
1552
|
+
} catch (error: unknown) {
|
|
1553
|
+
deleteErrors.set(record.id, error instanceof Error ? error : new Error(String(error)));
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
let providerRecordIds: string[] | undefined;
|
|
1558
|
+
let providerListError: Error | undefined;
|
|
1559
|
+
try {
|
|
1560
|
+
providerRecordIds = (await client.listRecordIds(domain.name)).map((providerRecordId) => (
|
|
1561
|
+
providerRecordId.trim()
|
|
1562
|
+
));
|
|
1563
|
+
} catch (error: unknown) {
|
|
1564
|
+
providerListError = error instanceof Error ? error : new Error(String(error));
|
|
1565
|
+
}
|
|
1566
|
+
const invalidListingMessage = providerRecordIds?.some((providerRecordId) => !providerRecordId)
|
|
1567
|
+
? 'Provider deletion could not be confirmed: provider returned an empty record id'
|
|
1568
|
+
: providerRecordIds && new Set(providerRecordIds).size !== providerRecordIds.length
|
|
1569
|
+
? 'Provider deletion could not be confirmed: provider returned duplicate record ids'
|
|
1570
|
+
: undefined;
|
|
1571
|
+
const listedIds = providerRecordIds && !invalidListingMessage
|
|
1572
|
+
? new Set(providerRecordIds)
|
|
1573
|
+
: undefined;
|
|
1574
|
+
for (const record of records) {
|
|
1575
|
+
const providerRecordId = record.providerRecordId!.trim();
|
|
1576
|
+
const deleteError = deleteErrors.get(record.id);
|
|
1577
|
+
if (deleteError && this.isProviderRecordNotFoundError(deleteError)) {
|
|
1578
|
+
await record.delete();
|
|
1579
|
+
results.set(record.id, { id: record.id, success: true });
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
if (providerListError) {
|
|
1583
|
+
results.set(record.id, {
|
|
1584
|
+
id: record.id,
|
|
1585
|
+
success: false,
|
|
1586
|
+
message: `Provider deletion could not be confirmed: ${providerListError.message}`,
|
|
1587
|
+
});
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1590
|
+
if (invalidListingMessage || !listedIds) {
|
|
1591
|
+
results.set(record.id, {
|
|
1592
|
+
id: record.id,
|
|
1593
|
+
success: false,
|
|
1594
|
+
message: invalidListingMessage || 'Provider deletion could not be confirmed',
|
|
1595
|
+
});
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
if (listedIds.has(providerRecordId)) {
|
|
1599
|
+
results.set(record.id, {
|
|
1600
|
+
id: record.id,
|
|
1601
|
+
success: false,
|
|
1602
|
+
message: deleteError
|
|
1603
|
+
? `Provider rejected delete and still lists the record: ${deleteError.message}`
|
|
1604
|
+
: 'Provider accepted delete but still lists the record',
|
|
1605
|
+
});
|
|
1606
|
+
continue;
|
|
1607
|
+
}
|
|
1608
|
+
await record.delete();
|
|
1609
|
+
results.set(record.id, { id: record.id, success: true });
|
|
1610
|
+
}
|
|
1417
1611
|
}
|
|
1418
|
-
|
|
1612
|
+
|
|
1613
|
+
return ids.map((id) => results.get(id) || { id, success: false, message: 'Record deletion was not evaluated' });
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
private isProviderRecordNotFoundError(error: Error): boolean {
|
|
1617
|
+
const providerError = error as Error & { status?: unknown; statusCode?: unknown };
|
|
1618
|
+
return providerError.status === 404 || providerError.statusCode === 404;
|
|
1419
1619
|
}
|
|
1420
1620
|
|
|
1421
1621
|
/**
|