@serve.zone/dcrouter 16.4.1 → 17.0.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.
Files changed (82) hide show
  1. package/deno.json +1 -1
  2. package/dist_serve/bundle.js +852 -852
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/classes.dcrouter.d.ts +5 -1
  5. package/dist_ts/classes.dcrouter.js +42 -9
  6. package/dist_ts/db/documents/classes.dns-record.doc.d.ts +4 -0
  7. package/dist_ts/db/documents/classes.dns-record.doc.js +33 -2
  8. package/dist_ts/db/documents/classes.email-domain.doc.d.ts +5 -1
  9. package/dist_ts/db/documents/classes.email-domain.doc.js +26 -2
  10. package/dist_ts/db/documents/classes.smartmta-storage.doc.d.ts +8 -0
  11. package/dist_ts/db/documents/classes.smartmta-storage.doc.js +91 -0
  12. package/dist_ts/db/documents/index.d.ts +1 -0
  13. package/dist_ts/db/documents/index.js +2 -1
  14. package/dist_ts/dns/manager.dns.d.ts +6 -0
  15. package/dist_ts/dns/manager.dns.js +81 -32
  16. package/dist_ts/dns/providers/cloudflare.provider.d.ts +2 -0
  17. package/dist_ts/dns/providers/cloudflare.provider.js +45 -28
  18. package/dist_ts/email/classes.email-domain.manager.d.ts +43 -38
  19. package/dist_ts/email/classes.email-domain.manager.js +391 -324
  20. package/dist_ts/email/classes.email-settings.manager.js +2 -1
  21. package/dist_ts/email/classes.mail-dns-sync.d.ts +58 -17
  22. package/dist_ts/email/classes.mail-dns-sync.js +857 -141
  23. package/dist_ts/email/classes.mail-edge-eligibility.d.ts +55 -0
  24. package/dist_ts/email/classes.mail-edge-eligibility.js +168 -0
  25. package/dist_ts/email/classes.mail-egress-coordinator.d.ts +3 -1
  26. package/dist_ts/email/classes.mail-egress-coordinator.js +43 -22
  27. package/dist_ts/email/classes.smartmta-blob-storage-manager.d.ts +27 -0
  28. package/dist_ts/email/classes.smartmta-blob-storage-manager.js +109 -0
  29. package/dist_ts/email/classes.smartmta-storage-manager.d.ts +6 -8
  30. package/dist_ts/email/classes.smartmta-storage-manager.js +63 -86
  31. package/dist_ts/email/classes.workapp-mail-manager.d.ts +3 -0
  32. package/dist_ts/email/classes.workapp-mail-manager.js +63 -14
  33. package/dist_ts/email/index.d.ts +3 -0
  34. package/dist_ts/email/index.js +4 -1
  35. package/dist_ts/email/smartmta-storage-policy.d.ts +9 -0
  36. package/dist_ts/email/smartmta-storage-policy.js +58 -0
  37. package/dist_ts/opsserver/handlers/email-domain.handler.d.ts +1 -0
  38. package/dist_ts/opsserver/handlers/email-domain.handler.js +138 -22
  39. package/dist_ts/opsserver/handlers/stats.handler.js +3 -5
  40. package/dist_ts/plugins.d.ts +2 -1
  41. package/dist_ts/plugins.js +3 -2
  42. package/dist_ts/remoteingress/classes.hub-lifecycle.js +2 -1
  43. package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +6 -0
  44. package/dist_ts/remoteingress/classes.tunnel-manager.js +40 -2
  45. package/dist_ts_interfaces/data/dns-record.d.ts +6 -0
  46. package/dist_ts_interfaces/data/email-domain.d.ts +81 -0
  47. package/dist_ts_interfaces/requests/email-domains.d.ts +25 -17
  48. package/dist_ts_migrations/index.d.ts +2 -0
  49. package/dist_ts_migrations/index.js +441 -16
  50. package/dist_ts_web/00_commitinfo_data.js +1 -1
  51. package/dist_ts_web/appstate/email-domains.d.ts +16 -0
  52. package/dist_ts_web/appstate/email-domains.js +140 -19
  53. package/dist_ts_web/elements/email/ops-view-email-domains.d.ts +1 -0
  54. package/dist_ts_web/elements/email/ops-view-email-domains.js +36 -13
  55. package/package.json +4 -3
  56. package/readme.md +13 -1
  57. package/ts/00_commitinfo_data.ts +1 -1
  58. package/ts/classes.dcrouter.ts +55 -11
  59. package/ts/db/documents/classes.dns-record.doc.ts +20 -0
  60. package/ts/db/documents/classes.email-domain.doc.ts +14 -0
  61. package/ts/db/documents/classes.smartmta-storage.doc.ts +25 -0
  62. package/ts/db/documents/index.ts +1 -0
  63. package/ts/dns/manager.dns.ts +89 -29
  64. package/ts/dns/providers/cloudflare.provider.ts +46 -27
  65. package/ts/email/classes.email-domain.manager.ts +416 -368
  66. package/ts/email/classes.email-settings.manager.ts +1 -0
  67. package/ts/email/classes.mail-dns-sync.ts +913 -146
  68. package/ts/email/classes.mail-edge-eligibility.ts +205 -0
  69. package/ts/email/classes.mail-egress-coordinator.ts +46 -23
  70. package/ts/email/classes.smartmta-blob-storage-manager.ts +138 -0
  71. package/ts/email/classes.smartmta-storage-manager.ts +86 -83
  72. package/ts/email/classes.workapp-mail-manager.ts +82 -16
  73. package/ts/email/index.ts +3 -0
  74. package/ts/email/smartmta-storage-policy.ts +73 -0
  75. package/ts/opsserver/handlers/email-domain.handler.ts +154 -21
  76. package/ts/opsserver/handlers/stats.handler.ts +2 -4
  77. package/ts/plugins.ts +2 -1
  78. package/ts/remoteingress/classes.hub-lifecycle.ts +1 -0
  79. package/ts/remoteingress/classes.tunnel-manager.ts +53 -7
  80. package/ts_web/00_commitinfo_data.ts +1 -1
  81. package/ts_web/appstate/email-domains.ts +187 -18
  82. package/ts_web/elements/email/ops-view-email-domains.ts +44 -12
@@ -3,18 +3,18 @@ import { logger } from '../logger.js';
3
3
  import { EmailDomainDoc } from '../db/documents/classes.email-domain.doc.js';
