@serve.zone/dcrouter 17.10.2 → 18.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 (84) hide show
  1. package/deno.json +1 -1
  2. package/dist_serve/bundle.js +360 -360
  3. package/dist_ts/00_commitinfo_data.js +2 -2
  4. package/dist_ts/acme/acme-failure-classification.d.ts +64 -0
  5. package/dist_ts/acme/acme-failure-classification.js +114 -0
  6. package/dist_ts/acme/classes.smartacme-lifecycle.d.ts +42 -0
  7. package/dist_ts/acme/classes.smartacme-lifecycle.js +75 -4
  8. package/dist_ts/acme/index.d.ts +1 -0
  9. package/dist_ts/acme/index.js +2 -1
  10. package/dist_ts/classes.dcrouter.d.ts +33 -9
  11. package/dist_ts/classes.dcrouter.js +145 -11
  12. package/dist_ts/config/classes.route-config-manager.d.ts +56 -0
  13. package/dist_ts/config/classes.route-config-manager.js +161 -1
  14. package/dist_ts/db/documents/classes.dns-authority.doc.d.ts +30 -0
  15. package/dist_ts/db/documents/classes.dns-authority.doc.js +108 -0
  16. package/dist_ts/db/documents/index.d.ts +1 -0
  17. package/dist_ts/db/documents/index.js +2 -1
  18. package/dist_ts/dns/classes.dns-server-runtime.d.ts +109 -1
  19. package/dist_ts/dns/classes.dns-server-runtime.js +212 -34
  20. package/dist_ts/dns/domain-ownership.d.ts +111 -0
  21. package/dist_ts/dns/domain-ownership.js +152 -0
  22. package/dist_ts/dns/index.d.ts +2 -0
  23. package/dist_ts/dns/index.js +3 -1
  24. package/dist_ts/dns/manager.dns-authority.d.ts +143 -0
  25. package/dist_ts/dns/manager.dns-authority.js +481 -0
  26. package/dist_ts/dns/manager.dns.d.ts +121 -12
  27. package/dist_ts/dns/manager.dns.js +298 -28
  28. package/dist_ts/errors/error.codes.d.ts +4 -0
  29. package/dist_ts/errors/error.codes.js +5 -1
  30. package/dist_ts/opsserver/classes.opsserver.d.ts +1 -0
  31. package/dist_ts/opsserver/classes.opsserver.js +3 -1
  32. package/dist_ts/opsserver/handlers/acme-config.handler.js +6 -1
  33. package/dist_ts/opsserver/handlers/certificate.handler.d.ts +16 -0
  34. package/dist_ts/opsserver/handlers/certificate.handler.js +96 -10
  35. package/dist_ts/opsserver/handlers/config.handler.js +4 -2
  36. package/dist_ts/opsserver/handlers/dns-authority.handler.d.ts +20 -0
  37. package/dist_ts/opsserver/handlers/dns-authority.handler.js +108 -0
  38. package/dist_ts/opsserver/handlers/dns-provider.handler.js +5 -1
  39. package/dist_ts/opsserver/handlers/domain.handler.js +9 -1
  40. package/dist_ts/opsserver/handlers/gatewayclient.handler.js +2 -2
  41. package/dist_ts/opsserver/handlers/index.d.ts +1 -0
  42. package/dist_ts/opsserver/handlers/index.js +2 -1
  43. package/dist_ts_interfaces/data/dns-authority.d.ts +98 -0
  44. package/dist_ts_interfaces/data/dns-authority.js +26 -0
  45. package/dist_ts_interfaces/data/index.d.ts +1 -0
  46. package/dist_ts_interfaces/data/index.js +2 -1
  47. package/dist_ts_interfaces/data/route-management.d.ts +9 -2
  48. package/dist_ts_interfaces/data/route-management.js +3 -1
  49. package/dist_ts_interfaces/requests/certificate.d.ts +23 -0
  50. package/dist_ts_interfaces/requests/certificate.js +1 -1
  51. package/dist_ts_interfaces/requests/dns-authority.d.ts +80 -0
  52. package/dist_ts_interfaces/requests/dns-authority.js +3 -0
  53. package/dist_ts_interfaces/requests/index.d.ts +1 -0
  54. package/dist_ts_interfaces/requests/index.js +2 -1
  55. package/dist_ts_oci_container/index.js +9 -4
  56. package/dist_ts_web/00_commitinfo_data.js +2 -2
  57. package/package.json +1 -1
  58. package/readme.hints.md +412 -0
  59. package/readme.md +48 -6
  60. package/ts/00_commitinfo_data.ts +1 -1
  61. package/ts/acme/acme-failure-classification.ts +201 -0
  62. package/ts/acme/classes.smartacme-lifecycle.ts +104 -3
  63. package/ts/acme/index.ts +1 -0
  64. package/ts/classes.dcrouter.ts +193 -23
  65. package/ts/config/classes.route-config-manager.ts +197 -0
  66. package/ts/db/documents/classes.dns-authority.doc.ts +49 -0
  67. package/ts/db/documents/index.ts +1 -0
  68. package/ts/dns/classes.dns-server-runtime.ts +257 -38
  69. package/ts/dns/domain-ownership.ts +272 -0
  70. package/ts/dns/index.ts +2 -0
  71. package/ts/dns/manager.dns-authority.ts +558 -0
  72. package/ts/dns/manager.dns.ts +373 -27
  73. package/ts/errors/error.codes.ts +4 -0
  74. package/ts/opsserver/classes.opsserver.ts +2 -0
  75. package/ts/opsserver/handlers/acme-config.handler.ts +7 -0
  76. package/ts/opsserver/handlers/certificate.handler.ts +103 -8
  77. package/ts/opsserver/handlers/config.handler.ts +3 -1
  78. package/ts/opsserver/handlers/dns-authority.handler.ts +142 -0
  79. package/ts/opsserver/handlers/dns-provider.handler.ts +6 -0
  80. package/ts/opsserver/handlers/domain.handler.ts +12 -0
  81. package/ts/opsserver/handlers/gatewayclient.handler.ts +1 -1
  82. package/ts/opsserver/handlers/index.ts +1 -0
  83. package/ts/readme.md +1 -1
  84. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -4,6 +4,22 @@ import type { IDcRouterOptions } from '../classes.dcrouter.js';
