@serve.zone/dcrouter 17.0.0 → 17.1.1

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 (141) hide show
  1. package/.smartconfig.json +7 -4
  2. package/deno.json +1 -1
  3. package/dist_serve/bundle.js +1316 -1151
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/classes.dcrouter.d.ts +3 -1
  6. package/dist_ts/classes.dcrouter.js +113 -52
  7. package/dist_ts/db/classes.cache.cleaner.d.ts +3 -0
  8. package/dist_ts/db/classes.cache.cleaner.js +7 -3
  9. package/dist_ts/db/classes.dcrouter-db.js +1 -2
  10. package/dist_ts/db/documents/classes.cached.email.d.ts +41 -4
  11. package/dist_ts/db/documents/classes.cached.email.js +36 -5
  12. package/dist_ts/db/documents/classes.dns-record.doc.js +3 -1
  13. package/dist_ts/dns/classes.dns-server-runtime.d.ts +0 -1
  14. package/dist_ts/dns/classes.dns-server-runtime.js +4 -36
  15. package/dist_ts/dns/index.d.ts +1 -0
  16. package/dist_ts/dns/index.js +2 -1
  17. package/dist_ts/dns/manager.dns.d.ts +1 -0
  18. package/dist_ts/dns/manager.dns.js +49 -14
  19. package/dist_ts/dns/providers/cloudflare.provider.js +19 -4
  20. package/dist_ts/dns/txt-record-presentation.d.ts +20 -0
  21. package/dist_ts/dns/txt-record-presentation.js +131 -0
  22. package/dist_ts/email/classes.accepted-email-spool.d.ts +32 -3
  23. package/dist_ts/email/classes.accepted-email-spool.js +174 -13
  24. package/dist_ts/email/classes.email-domain.manager.d.ts +14 -1
  25. package/dist_ts/email/classes.email-domain.manager.js +151 -8
  26. package/dist_ts/email/classes.email-settings.manager.js +2 -2
  27. package/dist_ts/email/classes.mail-dns-sync.d.ts +31 -5
  28. package/dist_ts/email/classes.mail-dns-sync.js +508 -117
  29. package/dist_ts/email/classes.smartmta-blob-storage-manager.d.ts +2 -2
  30. package/dist_ts/email/classes.smartmta-blob-storage-manager.js +4 -3
  31. package/dist_ts/email/classes.workapp-mail-manager.d.ts +1 -0
  32. package/dist_ts/email/classes.workapp-mail-manager.js +26 -2
  33. package/dist_ts/email/index.d.ts +2 -0
  34. package/dist_ts/email/index.js +3 -1
  35. package/dist_ts/email/mail-dns-txt-policy.d.ts +18 -0
  36. package/dist_ts/email/mail-dns-txt-policy.js +466 -0
  37. package/dist_ts/email/reconcile-mail-dns-singleton.d.ts +47 -0
  38. package/dist_ts/email/reconcile-mail-dns-singleton.js +159 -0
  39. package/dist_ts/opsserver/classes.opsserver.d.ts +8 -0
  40. package/dist_ts/opsserver/classes.opsserver.js +34 -1
  41. package/dist_ts/opsserver/handlers/certificate.handler.js +25 -4
  42. package/dist_ts/opsserver/handlers/config.handler.js +9 -5
  43. package/dist_ts/opsserver/handlers/dns-provider.handler.js +19 -2
  44. package/dist_ts/opsserver/handlers/dns-record.handler.js +25 -4
  45. package/dist_ts/opsserver/handlers/domain.handler.js +37 -3
  46. package/dist_ts/opsserver/handlers/email-domain.handler.js +5 -7
  47. package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +1 -0
  48. package/dist_ts/opsserver/handlers/email-ops.handler.js +26 -7
  49. package/dist_ts/opsserver/handlers/index.d.ts +1 -0
  50. package/dist_ts/opsserver/handlers/index.js +2 -1
  51. package/dist_ts/opsserver/handlers/logs.handler.d.ts +1 -1
  52. package/dist_ts/opsserver/handlers/logs.handler.js +3 -3
  53. package/dist_ts/opsserver/handlers/realtime.handler.d.ts +37 -0
  54. package/dist_ts/opsserver/handlers/realtime.handler.js +154 -0
  55. package/dist_ts/opsserver/handlers/remoteingress.handler.js +22 -1
  56. package/dist_ts/opsserver/handlers/route-management.handler.js +47 -5
  57. package/dist_ts/opsserver/handlers/stats.handler.js +5 -1
  58. package/dist_ts/paths.d.ts +0 -11
  59. package/dist_ts/paths.js +1 -22
  60. package/dist_ts/plugins.d.ts +0 -34
  61. package/dist_ts/plugins.js +1 -62
  62. package/dist_ts_interfaces/data/email-domain.d.ts +14 -0
  63. package/dist_ts_interfaces/requests/config.d.ts +1 -1
  64. package/dist_ts_interfaces/requests/email-ops.d.ts +34 -1
  65. package/dist_ts_interfaces/requests/index.d.ts +1 -0
  66. package/dist_ts_interfaces/requests/index.js +2 -1
  67. package/dist_ts_interfaces/requests/realtime.d.ts +38 -0
  68. package/dist_ts_interfaces/requests/realtime.js +11 -0
  69. package/dist_ts_migrations/index.d.ts +6 -0
  70. package/dist_ts_migrations/index.js +208 -9
  71. package/dist_ts_web/00_commitinfo_data.js +1 -1
  72. package/dist_ts_web/appstate/certificates.js +9 -2
  73. package/dist_ts_web/appstate/domains.js +16 -5
  74. package/dist_ts_web/appstate/email-domains.d.ts +3 -0
  75. package/dist_ts_web/appstate/email-domains.js +47 -14
  76. package/dist_ts_web/appstate/email-ops.d.ts +1 -0
  77. package/dist_ts_web/appstate/email-ops.js +20 -2
  78. package/dist_ts_web/appstate/realtime.d.ts +27 -0
  79. package/dist_ts_web/appstate/realtime.js +71 -0
  80. package/dist_ts_web/appstate/remoteingress.js +9 -3
  81. package/dist_ts_web/appstate/routes.js +16 -5
  82. package/dist_ts_web/appstate/runtime.js +135 -7
  83. package/dist_ts_web/appstate.d.ts +1 -0
  84. package/dist_ts_web/appstate.js +2 -1
  85. package/dist_ts_web/elements/email/email-domain-creation-progress.d.ts +33 -0
  86. package/dist_ts_web/elements/email/email-domain-creation-progress.js +257 -0
  87. package/dist_ts_web/elements/email/ops-view-email-domains.js +233 -68
  88. package/dist_ts_web/elements/email/ops-view-emails.d.ts +4 -2
  89. package/dist_ts_web/elements/email/ops-view-emails.js +25 -13
  90. package/dist_ts_web/elements/overview/ops-view-config.js +5 -5
  91. package/package.json +22 -19
  92. package/ts/00_commitinfo_data.ts +1 -1
  93. package/ts/classes.dcrouter.ts +124 -57
  94. package/ts/db/classes.cache.cleaner.ts +18 -3
  95. package/ts/db/classes.dcrouter-db.ts +0 -2
  96. package/ts/db/documents/classes.cached.email.ts +78 -4
  97. package/ts/db/documents/classes.dns-record.doc.ts +1 -0
  98. package/ts/dns/classes.dns-server-runtime.ts +9 -45
  99. package/ts/dns/index.ts +1 -0
  100. package/ts/dns/manager.dns.ts +50 -16
  101. package/ts/dns/providers/cloudflare.provider.ts +21 -3
  102. package/ts/dns/txt-record-presentation.ts +134 -0
  103. package/ts/email/classes.accepted-email-spool.ts +220 -14
  104. package/ts/email/classes.email-domain.manager.ts +201 -7
  105. package/ts/email/classes.email-settings.manager.ts +1 -1
  106. package/ts/email/classes.mail-dns-sync.ts +588 -122
  107. package/ts/email/classes.smartmta-blob-storage-manager.ts +3 -2
  108. package/ts/email/classes.workapp-mail-manager.ts +34 -1
  109. package/ts/email/index.ts +2 -0
  110. package/ts/email/mail-dns-txt-policy.ts +505 -0
  111. package/ts/email/reconcile-mail-dns-singleton.ts +224 -0
  112. package/ts/opsserver/classes.opsserver.ts +42 -0
  113. package/ts/opsserver/handlers/certificate.handler.ts +24 -3
  114. package/ts/opsserver/handlers/config.handler.ts +9 -5
  115. package/ts/opsserver/handlers/dns-provider.handler.ts +18 -1
  116. package/ts/opsserver/handlers/dns-record.handler.ts +24 -3
  117. package/ts/opsserver/handlers/domain.handler.ts +36 -2
  118. package/ts/opsserver/handlers/email-domain.handler.ts +4 -5
  119. package/ts/opsserver/handlers/email-ops.handler.ts +29 -6
  120. package/ts/opsserver/handlers/index.ts +1 -0
  121. package/ts/opsserver/handlers/logs.handler.ts +2 -2
  122. package/ts/opsserver/handlers/realtime.handler.ts +222 -0
  123. package/ts/opsserver/handlers/remoteingress.handler.ts +21 -0
  124. package/ts/opsserver/handlers/route-management.handler.ts +46 -4
  125. package/ts/opsserver/handlers/stats.handler.ts +4 -0
  126. package/ts/paths.ts +0 -25
  127. package/ts/plugins.ts +0 -68
  128. package/ts_web/00_commitinfo_data.ts +1 -1
  129. package/ts_web/appstate/certificates.ts +6 -1
  130. package/ts_web/appstate/domains.ts +11 -4
  131. package/ts_web/appstate/email-domains.ts +68 -14
  132. package/ts_web/appstate/email-ops.ts +20 -1
  133. package/ts_web/appstate/realtime.ts +109 -0
  134. package/ts_web/appstate/remoteingress.ts +6 -2
  135. package/ts_web/appstate/routes.ts +11 -4
  136. package/ts_web/appstate/runtime.ts +176 -7
  137. package/ts_web/appstate.ts +1 -0
  138. package/ts_web/elements/email/email-domain-creation-progress.ts +340 -0
  139. package/ts_web/elements/email/ops-view-email-domains.ts +273 -74
  140. package/ts_web/elements/email/ops-view-emails.ts +23 -16
  141. package/ts_web/elements/overview/ops-view-config.ts +4 -4