4
4
  import { DomainDoc } from '../db/documents/classes.domain.doc.js';
5
5
  import { DnsRecordDoc } from '../db/documents/classes.dns-record.doc.js';
6
- import { buildEmailDnsRecords } from './email-dns-records.js';
7
6
  /**
8
- * EmailDomainManager — orchestrates email domain setup.
9
- *
10
- * Wires smartmta's DKIMCreator (key generation) with dcrouter's DnsManager
11
- * (record creation for dcrouter-hosted and provider-managed zones) to provide
12
- * a single entry point for setting up an email domain from A to Z.
7
+ * Persists managed email domains and projects them into SmartMTA. DNS mutation
8
+ * is delegated exclusively to MailDnsSync.
13
9
  */
14
10
  export class EmailDomainManager {
15
11
  dcRouter; // DcRouter — avoids circular import
16
12
  baseEmailDomains = [];
17
- dnsClient;
13
+ mutationChain = Promise.resolve();
14
+ /** Explicit upstream capability marker; absence is deliberately fail-closed. */
15
+ get selectorCorrectSigningCapability() {
16
+ return plugins.smartmta.smartMtaCapabilities?.selectorCorrectDkimSigning === true;
17
+ }
18
18
  constructor(dcRouterRef) {
19
19
  this.dcRouter = dcRouterRef;
20
20
  this.setBaseEmailDomains(this.dcRouter.options?.emailConfig?.domains);
@@ -23,28 +23,28 @@ export class EmailDomainManager {
23
23
  this.baseEmailDomains = (domains || [])
24
24
  .map((domainConfig) => JSON.parse(JSON.stringify(domainConfig)));
25
25
  }
26
- get dnsManager() {
27
- return this.dcRouter.dnsManager;
28
- }
29
26
  get dkimCreator() {
30
27
  return this.dcRouter.emailServer?.dkimCreator;
31
28
  }
32
- get emailHostname() {
33
- return this.dcRouter.options?.emailConfig?.hostname || this.dcRouter.options?.tls?.domain || 'localhost';
34
- }
35
29
  async start() {
30
+ // Inbound projection is safe before the SMTP server exists. DNS scheduling
31
+ // starts later, after DNS, RemoteIngress, tunnel, and DKIM dependencies.
36
32
  await this.syncManagedDomainsToRuntime();
37
33
  }
38
34
  async stop() {
39
- this.dnsClient?.destroy();
40
- this.dnsClient = undefined;
35
+ await this.mutationChain.catch(() => undefined);
36
+ }
37
+ supportsSelectorCorrectSigning() {
38
+ return this.selectorCorrectSigningCapability;
39
+ }
40
+ async runMutationExclusive(action) {
41
+ const result = this.mutationChain.catch(() => undefined).then(action);
42
+ this.mutationChain = result.then(() => undefined, () => undefined);
43
+ return await result;
41
44
  }
42
- // ---------------------------------------------------------------------------
43
- // CRUD
44
- // ---------------------------------------------------------------------------
45
45
  async getAll() {
46
46
  const docs = await EmailDomainDoc.findAll();
47
- return docs.map((d) => this.docToInterface(d));
47
+ return docs.map((doc) => this.docToInterface(doc));
48
48
  }
49
49
  async getById(id) {
50
50
  const doc = await EmailDomainDoc.findById(id);
@@ -62,324 +62,389 @@ export class EmailDomainManager {
62
62
  if (this.isDomainAlreadyConfigured(normalizedDomain))
63
63
  return null;
64
64
  const linkedDomain = await this.findLinkedDnsDomain(normalizedDomain);
65
- if (!linkedDomain) {
65
+ if (!linkedDomain)
66
66
  throw new Error(`DNS domain not found for email domain: ${normalizedDomain}`);
67
- }
68
67
  const subdomain = normalizedDomain === linkedDomain.name
69
68
  ? undefined
70
69
  : normalizedDomain.slice(0, -(linkedDomain.name.length + 1));
71
- return await this.createEmailDomain({
72
- linkedDomainId: linkedDomain.id,
73
- subdomain,
74
- });
70
+ return await this.createEmailDomain({ linkedDomainId: linkedDomain.id, subdomain });
75
71
  }
76
72
  async createEmailDomain(opts) {
77
- // Resolve the linked DNS domain
78
- const domainDoc = await DomainDoc.findById(opts.linkedDomainId);
79
- if (!domainDoc) {
80
- throw new Error(`DNS domain not found: ${opts.linkedDomainId}`);
81
- }
82
- const baseDomain = domainDoc.name;
83
- const subdomain = opts.subdomain?.trim() || undefined;
84
- const domainName = subdomain ? `${subdomain}.${baseDomain}` : baseDomain;
85
- // Check for duplicates
86
- if (this.isDomainAlreadyConfigured(domainName)) {
87
- throw new Error(`Email domain already configured for ${domainName}`);
88
- }
89
- const existing = await EmailDomainDoc.findByDomain(domainName);
90
- if (existing) {
91
- throw new Error(`Email domain already exists for ${domainName}`);
92
- }
93
- const selector = opts.dkimSelector || 'default';
94
- const keySize = opts.dkimKeySize || 2048;
95
- const now = new Date().toISOString();
96
- // Generate DKIM keys
97
- let publicKey;
98
- if (this.dkimCreator) {
73
+ const created = await this.runMutationExclusive(async () => {
74
+ const domainDoc = await DomainDoc.findById(opts.linkedDomainId);
75
+ if (!domainDoc)
76
+ throw new Error(`DNS domain not found: ${opts.linkedDomainId}`);
77
+ const subdomain = opts.subdomain?.trim().toLowerCase() || undefined;
78
+ const domainName = (subdomain ? `${subdomain}.${domainDoc.name}` : domainDoc.name).toLowerCase();
79
+ if (this.isDomainAlreadyConfigured(domainName)) {
80
+ throw new Error(`Email domain already configured for ${domainName}`);
81
+ }
82
+ if (await EmailDomainDoc.findByDomain(domainName)) {
83
+ throw new Error(`Email domain already exists for ${domainName}`);
84
+ }
85
+ const selector = opts.dkimSelector?.trim() || 'default';
86
+ if (selector !== 'default' && !this.selectorCorrectSigningCapability) {
87
+ throw this.capabilityError('SMARTMTA_SELECTOR_SIGNING_UNSUPPORTED', 'Custom DKIM selectors are disabled until the selector-correct SmartMTA release is consumed');
88
+ }
89
+ if (opts.rotateKeys && !this.selectorCorrectSigningCapability) {
90
+ throw this.capabilityError('SMARTMTA_DKIM_ROTATION_UNSUPPORTED', 'Automatic DKIM rotation is disabled until the selector-correct SmartMTA release is consumed');
91
+ }
92
+ if (!this.dkimCreator) {
93
+ throw new Error('DKIM key creator is not ready; email domain was not persisted');
94
+ }
95
+ const keySize = opts.dkimKeySize || 2048;
96
+ await this.dkimCreator.handleDKIMKeysForSelector(domainName, selector, keySize);
97
+ const dnsRecord = await this.dkimCreator.getDNSRecordForDomain(domainName, selector);
98
+ const publicKey = this.extractDkimPublicKey(dnsRecord?.value);
99
+ if (!publicKey) {
100
+ throw new Error(`DKIM key generation for ${domainName} returned no usable public key; email domain was not persisted`);
101
+ }
102
+ const now = new Date().toISOString();
103
+ const activeDkim = {
104
+ selector,
105
+ keySize,
106
+ publicKey,
107
+ createdAt: now,
108
+ };
109
+ const doc = new EmailDomainDoc();
110
+ doc.id = plugins.smartunique.shortId();
111
+ doc.domain = domainName;
112
+ doc.linkedDomainId = opts.linkedDomainId;
113
+ doc.subdomain = subdomain;
114
+ doc.dkim = {
115
+ selector,
116
+ keySize,
117
+ publicKey,
118
+ rotateKeys: opts.rotateKeys ?? false,
119
+ rotationIntervalDays: opts.rotationIntervalDays ?? 90,
120
+ retirementOverlapDays: 30,
121
+ };
122
+ doc.activeDkim = activeDkim;
123
+ doc.retiringDkim = [];
124
+ doc.remoteIngress = this.normalizeRemoteIngressPin(opts.remoteIngress, domainName);
125
+ doc.dnsStatus = { mx: 'unchecked', spf: 'unchecked', dkim: 'unchecked', dmarc: 'unchecked' };
126
+ doc.reconciliation = {
127
+ lifecycleStatus: 'pending',
128
+ desiredGeneration: 1,
129
+ intents: [],
130
+ errors: [{
131
+ code: 'RECONCILIATION_PENDING',
132
+ message: 'Initial DNS reconciliation has not completed',
133
+ retryable: true,
134
+ }],
135
+ capability: {
136
+ egressIdentityProof: 'unsupported',
137
+ selectorCorrectSigning: selector === 'default' || this.selectorCorrectSigningCapability
138
+ ? 'supported'
139
+ : 'unsupported',
140
+ },
141
+ };
142
+ doc.createdAt = now;
143
+ doc.updatedAt = now;
99
144
  try {
100
- await this.dkimCreator.handleDKIMKeysForSelector(domainName, selector, keySize);
101
- const dnsRecord = await this.dkimCreator.getDNSRecordForDomain(domainName, selector);
102
- // Extract public key from the DNS record value
103
- const match = dnsRecord?.value?.match(/p=([A-Za-z0-9+/=]+)/);
104
- publicKey = match ? match[1] : undefined;
105
- logger.log('info', `DKIM keys generated for ${domainName} (selector: ${selector})`);
145
+ await doc.save();
106
146
  }
107
- catch (err) {
108
- logger.log('warn', `DKIM key generation failed for ${domainName}: ${err.message}`);
147
+ catch (error) {
148
+ if (error?.code === 11000 || error?.codeName === 'DuplicateKey') {
149
+ throw new Error(`Email domain already exists for ${domainName}`);
150
+ }
151
+ throw error;
109
152
  }
110
- }
111
- // Create the document
112
- const doc = new EmailDomainDoc();
113
- doc.id = plugins.smartunique.shortId();
114
- doc.domain = domainName.toLowerCase();
115
- doc.linkedDomainId = opts.linkedDomainId;
116
- doc.subdomain = subdomain;
117
- doc.dkim = {
118
- selector,
119
- keySize,
120
- publicKey,
121
- rotateKeys: opts.rotateKeys ?? false,
122
- rotationIntervalDays: opts.rotationIntervalDays ?? 90,
123
- };
124
- doc.dnsStatus = {
125
- mx: 'unchecked',
126
- spf: 'unchecked',
127
- dkim: 'unchecked',
128
- dmarc: 'unchecked',
129
- };
130
- doc.remoteIngress = this.normalizeRemoteIngressPin(opts.remoteIngress, domainName);
131
- doc.createdAt = now;
132
- doc.updatedAt = now;
133
- await doc.save();
134
- await this.syncManagedDomainsToRuntime();
135
- this.dcRouter.mailDnsSync?.requestSync(`email domain created: ${domainName}`);
136
- logger.log('info', `Email domain created: ${domainName}`);
137
- return this.docToInterface(doc);
153
+ await this.syncManagedDomainsToRuntime();
154
+ return { id: doc.id, domainName };
155
+ });
156
+ await this.dcRouter.mailDnsSync?.sync(`email domain created: ${created.domainName}`);
157
+ const current = await EmailDomainDoc.findById(created.id);
158
+ if (!current)
159
+ throw new Error(`Email domain disappeared during reconciliation: ${created.domainName}`);
160
+ logger.log('info', `Email domain created in ${current.reconciliation?.lifecycleStatus || 'pending'} state: ${created.domainName}`);
161
+ return this.docToInterface(current);
138
162
  }
139
163
  async updateEmailDomain(id, changes) {
140
- const doc = await EmailDomainDoc.findById(id);
141
- if (!doc)
142
- throw new Error(`Email domain not found: ${id}`);
143
- if (changes.rotateKeys !== undefined)
144
- doc.dkim.rotateKeys = changes.rotateKeys;
145
- if (changes.rotationIntervalDays !== undefined)
146
- doc.dkim.rotationIntervalDays = changes.rotationIntervalDays;
147
- if (changes.rateLimits !== undefined)
148
- doc.rateLimits = changes.rateLimits;
149
- if (changes.remoteIngress !== undefined) {
150
- doc.remoteIngress = changes.remoteIngress === null
151
- ? undefined
152
- : this.normalizeRemoteIngressPin(changes.remoteIngress, doc.domain);
153
- }
154
- doc.updatedAt = new Date().toISOString();
155
- await doc.save();
156
- await this.syncManagedDomainsToRuntime();
157
- this.dcRouter.mailDnsSync?.requestSync(`email domain updated: ${doc.domain}`);
158
- }
159
- /**
160
- * Normalize a per-domain edge pin. Pins may reference edges that are not
161
- * registered yet — that only warns, so pins can precede edge registration.
162
- */
163
- normalizeRemoteIngressPin(pin, domainName) {
164
- const edgeFilter = [...new Set((pin?.edgeFilter || []).map((entry) => `${entry}`.trim()).filter(Boolean))];
165
- if (edgeFilter.length === 0) {
166
- return undefined;
167
- }
168
- const manager = this.dcRouter.remoteIngressManager;
169
- if (manager && manager.resolveEdgesByFilter(edgeFilter).length === 0) {
170
- logger.log('warn', `Email domain ${domainName}: edge pin [${edgeFilter.join(', ')}] matches no registered enabled edge yet`);
171
- }
172
- return { edgeFilter };
164
+ const mutation = await this.runMutationExclusive(async () => {
165
+ const doc = await EmailDomainDoc.findById(id);
166
+ if (!doc)
167
+ throw new Error(`Email domain not found: ${id}`);
168
+ if (changes.rotateKeys === true && !this.selectorCorrectSigningCapability) {
169
+ return {
170
+ kind: 'result',
171
+ result: this.unsupportedResult(doc, 'SMARTMTA_DKIM_ROTATION_UNSUPPORTED', 'Automatic DKIM rotation is disabled until the selector-correct SmartMTA release is consumed'),
172
+ };
173
+ }
174
+ if (changes.rotateKeys !== undefined)
175
+ doc.dkim.rotateKeys = changes.rotateKeys;
176
+ if (changes.rotationIntervalDays !== undefined)
177
+ doc.dkim.rotationIntervalDays = changes.rotationIntervalDays;
178
+ if (changes.rateLimits !== undefined)
179
+ doc.rateLimits = changes.rateLimits;
180
+ if (changes.remoteIngress !== undefined) {
181
+ doc.remoteIngress = changes.remoteIngress === null
182
+ ? undefined
183
+ : this.normalizeRemoteIngressPin(changes.remoteIngress, doc.domain);
184
+ }
185
+ doc.reconciliation = this.invalidateReconciliation(doc, 'EMAIL_DOMAIN_CONFIGURATION_CHANGED');
186
+ doc.updatedAt = new Date().toISOString();
187
+ await doc.save();
188
+ await this.syncManagedDomainsToRuntime();
189
+ return { kind: 'sync', domainName: doc.domain };
190
+ });
191
+ if (mutation.kind === 'result')
192
+ return mutation.result;
193
+ await this.dcRouter.mailDnsSync?.sync(`email domain updated: ${mutation.domainName}`);
194
+ const current = await EmailDomainDoc.findById(id);
195
+ if (!current)
196
+ throw new Error(`Email domain disappeared during reconciliation: ${id}`);
197
+ return this.resultForDoc(current, !this.hasDnsMutationFailure(current));
173
198
  }
174
- /** Enabled edges pinned for this domain (empty when unpinned). */
175
- resolvePinnedEdges(doc) {
176
- const edgeFilter = doc.remoteIngress?.edgeFilter;
177
- if (!edgeFilter?.length) {
178
- return [];
199
+ async deleteEmailDomain(id) {
200
+ const mutation = await this.runMutationExclusive(async () => {
201
+ const doc = await EmailDomainDoc.findById(id);
202
+ if (!doc)
203
+ throw new Error(`Email domain not found: ${id}`);
204
+ const bindings = await this.dcRouter.workAppMailManager?.listMailAddressBindings({ domain: doc.domain }) || [];
205
+ if (bindings.length > 0) {
206
+ return {
207
+ kind: 'result',
208
+ result: {
209
+ success: false,
210
+ lifecycleStatus: doc.reconciliation?.lifecycleStatus || 'pending',
211
+ code: 'EMAIL_DOMAIN_HAS_BINDINGS',
212
+ message: `Email domain ${doc.domain} still has ${bindings.length} WorkApp mail binding(s)`,
213
+ errors: [{
214
+ code: 'EMAIL_DOMAIN_HAS_BINDINGS',
215
+ message: 'Delete all WorkApp mail bindings before deleting the email domain',
216
+ retryable: false,
217
+ }],
218
+ },
219
+ };
220
+ }
221
+ const now = new Date().toISOString();
222
+ doc.reconciliation = {
223
+ ...(doc.reconciliation || { desiredGeneration: 1, intents: [], errors: [] }),
224
+ lifecycleStatus: 'deleting',
225
+ intents: [],
226
+ errors: [],
227
+ deletingAt: now,
228
+ retryAt: new Date(Date.now() + 300_000).toISOString(),
229
+ };
230
+ doc.updatedAt = now;
231
+ await doc.save();
232
+ await this.syncManagedDomainsToRuntime();
233
+ return { kind: 'sync', domainName: doc.domain };
234
+ });
235
+ if (mutation.kind === 'result')
236
+ return mutation.result;
237
+ await this.dcRouter.mailDnsSync?.sync(`email domain deleting: ${mutation.domainName}`);
238
+ const remaining = await EmailDomainDoc.findById(id);
239
+ if (!remaining) {
240
+ return { success: true, lifecycleStatus: 'deleting', message: `Email domain ${mutation.domainName} deleted` };
179
241
  }
180
- return this.dcRouter.remoteIngressManager?.resolveEdgesByFilter(edgeFilter) || [];
242
+ return this.resultForDoc(remaining, remaining.reconciliation?.errors.length === 0);
181
243
  }
182
- async deleteEmailDomain(id) {
183
- const doc = await EmailDomainDoc.findById(id);
184
- if (!doc)
185
- throw new Error(`Email domain not found: ${id}`);
186
- await doc.delete();
187
- await this.syncManagedDomainsToRuntime();
188
- this.dcRouter.mailDnsSync?.requestSync(`email domain deleted: ${doc.domain}`);
189
- logger.log('info', `Email domain deleted: ${doc.domain}`);
190
- }
191
- // ---------------------------------------------------------------------------
192
- // DNS record computation
193
- // ---------------------------------------------------------------------------
194
- /**
195
- * Compute the 4 required DNS records for an email domain.
196
- */
197
244
  async getRequiredDnsRecords(id) {
198
245
  const doc = await EmailDomainDoc.findById(id);
199
246
  if (!doc)
200
247
  throw new Error(`Email domain not found: ${id}`);
201
- const domain = doc.domain;
202
- const selector = doc.dkim.selector;
203
- // Pinned domains get their own MX host whose A records are the pinned edges'
204
- // public IPs; unpinned domains use the shared mail hostname.
205
- const pinnedEdges = this.resolvePinnedEdges(doc);
206
- const hostname = pinnedEdges.length > 0 ? `mx.${domain}` : this.emailHostname;
207
- let dkimValue = `v=DKIM1; h=sha256; k=rsa; p=${doc.dkim.publicKey || ''}`;
208
- if (this.dkimCreator) {
209
- try {
210
- const dnsRecord = await this.dkimCreator.getDNSRecordForDomain(domain, selector);
211
- dkimValue = dnsRecord.value;
212
- }
213
- catch (err) {
214
- logger.log('warn', `Failed to load DKIM DNS record for ${domain}: ${err.message}`);
215
- }
216
- }
217
- const records = buildEmailDnsRecords({
218
- domain,
219
- hostname,
220
- selector,
221
- dkimValue,
222
- statuses: doc.dnsStatus,
223
- });
224
- for (const edge of pinnedEdges) {
225
- if (edge.publicIp) {
226
- records.push({ type: 'A', name: hostname, value: edge.publicIp, status: doc.dnsStatus.mx });
227
- }
228
- if (edge.publicIpV6) {
229
- records.push({ type: 'AAAA', name: hostname, value: edge.publicIpV6, status: doc.dnsStatus.mx });
230
- }
231
- }
232
- return records;
233
- }
234
- // ---------------------------------------------------------------------------
235
- // DNS provisioning
236
- // ---------------------------------------------------------------------------
237
- /**
238
- * Auto-create missing DNS records via the linked domain's DNS path.
239
- */
248
+ return (doc.reconciliation?.intents || []).map((intent) => ({
249
+ type: intent.type,
250
+ name: intent.name,
251
+ value: intent.value,
252
+ status: intent.status === 'valid'
253
+ ? 'valid'
254
+ : intent.status === 'conflict' || intent.status === 'failed'
255
+ ? 'invalid'
256
+ : 'missing',
257
+ }));
258
+ }
240
259
  async provisionDnsRecords(id) {
260
+ const before = new Set((await DnsRecordDoc.findAll()).filter((record) => record.managedBy === 'mail-dns-reconciler').map((record) => record.id));
261
+ await this.dcRouter.mailDnsSync?.sync(`manual provision: ${id}`);
241
262
  const doc = await EmailDomainDoc.findById(id);
242
263
  if (!doc)
243
264
  throw new Error(`Email domain not found: ${id}`);
244
- if (!this.dnsManager)
245
- throw new Error('DnsManager not available');
246
- const requiredRecords = await this.getRequiredDnsRecords(id);
247
- const domainId = doc.linkedDomainId;
248
- // Get existing DNS records for the linked domain
249
- const existingRecords = await DnsRecordDoc.findByDomainId(domainId);
250
- let provisioned = 0;
251
- for (const required of requiredRecords) {
252
- // Check if a matching record already exists
253
- const exists = existingRecords.some((r) => this.recordMatchesRequired(r, required));
254
- if (!exists) {
255
- try {
256
- await this.dnsManager.createRecord({
257
- domainId,
258
- name: required.name,
259
- type: required.type,
260
- value: required.value,
261
- ttl: 3600,
262
- createdBy: 'email-domain-manager',
263
- });
264
- provisioned++;
265
- logger.log('info', `Provisioned ${required.type} record for ${required.name}`);
266
- }
267
- catch (err) {
268
- logger.log('warn', `Failed to provision ${required.type} for ${required.name}: ${err.message}`);
269
- }
270
- }
271
- }
272
- // Re-validate after provisioning
273
- await this.validateDns(id);
274
- return provisioned;
275
- }
276
- // ---------------------------------------------------------------------------
277
- // DNS validation
278
- // ---------------------------------------------------------------------------
279
- /**
280
- * Validate DNS records via live lookups.
281
- */
265
+ const provisioned = (await DnsRecordDoc.findAll())
266
+ .filter((record) => record.managedBy === 'mail-dns-reconciler' && !before.has(record.id)).length;
267
+ return { ...this.resultForDoc(doc, !this.hasDnsMutationFailure(doc)), provisioned };
268
+ }
282
269
  async validateDns(id) {
270
+ await this.dcRouter.mailDnsSync?.sync(`manual validation: ${id}`);
283
271
  const doc = await EmailDomainDoc.findById(id);
284
272
  if (!doc)
285
273
  throw new Error(`Email domain not found: ${id}`);
286
- const domain = doc.domain;
287
- const selector = doc.dkim.selector;
288
- const dnsClient = this.getDnsClient();
289
- // MX check
290
- const requiredRecords = await this.getRequiredDnsRecords(id);
291
- const mxRecord = requiredRecords.find((record) => record.type === 'MX');
292
- const spfRecord = requiredRecords.find((record) => record.name === domain && record.value.startsWith('v=spf1'));
293
- const dkimRecord = requiredRecords.find((record) => record.name === `${selector}._domainkey.${domain}`);
294
- const dmarcRecord = requiredRecords.find((record) => record.name === `_dmarc.${domain}`);
295
- doc.dnsStatus.mx = await this.checkMx(dnsClient, domain, mxRecord?.value);
296
- // Pinned domains: the MX host's A records must cover the pinned edges' IPs.
297
- const requiredARecords = requiredRecords.filter((record) => record.type === 'A');
298
- if (doc.dnsStatus.mx === 'valid' && requiredARecords.length > 0) {
299
- const mxHostname = mxRecord?.value?.split(/\s+/)[1] || `mx.${domain}`;
300
- const aStatus = await this.checkARecords(dnsClient, mxHostname, requiredARecords.map((record) => record.value));
301
- if (aStatus !== 'valid') {
302
- doc.dnsStatus.mx = aStatus;
303
- }
304
- }
305
- // SPF check
306
- doc.dnsStatus.spf = await this.checkTxtRecord(dnsClient, domain, spfRecord?.value);
307
- // DKIM check
308
- doc.dnsStatus.dkim = await this.checkTxtRecord(dnsClient, `${selector}._domainkey.${domain}`, dkimRecord?.value);
309
- // DMARC check
310
- doc.dnsStatus.dmarc = await this.checkTxtRecord(dnsClient, `_dmarc.${domain}`, dmarcRecord?.value);
311
- doc.dnsStatus.lastCheckedAt = new Date().toISOString();
312
- doc.updatedAt = new Date().toISOString();
313
- await doc.save();
314
- return this.getRequiredDnsRecords(id);
315
- }
316
- recordMatchesRequired(record, required) {
317
- if (record.type !== required.type || record.name.toLowerCase() !== required.name.toLowerCase()) {
318
- return false;
319
- }
320
- return record.value.trim() === required.value.trim();
274
+ const records = await this.getRequiredDnsRecords(id);
275
+ return {
276
+ ...this.resultForDoc(doc, doc.reconciliation?.lifecycleStatus === 'active'),
277
+ domain: this.docToInterface(doc),
278
+ records,
279
+ };
321
280
  }
322
- /** Lazy shared smartdns client; the Rust bridge spawns on first non-system lookup. */
323
- getDnsClient() {
324
- if (!this.dnsClient) {
325
- this.dnsClient = new plugins.smartdns.dnsClientMod.Smartdns({});
281
+ async getOutboundReadiness(domainName) {
282
+ const doc = await EmailDomainDoc.findByDomain(domainName.toLowerCase());
283
+ if (!doc)
284
+ return { ready: true, edgeIds: [] }; // unmanaged/static domain policy
285
+ const activeDkim = this.getActiveDkim(doc);
286
+ if (!activeDkim)
287
+ return { ready: false, reason: 'no usable active DKIM key', edgeIds: [] };
288
+ if (activeDkim.selector !== 'default' && !this.selectorCorrectSigningCapability) {
289
+ return { ready: false, reason: 'SmartMTA selector-correct signing capability is unavailable', edgeIds: [] };
326
290
  }
327
- return this.dnsClient;
328
- }
329
- /** 'pref exchange' normalized for comparison: numeric pref, lowercased exchange, no trailing dot. */
330
- normalizeMxValue(value) {
331
- const [pref, exchange = ''] = value.trim().split(/\s+/);
332
- return `${Number(pref)} ${exchange.toLowerCase().replace(/\.$/, '')}`;
333
- }
334
- async checkMx(dnsClient, domain, expectedValue) {
335
- try {
336
- const records = await dnsClient.getRecords(domain, 'MX');
337
- if (!records || records.length === 0) {
338
- return 'missing';
339
- }
340
- if (!expectedValue) {
341
- return 'valid';
342
- }
343
- const expected = this.normalizeMxValue(expectedValue);
344
- const found = records.some((record) => this.normalizeMxValue(record.value) === expected);
345
- return found ? 'valid' : 'invalid';
291
+ if (!doc.reconciliation?.activeRevision) {
292
+ return { ready: false, reason: 'no validated active DNS revision', edgeIds: [] };
346
293
  }
347
- catch {
348
- return 'missing';
294
+ const live = await this.dcRouter.mailEdgeEligibility.resolveActiveForDomain(doc);
295
+ if (live.edges.length === 0) {
296
+ return { ready: false, reason: live.reason || 'no validated active egress edge is live', edgeIds: [] };
349
297
  }
298
+ return {
299
+ ready: true,
300
+ edgeIds: live.edges.map((candidate) => candidate.edge.id),
301
+ selector: activeDkim.selector,
302
+ };
350
303
  }
351
- async checkARecords(dnsClient, name, expectedIps) {
352
- try {
353
- const records = await dnsClient.getRecordsA(name);
354
- if (!records || records.length === 0) {
355
- return 'missing';
304
+ async requestDkimRotation(id) {
305
+ const mutation = await this.runMutationExclusive(async () => {
306
+ const doc = await EmailDomainDoc.findById(id);
307
+ if (!doc)
308
+ throw new Error(`Email domain not found: ${id}`);
309
+ if (!this.selectorCorrectSigningCapability) {
310
+ return {
311
+ kind: 'result',
312
+ result: this.unsupportedResult(doc, 'SMARTMTA_DKIM_ROTATION_UNSUPPORTED', 'DKIM rotation remains pending until the selector-correct SmartMTA release is consumed'),
313
+ };
356
314
  }
357
- const resolved = new Set(records.map((record) => record.value));
358
- return expectedIps.every((ip) => resolved.has(ip)) ? 'valid' : 'invalid';
359
- }
360
- catch {
361
- return 'missing';
362
- }
315
+ if (doc.pendingDkim) {
316
+ return {
317
+ kind: 'result',
318
+ result: {
319
+ ...this.resultForDoc(doc, true),
320
+ message: `Selector ${doc.pendingDkim.selector} is already staged`,
321
+ },
322
+ };
323
+ }
324
+ await this.stageDkimRotation(doc);
325
+ return { kind: 'sync', domainName: doc.domain };
326
+ });
327
+ if (mutation.kind === 'result')
328
+ return mutation.result;
329
+ await this.dcRouter.mailDnsSync?.sync(`DKIM rotation staged: ${mutation.domainName}`);
330
+ const current = await EmailDomainDoc.findById(id);
331
+ if (!current)
332
+ throw new Error(`Email domain disappeared during reconciliation: ${id}`);
333
+ return this.resultForDoc(current, !this.hasDnsMutationFailure(current));
363
334
  }
364
- async checkTxtRecord(dnsClient, name, expectedValue) {
365
- try {
366
- const records = await dnsClient.getRecordsTxt(name);
367
- if (!records || records.length === 0) {
368
- return 'missing';
335
+ /** Called by the reconciler before planning so scheduled external rotation is durable first. */
336
+ async stageDkimRotationIfDue(id) {
337
+ return await this.runMutationExclusive(async () => {
338
+ const doc = await EmailDomainDoc.findById(id);
339
+ if (!doc || !doc.dkim.rotateKeys || doc.pendingDkim || !this.selectorCorrectSigningCapability) {
340
+ return doc || undefined;
369
341
  }
370
- if (!expectedValue) {
371
- return 'valid';
342
+ const active = this.getActiveDkim(doc);
343
+ const reference = Date.parse(active?.promotedAt || doc.dkim.lastRotatedAt || active?.createdAt || doc.createdAt);
344
+ const intervalMs = Math.max(1, doc.dkim.rotationIntervalDays || 90) * 86_400_000;
345
+ if (Number.isFinite(reference) && Date.now() - reference < intervalMs)
346
+ return doc;
347
+ try {
348
+ await this.stageDkimRotation(doc);
372
349
  }
373
- const found = records.some((record) => record.value.trim() === expectedValue.trim());
374
- return found ? 'valid' : 'invalid';
375
- }
376
- catch {
377
- return 'missing';
350
+ catch (error) {
351
+ doc.reconciliation = this.invalidateReconciliation(doc, 'DKIM_ROTATION_STAGE_FAILED');
352
+ doc.reconciliation.errors = [{
353
+ code: 'DKIM_ROTATION_STAGE_FAILED',
354
+ message: `Failed to stage DKIM rotation: ${error.message}`,
355
+ retryable: true,
356
+ }];
357
+ doc.updatedAt = new Date().toISOString();
358
+ await doc.save();
359
+ }
360
+ return doc;
361
+ });
362
+ }
363
+ async stageDkimRotation(doc) {
364
+ if (!this.dkimCreator)
365
+ throw new Error('DKIM key creator is not ready');
366
+ const selector = `s${new Date().toISOString().slice(0, 10).replace(/-/g, '')}-${plugins.smartunique.shortId()}`;
367
+ const keySize = doc.dkim.keySize || 2048;
368
+ await this.dkimCreator.handleDKIMKeysForSelector(doc.domain, selector, keySize);
369
+ const record = await this.dkimCreator.getDNSRecordForDomain(doc.domain, selector);
370
+ const publicKey = this.extractDkimPublicKey(record?.value);
371
+ if (!publicKey)
372
+ throw new Error(`DKIM rotation generated no public key for ${selector}`);
373
+ doc.pendingDkim = { selector, keySize, publicKey, createdAt: new Date().toISOString() };
374
+ doc.reconciliation = this.invalidateReconciliation(doc, 'DKIM_ROTATION_STAGED');
375
+ doc.updatedAt = new Date().toISOString();
376
+ await doc.save();
377
+ }
378
+ normalizeRemoteIngressPin(pin, domainName) {
379
+ const edgeFilter = [...new Set((pin?.edgeFilter || []).map((entry) => `${entry}`.trim()).filter(Boolean))];
380
+ if (edgeFilter.length === 0)
381
+ return undefined;
382
+ const manager = this.dcRouter.remoteIngressManager;
383
+ if (manager && manager.resolveEdgesByFilter(edgeFilter).length === 0) {
384
+ logger.log('warn', `Email domain ${domainName}: pin [${edgeFilter.join(', ')}] matches no enabled edge yet`);
378
385
  }
386
+ return { edgeFilter };
387
+ }
388
+ extractDkimPublicKey(value) {
389
+ if (typeof value !== 'string')
390
+ return undefined;
391
+ return value.match(/(?:^|;)\s*p=([A-Za-z0-9+/=]+)(?:;|$)/)?.[1];
392
+ }
393
+ getActiveDkim(doc) {
394
+ if (doc.activeDkim?.publicKey)
395
+ return doc.activeDkim;
396
+ if (!doc.dkim?.publicKey)
397
+ return undefined;
398
+ return {
399
+ selector: doc.dkim.selector || 'default',
400
+ keySize: doc.dkim.keySize || 2048,
401
+ publicKey: doc.dkim.publicKey,
402
+ createdAt: doc.createdAt,
403
+ };
404
+ }
405
+ invalidateReconciliation(doc, code) {
406
+ return {
407
+ ...(doc.reconciliation || { desiredGeneration: 0, intents: [], errors: [] }),
408
+ lifecycleStatus: doc.reconciliation?.activeRevision ? 'active' : 'pending',
409
+ desiredGeneration: (doc.reconciliation?.desiredGeneration || 0) + 1,
410
+ errors: [{ code, message: 'DNS reconciliation is pending', retryable: true }],
411
+ retryAt: new Date().toISOString(),
412
+ };
413
+ }
414
+ capabilityError(code, message) {
415
+ const error = new Error(message);
416
+ error.code = code;
417
+ error.capability = 'unsupported';
418
+ error.errors = [{ code, message, retryable: false }];
419
+ return error;
420
+ }
421
+ unsupportedResult(doc, code, message) {
422
+ return {
423
+ success: false,
424
+ lifecycleStatus: doc.reconciliation?.lifecycleStatus || 'pending',
425
+ code,
426
+ capability: 'unsupported',
427
+ message,
428
+ errors: [{ code, message, retryable: false }],
429
+ };
430
+ }
431
+ hasDnsMutationFailure(doc) {
432
+ return (doc.reconciliation?.intents || []).some((intent) => (intent.status === 'failed' || intent.status === 'conflict')) || (doc.reconciliation?.errors || []).some((error) => (['DNS_PROVIDER_ZONE_FAILED', 'DNS_UNMANAGED_CONFLICT', 'DNS_CLEANUP_FAILED'].includes(error.code)));
433
+ }
434
+ resultForDoc(doc, actionSucceeded) {
435
+ const state = doc.reconciliation;
436
+ const firstError = state?.errors[0];
437
+ return {
438
+ success: actionSucceeded,
439
+ lifecycleStatus: state?.lifecycleStatus || 'pending',
440
+ message: firstError?.message,
441
+ code: firstError?.code,
442
+ errors: state?.errors,
443
+ retryAt: state?.retryAt,
444
+ capability: state?.capability?.egressIdentityProof,
445
+ domain: this.docToInterface(doc),
446
+ };
379
447
  }
380
- // ---------------------------------------------------------------------------
381
- // Helpers
382
- // ---------------------------------------------------------------------------
383
448
  docToInterface(doc) {
384
449
  return {
385
450
  id: doc.id,
@@ -390,52 +455,56 @@ export class EmailDomainManager {
390
455
  rateLimits: doc.rateLimits,
391
456
  remoteIngress: doc.remoteIngress,
392
457
  dnsStatus: doc.dnsStatus,
458
+ reconciliation: doc.reconciliation,
459
+ activeDkim: doc.activeDkim,
460
+ pendingDkim: doc.pendingDkim,
461
+ retiringDkim: doc.retiringDkim,
393
462
  createdAt: doc.createdAt,
394
463
  updatedAt: doc.updatedAt,
395
464
  };
396
465
  }
397
466
  isDomainAlreadyConfigured(domainName) {
398
- const configuredDomains = (this.dcRouter.options?.emailConfig?.domains || [])
399
- .map((domainConfig) => domainConfig.domain.toLowerCase());
400
- return configuredDomains.includes(domainName.toLowerCase());
467
+ return (this.dcRouter.options?.emailConfig?.domains || [])
468
+ .some((domainConfig) => domainConfig.domain.toLowerCase() === domainName.toLowerCase());
401
469
  }
402
470
  async findLinkedDnsDomain(domainName) {
403
471
  const domains = await DomainDoc.findAll();
404
472
  return domains
405
473
  .filter((domainDoc) => domainName === domainDoc.name || domainName.endsWith(`.${domainDoc.name}`))
406
- .sort((a, b) => b.name.length - a.name.length)[0] || null;
474
+ .sort((left, right) => right.name.length - left.name.length)[0] || null;
407
475
  }
408
476
  async buildManagedDomainConfigs() {
409
477
  const docs = await EmailDomainDoc.findAll();
410
478
  const managedConfigs = [];
411
479
  for (const doc of docs) {
412
- const linkedDomain = await DomainDoc.findById(doc.linkedDomainId);
413
- if (!linkedDomain) {
414
- logger.log('warn', `Skipping managed email domain ${doc.domain}: linked domain missing`);
480
+ if (doc.reconciliation?.lifecycleStatus === 'deleting')
481
+ continue;
482
+ if (!await DomainDoc.findById(doc.linkedDomainId)) {
483
+ logger.log('warn', `Managed email domain ${doc.domain} has no linked DNS domain; keeping it out of runtime`);
415
484
  continue;
416
485
  }
486
+ const activeDkim = this.getActiveDkim(doc);
487
+ const dkimConfig = activeDkim && (activeDkim.selector === 'default' || this.selectorCorrectSigningCapability)
488
+ ? {
489
+ selector: activeDkim.selector,
490
+ keySize: activeDkim.keySize,
491
+ // Dcrouter exclusively owns staged external rotation.
492
+ rotateKeys: false,
493
+ rotationInterval: doc.dkim.rotationIntervalDays,
494
+ }
495
+ : undefined;
417
496
  managedConfigs.push({
418
497
  domain: doc.domain,
419
- // Always external-dns: DcRouter owns the DNS records for managed domains
420
- // (email-domain-manager DnsRecordDocs). internal-dns would make smartmta
421
- // self-register a conflicting MX (exchange = the domain itself) plus
422
- // duplicate SPF/DKIM TXT handlers on the shared DNS server.
423
498
  dnsMode: 'external-dns',
424
- dkim: {
425
- selector: doc.dkim.selector,
426
- keySize: doc.dkim.keySize,
427
- rotateKeys: doc.dkim.rotateKeys,
428
- rotationInterval: doc.dkim.rotationIntervalDays,
429
- },
499
+ ...(dkimConfig ? { dkim: dkimConfig } : {}),
430
500
  rateLimits: doc.rateLimits,
431
501
  });
432
502
  }
433
503
  return managedConfigs;
434
504
  }
435
505
  async syncManagedDomainsToRuntime() {
436
- if (!this.dcRouter.options?.emailConfig) {
506
+ if (!this.dcRouter.options?.emailConfig)
437
507
  return;
438
- }
439
508
  const mergedDomains = new Map();
440
509
  for (const domainConfig of this.baseEmailDomains) {
441
510
  mergedDomains.set(domainConfig.domain.toLowerCase(), JSON.parse(JSON.stringify(domainConfig)));
@@ -448,11 +517,9 @@ export class EmailDomainManager {
448
517
  }
449
518
  mergedDomains.set(key, managedConfig);
450
519
  }
451
- const domains = Array.from(mergedDomains.values());
520
+ const domains = [...mergedDomains.values()];
452
521
  this.dcRouter.options.emailConfig.domains = domains;
453
- if (this.dcRouter.emailServer) {
454
- this.dcRouter.emailServer.updateOptions({ domains });
455
- }
522
+ this.dcRouter.emailServer?.updateOptions({ domains });
456
523
  }
457
524
  }
458
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbC1kb21haW4ubWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2VtYWlsL2NsYXNzZXMuZW1haWwtZG9tYWluLm1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFFekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDN0UsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUl6RSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU5RDs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ3JCLFFBQVEsQ0FBTSxDQUFDLG9DQUFvQztJQUNuRCxnQkFBZ0IsR0FBeUIsRUFBRSxDQUFDO0lBQzVDLFNBQVMsQ0FBMEM7SUFFM0QsWUFBWSxXQUFnQjtRQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLFdBQVcsQ0FBQztRQUM1QixJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE9BQTJDLENBQUMsQ0FBQztJQUM1RyxDQUFDO0lBRU0sbUJBQW1CLENBQUMsT0FBeUM7UUFDbEUsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQzthQUNwQyxHQUFHLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBdUIsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFFRCxJQUFZLFVBQVU7UUFDcEIsT0FBTyxJQUFJLENBQUMsUUFB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
525
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5lbWFpbC1kb21haW4ubWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2VtYWlsL2NsYXNzZXMuZW1haWwtZG9tYWluLm1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFFekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDN0UsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQXVCekU7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUNyQixRQUFRLENBQU0sQ0FBQyxvQ0FBb0M7SUFDbkQsZ0JBQWdCLEdBQXlCLEVBQUUsQ0FBQztJQUM1QyxhQUFhLEdBQXFCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM1RCxnRkFBZ0Y7SUFDaEYsSUFBWSxnQ0FBZ0M7UUFDMUMsT0FBUSxPQUFPLENBQUMsUUFBZ0IsQ0FBQyxvQkFBb0IsRUFBRSwwQkFBMEIsS0FBSyxJQUFJLENBQUM7SUFDN0YsQ0FBQztJQUVELFlBQVksV0FBZ0I7UUFDMUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxXQUFXLENBQUM7UUFDNUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxPQUEyQyxDQUFDLENBQUM7SUFDNUcsQ0FBQztJQUVNLG1CQUFtQixDQUFDLE9BQXlDO1FBQ2xFLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUM7YUFDcEMsR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxT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