4
4
  import type { IDnsProviderClient } from './providers/interfaces.js';
5
5
  import type { TDnsRecordType, TDnsRecordSource } from '../../dist_ts_interfaces/data/dns-record.js';
6
6
  import type { TDnsProviderType, TDnsProviderCredentials, IDnsProviderPublic, IProviderDomainListing } from '../../dist_ts_interfaces/data/dns-provider.js';
7
+ import { type IDomainOwnershipZone, type TDomainOwnership } from './domain-ownership.js';
8
+ /**
9
+ * Where a runtime DnsServer handler came from.
10
+ *
11
+ * - 'persisted' → rebuilt from a DnsRecordDoc row.
12
+ * - 'generated-default' → synthesised by dcrouter (apex NS today; SOA and other
13
+ * zone defaults would join this origin), so it has no DB row to enumerate and
14
+ * must be torn down from the registry.
15
+ */
16
+ export type TDnsRuntimeRegistrationOrigin = 'persisted' | 'generated-default';
17
+ /** One runtime DnsServer handler key owned by a DomainDoc. */
18
+ export interface IDnsRuntimeRegistration {
19
+ name: string;
20
+ type: TDnsRecordType;
21
+ origin: TDnsRuntimeRegistrationOrigin;
22
+ }
7
23
  /**
8
24
  * DnsManager — owns runtime DNS state on top of the embedded DnsServer.
9
25
  *
@@ -22,7 +38,7 @@ export declare class DnsManager {
22
38
  private options;
23
39
  /**
24
40
  * Reference to the active smartdns DnsServer (set by DcRouter once it exists).
25
- * May be undefined if dnsScopes/dnsNsDomains aren't configured.
41
+ * May be undefined if dnsNsDomains isn't configured.
26
42
  */
27
43
  dnsServer?: plugins.smartdns.dnsServerMod.DnsServer;