@@ -0,0 +1,466 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { decodeTxtRecordContent } from '../dns/txt-record-presentation.js';
3
+ function intentKind(intent) {
4
+ const desired = intent.value.trim().toLowerCase();
5
+ if (desired.startsWith('v=spf1'))
6
+ return 'spf';
7
+ if (desired.startsWith('v=dmarc1'))
8
+ return 'dmarc';
9
+ if (desired.startsWith('v=dkim1'))
10
+ return 'dkim';
11
+ return 'exact';
12
+ }
13
+ function markerForKind(kind) {
14
+ if (kind === 'spf')
15
+ return 'v=spf1';
16
+ if (kind === 'dmarc')
17
+ return 'v=dmarc1';
18
+ if (kind === 'dkim')
19
+ return 'v=dkim1';
20
+ return undefined;
21
+ }
22
+ export function classifyMailTxtRecord(intent, rawValue) {
23
+ const kind = intentKind(intent);
24
+ const decoded = decodeTxtRecordContent(rawValue);
25
+ if (!decoded.ok) {
26
+ const marker = markerForKind(kind);
27
+ const rawNormalized = rawValue.trim().toLowerCase();
28
+ const plausiblyRelevant = kind === 'dkim'
29
+ ? rawNormalized.length > 0
30
+ : kind === 'dmarc'
31
+ ? /(?:^|;)\s*v=dmarc1(?:;|$)/.test(rawNormalized.replace(/^"/, ''))
32
+ : marker
33
+ ? rawNormalized.slice(0, marker.length + 4).includes(marker)
34
+ : rawValue.trim().startsWith('"');
35
+ return plausiblyRelevant
36
+ ? { relevant: true, malformed: decoded.error }
37
+ : { relevant: false };
38
+ }
39
+ const canonicalValue = decoded.value.trim();
40
+ const marker = markerForKind(kind);
41
+ const normalizedValue = canonicalValue.toLowerCase();
42
+ return {
43
+ relevant: kind === 'dkim'
44
+ ? canonicalValue.length > 0
45
+ : kind === 'dmarc'
46
+ ? /(?:^|;)\s*v=dmarc1(?:;|$)/.test(normalizedValue)
47
+ : marker
48
+ ? normalizedValue.startsWith(marker)
49
+ : canonicalValue === intent.value.trim(),
50
+ canonicalValue,
51
+ };
52
+ }
53
+ function ipv4Bytes(address) {
54
+ const parts = address.split('.');
55
+ if (parts.length !== 4)
56
+ return undefined;
57
+ const bytes = parts.map((part) => Number(part));
58
+ return bytes.every((part) => Number.isInteger(part) && part >= 0 && part <= 255)
59
+ ? bytes
60
+ : undefined;
61
+ }
62
+ function ipv6Bytes(address) {
63
+ let normalized = address.toLowerCase();
64
+ if (normalized.includes('.')) {
65
+ const lastColon = normalized.lastIndexOf(':');
66
+ const ipv4 = ipv4Bytes(normalized.slice(lastColon + 1));
67
+ if (lastColon < 0 || !ipv4)
68
+ return undefined;
69
+ normalized = `${normalized.slice(0, lastColon)}:${((ipv4[0] << 8) | ipv4[1]).toString(16)}:${((ipv4[2] << 8) | ipv4[3]).toString(16)}`;
70
+ }
71
+ const halves = normalized.split('::');
72
+ if (halves.length > 2)
73
+ return undefined;
74
+ const left = halves[0] ? halves[0].split(':') : [];
75
+ const right = halves[1] ? halves[1].split(':') : [];
76
+ const missing = 8 - left.length - right.length;
77
+ if ((halves.length === 1 && missing !== 0) || missing < 0)
78
+ return undefined;
79
+ const groups = [...left, ...Array.from({ length: missing }, () => '0'), ...right];
80
+ if (groups.length !== 8 || groups.some((group) => !/^[0-9a-f]{1,4}$/.test(group))) {
81
+ return undefined;
82
+ }
83
+ return groups.flatMap((group) => {
84
+ const value = Number.parseInt(group, 16);
85
+ return [value >> 8, value & 0xff];
86
+ });
87
+ }
88
+ function parseIpNetwork(value, family) {
89
+ const slashIndex = value.lastIndexOf('/');
90
+ const address = slashIndex >= 0 ? value.slice(0, slashIndex) : value;
91
+ const maximumPrefix = family === 4 ? 32 : 128;
92
+ const rawPrefix = slashIndex >= 0 ? value.slice(slashIndex + 1) : String(maximumPrefix);
93
+ if (!/^\d{1,3}$/.test(rawPrefix))
94
+ return undefined;
95
+ const prefixLength = Number.parseInt(rawPrefix, 10);
96
+ if (prefixLength < 0 || prefixLength > maximumPrefix)
97
+ return undefined;
98
+ const bytes = family === 4 ? ipv4Bytes(address) : ipv6Bytes(address);
99
+ return bytes ? { family, bytes, prefixLength } : undefined;
100
+ }
101
+ function networkContains(network, address) {
102
+ if (network.family !== address.family)
103
+ return false;
104
+ const wholeBytes = Math.floor(network.prefixLength / 8);
105
+ const remainingBits = network.prefixLength % 8;
106
+ for (let index = 0; index < wholeBytes; index++) {
107
+ if (network.bytes[index] !== address.bytes[index])
108
+ return false;
109
+ }
110
+ if (remainingBits === 0)
111
+ return true;
112
+ const mask = (0xff << (8 - remainingBits)) & 0xff;
113
+ return (network.bytes[wholeBytes] & mask) === (address.bytes[wholeBytes] & mask);
114
+ }
115
+ function parseAMechanism(body) {
116
+ let remaining = body.slice(1);
117
+ let ipv6PrefixLength = 128;
118
+ const doubleSlashIndex = remaining.lastIndexOf('//');
119
+ if (doubleSlashIndex >= 0) {
120
+ const value = remaining.slice(doubleSlashIndex + 2);
121
+ if (!/^\d{1,3}$/.test(value))
122
+ return undefined;
123
+ ipv6PrefixLength = Number.parseInt(value, 10);
124
+ remaining = remaining.slice(0, doubleSlashIndex);
125
+ }
126
+ let ipv4PrefixLength = 32;
127
+ const slashIndex = remaining.lastIndexOf('/');
128
+ if (slashIndex >= 0) {
129
+ const value = remaining.slice(slashIndex + 1);
130
+ if (!/^\d{1,2}$/.test(value))
131
+ return undefined;
132
+ ipv4PrefixLength = Number.parseInt(value, 10);
133
+ remaining = remaining.slice(0, slashIndex);
134
+ }
135
+ if (ipv4PrefixLength > 32 || ipv6PrefixLength > 128)
136
+ return undefined;
137
+ if (remaining && !remaining.startsWith(':'))
138
+ return undefined;
139
+ const domain = remaining.slice(1).trim().toLowerCase().replace(/\.$/, '');
140
+ if (domain.includes('%') || (domain && !/^[a-z0-9_.-]+$/.test(domain)))
141
+ return undefined;
142
+ return {
143
+ ...(domain ? { domain } : {}),
144
+ ipv4PrefixLength,
145
+ ipv6PrefixLength,
146
+ };
147
+ }
148
+ function parseSpfRecord(value) {
149
+ const terms = value.trim().split(/\s+/);
150
+ if (terms.shift()?.toLowerCase() !== 'v=spf1') {
151
+ return { error: 'SPF record must start with v=spf1' };
152
+ }
153
+ const parsed = { mechanisms: [], hasRedirect: false };
154
+ const modifiers = new Set();
155
+ for (const rawTerm of terms) {
156
+ if (!rawTerm)
157
+ continue;
158
+ let term = rawTerm;
159
+ let qualifier = '+';
160
+ let hadQualifier = false;
161
+ if (/^[+\-~?]/.test(term)) {
162
+ qualifier = term[0];
163
+ term = term.slice(1);
164
+ hadQualifier = true;
165
+ }
166
+ if (!term)
167
+ return { error: 'SPF contains an empty mechanism' };
168
+ const normalized = term.toLowerCase();
169
+ if (normalized.includes('=')) {
170
+ const match = term.match(/^([a-z][a-z0-9_.-]*)=(\S+)$/i);
171
+ if (hadQualifier || !match)
172
+ return { error: `SPF contains an invalid modifier: ${rawTerm}` };
173
+ const name = match[1].toLowerCase();
174
+ if (modifiers.has(name))
175
+ return { error: `SPF contains duplicate ${name} modifiers` };
176
+ modifiers.add(name);
177
+ if (name === 'redirect')
178
+ parsed.hasRedirect = true;
179
+ continue;
180
+ }
181
+ if (normalized.startsWith('ip4:') || normalized.startsWith('ip6:')) {
182
+ const family = normalized.startsWith('ip4:') ? 4 : 6;
183
+ const network = parseIpNetwork(term.slice(4), family);
184
+ if (!network)
185
+ return { error: `SPF contains an invalid ${family === 4 ? 'ip4' : 'ip6'} mechanism: ${rawTerm}` };
186
+ parsed.mechanisms.push({ kind: 'ip', qualifier, network });
187
+ continue;
188
+ }
189
+ if (normalized === 'a' || normalized.startsWith('a:') || normalized.startsWith('a/')) {
190
+ const mechanism = parseAMechanism(term);
191
+ if (!mechanism)
192
+ return { error: `SPF contains an invalid a mechanism: ${rawTerm}` };
193
+ parsed.mechanisms.push({ kind: 'a', qualifier, mechanism });
194
+ continue;
195
+ }
196
+ if (normalized === 'all') {
197
+ parsed.mechanisms.push({ kind: 'all', qualifier });
198
+ continue;
199
+ }
200
+ if (normalized === 'mx'
201
+ || normalized.startsWith('mx:')
202
+ || normalized.startsWith('mx/')
203
+ || normalized.startsWith('include:')
204
+ || normalized.startsWith('exists:')
205
+ || normalized === 'ptr'
206
+ || normalized.startsWith('ptr:')) {
207
+ parsed.mechanisms.push({ kind: 'unsupported', name: rawTerm });
208
+ continue;
209
+ }
210
+ return { error: `SPF contains an unknown mechanism: ${rawTerm}` };
211
+ }
212
+ return { parsed };
213
+ }
214
+ function desiredSpfAddresses(value) {
215
+ const parsed = parseSpfRecord(value);
216
+ if (!parsed.parsed)
217
+ return { error: parsed.error };
218
+ const addresses = [];
219
+ for (const mechanism of parsed.parsed.mechanisms) {
220
+ if (mechanism.kind === 'all' && mechanism.qualifier === '-')
221
+ continue;
222
+ if (mechanism.kind !== 'ip'
223
+ || mechanism.qualifier !== '+'
224
+ || mechanism.network.prefixLength !== (mechanism.network.family === 4 ? 32 : 128)) {
225
+ return { error: 'Desired SPF intent does not contain only concrete sender addresses' };
226
+ }
227
+ addresses.push(mechanism.network);
228
+ }
229
+ return addresses.length > 0
230
+ ? { addresses }
231
+ : { error: 'Desired SPF intent does not contain concrete sender addresses' };
232
+ }
233
+ async function withTimeout(promise, timeoutMs) {
234
+ let timer;
235
+ try {
236
+ return await Promise.race([
237
+ promise,
238
+ new Promise((_resolve, reject) => {
239
+ timer = setTimeout(() => reject(new Error(`DNS lookup timed out after ${timeoutMs}ms`)), timeoutMs);
240
+ }),
241
+ ]);
242
+ }
243
+ finally {
244
+ if (timer)
245
+ clearTimeout(timer);
246
+ }
247
+ }
248
+ async function evaluateSpf(intent, actualValue, options) {
249
+ const desired = desiredSpfAddresses(intent.value);
250
+ if (!desired.addresses)
251
+ return { outcome: 'invalid', reason: desired.error };
252
+ const actual = parseSpfRecord(actualValue);
253
+ if (!actual.parsed)
254
+ return { outcome: 'invalid', reason: actual.error };
255
+ const timeoutMs = Math.max(1, options.lookupTimeoutMs ?? 2_000);
256
+ const maxDnsLookups = Math.max(1, options.maxDnsLookups ?? 10);
257
+ let lookupCount = 0;
258
+ const cache = new Map();
259
+ const resolveBounded = async (name, type) => {
260
+ const key = `${type}:${name}`;
261
+ const cached = cache.get(key);
262
+ if (cached)
263
+ return await cached;
264
+ if (!options.resolveDns)
265
+ throw new Error('SPF a mechanism requires a DNS resolver');
266
+ if (lookupCount >= maxDnsLookups) {
267
+ throw new Error(`SPF DNS lookup budget of ${maxDnsLookups} was exceeded`);
268
+ }
269
+ lookupCount++;
270
+ const lookup = withTimeout(options.resolveDns(name, type), timeoutMs);
271
+ cache.set(key, lookup);
272
+ return await lookup;
273
+ };
274
+ try {
275
+ for (const address of desired.addresses) {
276
+ let authorized = false;
277
+ for (const mechanism of actual.parsed.mechanisms) {
278
+ if (mechanism.kind === 'unsupported') {
279
+ return {
280
+ outcome: 'conflict',
281
+ reason: `SPF authorization is indeterminate before a proven match: ${mechanism.name}`,
282
+ };
283
+ }
284
+ let matches = false;
285
+ if (mechanism.kind === 'ip') {
286
+ matches = networkContains(mechanism.network, address);
287
+ }
288
+ else if (mechanism.kind === 'a') {
289
+ const domain = mechanism.mechanism.domain || intent.name.toLowerCase().replace(/\.$/, '');
290
+ const type = address.family === 4 ? 'A' : 'AAAA';
291
+ const prefixLength = address.family === 4
292
+ ? mechanism.mechanism.ipv4PrefixLength
293
+ : mechanism.mechanism.ipv6PrefixLength;
294
+ for (const answer of await resolveBounded(domain, type)) {
295
+ const network = parseIpNetwork(`${answer}/${prefixLength}`, address.family);
296
+ if (network && networkContains(network, address)) {
297
+ matches = true;
298
+ break;
299
+ }
300
+ }
301
+ }
302
+ else {
303
+ matches = true;
304
+ }
305
+ if (!matches)
306
+ continue;
307
+ if (mechanism.qualifier !== '+') {
308
+ return {
309
+ outcome: 'conflict',
310
+ reason: `SPF first match for a desired edge has qualifier ${mechanism.qualifier}`,
311
+ };
312
+ }
313
+ authorized = true;
314
+ break;
315
+ }
316
+ if (!authorized) {
317
+ return {
318
+ outcome: 'conflict',
319
+ reason: actual.parsed.hasRedirect
320
+ ? 'SPF redirect is unsupported and authorization cannot be proven'
321
+ : 'SPF record does not authorize every desired mail edge address',
322
+ };
323
+ }
324
+ }
325
+ }
326
+ catch (error) {
327
+ return { outcome: 'lookup-error', reason: `SPF DNS lookup failed: ${error.message}` };
328
+ }
329
+ return { outcome: 'valid', effectiveValue: actualValue };
330
+ }
331
+ function parseDmarc(value) {
332
+ const orderedTags = [];
333
+ const seen = new Set();
334
+ for (const segment of value.split(';')) {
335
+ const trimmed = segment.trim();
336
+ if (!trimmed)
337
+ continue;
338
+ const equalsIndex = trimmed.indexOf('=');
339
+ if (equalsIndex <= 0)
340
+ return { error: `Malformed DMARC tag: ${trimmed}` };
341
+ const key = trimmed.slice(0, equalsIndex).trim().toLowerCase();
342
+ const tagValue = trimmed.slice(equalsIndex + 1).trim();
343
+ if (!key || !tagValue || seen.has(key))
344
+ return { error: `Invalid or duplicate DMARC tag: ${key}` };
345
+ seen.add(key);
346
+ orderedTags.push({ key, value: tagValue });
347
+ }
348
+ if (orderedTags[0]?.key !== 'v' || orderedTags[0].value !== 'DMARC1') {
349
+ return { error: 'DMARC v=DMARC1 must be the first tag' };
350
+ }
351
+ const tags = new Map(orderedTags.map((tag) => [tag.key, tag.value]));
352
+ const rawPolicy = tags.get('p')?.toLowerCase();
353
+ // Malformed optional tag values are ignored and locally defaulted. A missing
354
+ // or malformed p therefore has effective policy "none". pct and unknown
355
+ // extension tags do not change the policy-strength comparison.
356
+ const policy = rawPolicy === 'quarantine' || rawPolicy === 'reject' || rawPolicy === 'none'
357
+ ? rawPolicy
358
+ : 'none';
359
+ return { policy: { policy } };
360
+ }
361
+ function evaluateDmarc(intent, actualValue) {
362
+ const desired = parseDmarc(intent.value);
363
+ const actual = parseDmarc(actualValue);
364
+ if (!desired.policy)
365
+ return { outcome: 'invalid', reason: desired.error };
366
+ if (!actual.policy)
367
+ return { outcome: 'invalid', reason: actual.error };
368
+ const strength = { none: 0, quarantine: 1, reject: 2 };
369
+ if (strength[actual.policy.policy] < strength[desired.policy.policy]) {
370
+ return { outcome: 'conflict', reason: 'Operator DMARC policy is weaker than the desired policy' };
371
+ }
372
+ return { outcome: 'valid', effectiveValue: actualValue };
373
+ }
374
+ function decodeDkimPublicKey(value) {
375
+ const normalized = value.replace(/\s+/g, '');
376
+ if (!normalized || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized) || normalized.length % 4 !== 0) {
377
+ return undefined;
378
+ }
379
+ const decoded = plugins.buffer.Buffer.from(normalized, 'base64');
380
+ return decoded.toString('base64').replace(/=+$/, '') === normalized.replace(/=+$/, '')
381
+ ? decoded
382
+ : undefined;
383
+ }
384
+ function parseDkim(value) {
385
+ const tags = new Map();
386
+ for (const segment of value.split(';')) {
387
+ const trimmed = segment.trim();
388
+ if (!trimmed)
389
+ continue;
390
+ const equalsIndex = trimmed.indexOf('=');
391
+ if (equalsIndex <= 0)
392
+ return { error: `Malformed DKIM tag: ${trimmed}` };
393
+ const key = trimmed.slice(0, equalsIndex).trim().toLowerCase();
394
+ const tagValue = trimmed.slice(equalsIndex + 1).trim();
395
+ if (!/^[a-z][a-z0-9]*$/.test(key) || tags.has(key)) {
396
+ return { error: `Invalid or duplicate DKIM tag: ${key}` };
397
+ }
398
+ tags.set(key, tagValue);
399
+ }
400
+ if (tags.has('v') && tags.get('v') !== 'DKIM1') {
401
+ return { error: 'DKIM v must be DKIM1 when present' };
402
+ }
403
+ const publicKey = decodeDkimPublicKey(tags.get('p') || '');
404
+ if (!publicKey)
405
+ return { error: 'DKIM p must contain a valid non-empty base64 public key' };
406
+ const keyType = (tags.get('k') || 'rsa').toLowerCase();
407
+ const hashes = (tags.get('h') || 'sha256')
408
+ .split(':').map((entry) => entry.trim().toLowerCase()).filter(Boolean);
409
+ const services = (tags.get('s') || '*')
410
+ .split(':').map((entry) => entry.trim().toLowerCase()).filter(Boolean);
411
+ return { policy: { publicKey, keyType, hashes, services } };
412
+ }
413
+ function equalBytes(left, right) {
414
+ return left.length === right.length && left.every((value, index) => value === right[index]);
415
+ }
416
+ function evaluateDkim(intent, actualValue) {
417
+ const desired = parseDkim(intent.value);
418
+ const actual = parseDkim(actualValue);
419
+ if (!desired.policy)
420
+ return { outcome: 'invalid', reason: desired.error };
421
+ if (!actual.policy)
422
+ return { outcome: 'invalid', reason: actual.error };
423
+ if (actual.policy.keyType !== 'rsa') {
424
+ return { outcome: 'conflict', reason: 'DKIM k does not permit the required RSA key' };
425
+ }
426
+ if (!actual.policy.hashes.includes('sha256')) {
427
+ return { outcome: 'conflict', reason: 'DKIM h does not permit sha256' };
428
+ }
429
+ if (!actual.policy.services.some((service) => service === '*' || service === 'email')) {
430
+ return { outcome: 'conflict', reason: 'DKIM s does not permit email service' };
431
+ }
432
+ if (!equalBytes(actual.policy.publicKey, desired.policy.publicKey)) {
433
+ return { outcome: 'conflict', reason: `DKIM record at ${intent.name} contains a different public key` };
434
+ }
435
+ return { outcome: 'valid', effectiveValue: actualValue };
436
+ }
437
+ export async function evaluateMailTxtIntent(intent, rawValues, options = {}) {
438
+ const classified = rawValues
439
+ .map((value) => classifyMailTxtRecord(intent, value))
440
+ .filter((entry) => entry.relevant);
441
+ if (classified.length === 0) {
442
+ return { outcome: 'missing', reason: `${intent.type} ${intent.name} is missing` };
443
+ }
444
+ if (classified.length > 1) {
445
+ return { outcome: 'duplicate', reason: `${intent.name} has multiple relevant TXT records` };
446
+ }
447
+ const record = classified[0];
448
+ if (record.malformed || record.canonicalValue === undefined) {
449
+ return { outcome: 'invalid', reason: record.malformed || 'TXT record is malformed' };
450
+ }
451
+ const kind = intentKind(intent);
452
+ if (kind === 'spf')
453
+ return await evaluateSpf(intent, record.canonicalValue, options);
454
+ if (kind === 'dmarc')
455
+ return evaluateDmarc(intent, record.canonicalValue);
456
+ if (kind === 'dkim')
457
+ return evaluateDkim(intent, record.canonicalValue);
458
+ if (record.canonicalValue === intent.value.trim()) {
459
+ return { outcome: 'valid', effectiveValue: record.canonicalValue };
460
+ }
461
+ return {
462
+ outcome: 'conflict',
463
+ reason: `TXT record at ${intent.name} does not exactly match the desired value`,
464
+ };
465
+ }
466
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbC1kbnMtdHh0LXBvbGljeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2VtYWlsL21haWwtZG5zLXR4dC1wb2xpY3kudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUE4QzNFLFNBQVMsVUFBVSxDQUFDLE1BQTZCO0lBQy9DLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbEQsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQy9DLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUNuRCxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDakQsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLElBQWtCO0lBQ3ZDLElBQUksSUFBSSxLQUFLLEtBQUs7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUNwQyxJQUFJLElBQUksS0FBSyxPQUFPO1FBQUUsT0FBTyxVQUFVLENBQUM7SUFDeEMsSUFBSSxJQUFJLEtBQUssTUFBTTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ3RDLE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLE1BQTZCLEVBQzdCLFFBQWdCO0lBRWhCLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoQyxNQUFNLE9BQU8sR0FBRyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUs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QUksU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPLFNBQVMsQ0FBQztRQUM3QyxVQUFVLEdBQUcsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3pJLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RDLElBQUksTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDeEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDbkQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksT0FBTyxLQUFLLENBQUMsQ0FBQyxJQUFJLE9BQU8sR0FBRyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDNUUsTUFBTSxNQUFN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
@@ -0,0 +1,47 @@
1
+ import { DnsRecordDoc } from '../db/documents/classes.dns-record.doc.js';
2
+ import type { IEmailDnsRecordIntent } from '../../dist_ts_interfaces/data/email-domain.js';
3
+ import { type IMailDnsTxtPolicyResult } from './mail-dns-txt-policy.js';
4
+ export interface IMailDnsMutationClient {
5
+ createRecord(args: {
6
+ domainId: string;
7
+ name: string;
8
+ type: 'MX' | 'TXT' | 'A' | 'AAAA';
9
+ value: string;
10
+ ttl: number;
11
+ createdBy: string;
12
+ managedBy: string;
13
+ managedOwnerId: string;
14
+ managedRecordKey: string;
15
+ }): Promise<{
16
+ success: boolean;
17
+ id?: string;
18
+ message?: string;
19
+ }>;
20
+ updateRecord(args: {
21
+ id: string;
22
+ name?: string;
23
+ value?: string;
24
+ ttl?: number;
25
+ }): Promise<{
26
+ success: boolean;
27
+ message?: string;
28
+ }>;
29
+ deleteRecord(id: string): Promise<{
30
+ success: boolean;
31
+ message?: string;
32
+ }>;
33
+ }
34
+ export interface IReconcileMailDnsSingletonOptions {
35
+ intent: IEmailDnsRecordIntent;
36
+ rrset: DnsRecordDoc[];
37
+ dnsManager: IMailDnsMutationClient;
38
+ managedBy: string;
39
+ createdBy: string;
40
+ evaluate: (intent: IEmailDnsRecordIntent, values: string[]) => Promise<IMailDnsTxtPolicyResult>;
41
+ }
42
+ export declare function applyMailDnsVerificationResult(intent: IEmailDnsRecordIntent, result: IMailDnsTxtPolicyResult, phase: 'reconcile' | 'verify'): void;
43
+ /**
44
+ * Reconcile SPF, DMARC, and DKIM singleton TXT records without adopting or
45
+ * mutating operator policy. Returns false for non-singleton intents.
46
+ */
47
+ export declare function reconcileMailDnsSingleton(options: IReconcileMailDnsSingletonOptions): Promise<boolean>;