28
44
  /**
@@ -30,7 +46,39 @@ export declare class DnsManager {
30
46
  * Created lazily when a provider is first needed.
31
47
  */
32
48
  private providerClients;
49
+ /**
50
+ * Per-domain registry of the runtime DnsServer handlers this manager owns,
51
+ * keyed by DomainDoc.id then by `name|type`.
52
+ *
53
+ * Teardown must remove exactly what registration added — no more, no less.
54
+ * smartdns' `unregisterHandler(pattern, types)` removes *every* handler for a
55
+ * pattern/type pair, including the nameserver glue handlers owned by
56
+ * DnsServerRuntime and the global wildcard A handler. Reconstructing "would I
57
+ * have registered this?" at delete time is therefore unsafe: any drift in the
58
+ * inputs (authority changed, ownership changed, a record row vanished) makes the
59
+ * reconstruction tear down another owner's handlers or miss its own. Recording
60
+ * the actual registrations, with their origin, removes that class of bug.
61
+ */
62
+ private runtimeRegistrations;
63
+ /** Supplies the effective authority set (bootstrap ∪ delegation-verified). */
64
+ private authorityZonesResolver?;
33
65
  constructor(options: IDcRouterOptions);
66
+ private trackRuntimeRegistration;
67
+ private untrackRuntimeRegistration;
68
+ /** Registrations currently owned by a domain. Exposed for teardown assertions. */
69
+ listRuntimeRegistrations(domainId: string): IDnsRuntimeRegistration[];
70
+ /**
71
+ * Unregister every runtime handler owned by a domain and forget them.
72
+ *
73
+ * Called from every path that ends dcrouter's authority over a zone. Without
74
+ * it, deleting a DomainDoc removed the DB source of truth (so record queries
75
+ * started answering REFUSED) while the generated apex NS handler kept answering
76
+ * `aa` with our nameservers until the process was restarted — stale authority
77
+ * live in memory, with nothing telling the next operator to restart. A restart
78
+ * is not an acceptable delete procedure: it costs 30–60 s of total public
79
+ * outage.
80
+ */
81
+ private tearDownDomainRuntimeRegistrations;
34
82
  start(): Promise<void>;
35
83
  stop(): Promise<void>;
36
84
  /**
@@ -46,19 +94,72 @@ export declare class DnsManager {
46
94
  private applyDcrouterDomainsToDnsServer;
47
95
  /**
48
96
  * Authoritative zones must answer apex NS queries or their delegation is
49
- * lame — Let's Encrypt's DNS-01 resolver SERVFAILs on such zones. Static
50
- * dnsScopes zones get NS records in DnsServerRuntime; zones registered in
51
- * the DB get them here, served from options.dnsNsDomains unless explicit
52
- * apex NS records exist in the DB.
97
+ * lame — Let's Encrypt's DNS-01 resolver SERVFAILs on such zones. This is the
98
+ * only place generated apex NS records come from, for every authoritative
99
+ * zone: they are served from options.dnsNsDomains unless explicit apex NS
100
+ * records exist in the DB. DnsServerRuntime used to emit a static set for
101
+ * bootstrap `dnsScopes` zones, which could neither appear for a zone verified
102
+ * after startup nor disappear for one whose authority was revoked.
103
+ *
104
+ * Ownership is verified first. smartdns marks any answer a registered handler
105
+ * produces as authoritative (`aa`) regardless of `authoritativeZones`, so
106
+ * registering this handler for a zone we cannot prove we own makes dcrouter
107
+ * publicly claim authority over somebody else's domain.
53
108
  */
54
109
  private registerAuthoritativeZoneDefaults;
110
+ /** Ownership inputs for every managed zone, fetched once per evaluation pass. */
111
+ listOwnershipZones(): Promise<IDomainOwnershipZone[]>;
112
+ /**
113
+ * The authority set used as an ownership proof: the delegation-verified zones
114
+ * held in the database, and nothing else. Empty until the resolver is wired,
115
+ * which fails closed — an unwired manager proves ownership of nothing rather
116
+ * than falling back to a declared list that no longer exists.
117
+ */
118
+ getAuthorityZones(): string[];
119
+ /**
120
+ * Supply the effective authority set. Injected rather than imported so
121
+ * DnsManager keeps a single direction of dependency and stays unit-testable.
122
+ */
123
+ setAuthorityZonesResolver(resolver?: () => string[]): void;
124
+ /**
125
+ * Re-derive every generated apex NS registration against the current authority
126
+ * set. Zones that gained proof start being served; zones that lost it are torn
127
+ * down — both in-process, with no restart.
128
+ *
129
+ * Throws on the first failure so the caller can roll the change back rather
130
+ * than leave the router half-converted.
131
+ */
132
+ reconcileAuthoritativeZones(): Promise<{
133
+ registered: string[];
134
+ unregistered: string[];
135
+ }>;
136
+ /** Keep `DomainDoc.authoritative` honest after an authority change. */
137
+ syncAuthoritativeFlags(): Promise<number>;
138
+ /**
139
+ * Can we prove the zone containing `fqdn` is ours? This gates certificate
140
+ * requirements and authoritative DNS. See ts/dns/domain-ownership.ts.
141
+ */
142
+ resolveDomainOwnership(fqdn: string): Promise<TDomainOwnership>;
143
+ /**
144
+ * Ownership of a zone that is about to become dcrouter-hosted, evaluated
145
+ * against its post-write shape. Create and provider→dcrouter migration must
146
+ * not read their own pre-write row: the provider link they are removing would
147
+ * otherwise still count as the proof.
148
+ */
149
+ private resolveOwnershipForPendingDcrouterZone;
55
150
  /**
56
151
  * Register a single record with the embedded DnsServer. The handler closure
57
152
  * captures the record fields, so updates require a re-register cycle.
58
153
  */
59
154
  private registerRecordWithDnsServer;
60
155
  private rrsetKey;
61
- /** Rebuild one authoritative RRset atomically from persisted rows. */
156
+ /**
157
+ * Rebuild one authoritative RRset atomically from persisted rows.
158
+ *
159
+ * The unregister-then-rebuild cycle also replaces a generated default on the
160
+ * same key (an explicit apex NS row supersedes the generated one), so the
161
+ * registry is updated to match what is actually registered afterwards.
162
+ */
62
163
  private refreshLocalRrset;
63
164
  private parseRecordData;
64
165
  /**
@@ -127,8 +228,14 @@ export declare class DnsManager {
127
228
  listDomains(): Promise<DomainDoc[]>;
128
229
  getDomain(id: string): Promise<DomainDoc | null>;
129
230
  /**
130
- * Create a dcrouter-hosted (authoritative) domain. dcrouter will serve
131
- * DNS records for this domain via the embedded smartdns.DnsServer.
231
+ * Create a dcrouter-hosted domain. dcrouter serves DNS records for it via the
232
+ * embedded smartdns.DnsServer.
233
+ *
234
+ * `authoritative` reflects whether ownership can actually be proven — it used
235
+ * to be hard-coded to `true`, which let an ops-API caller self-assert authority
236
+ * over any zone on the internet. Creating the record still succeeds (it is the
237
+ * container records and provider migration need), but an unverified zone is
238
+ * recorded as non-authoritative and gets no generated apex NS handler.
132
239
  */
133
240
  createDcrouterDomain(args: {
134
241
  name: string;
@@ -153,10 +260,12 @@ export declare class DnsManager {
153
260
  * For dcrouter-hosted domains, also unregisters records from the embedded
154
261
  * DnsServer.
155
262
  *
156
- * Note: smartdns has no public unregister-by-name API in the version pinned
157
- * here, so local record deletes only take effect after a restart. The DB
158
- * is the source of truth and the next start will not register the deleted
159
- * record.
263
+ * The unregister path is complete in-process: every runtime handler this
264
+ * manager registered for the domain — persisted RRsets and generated defaults
265
+ * alike — is removed from the registry, so deletion never leaves stale
266
+ * authority answering `aa` until an unrelated restart. Nameserver glue
267
+ * handlers and other domains' handlers are never touched, because only the
268
+ * domain's own recorded registrations are removed.
160
269
  */
161
270
  deleteDomain(id: string): Promise<boolean>;
162
271
  /**