@push.rocks/smartdns 8.2.1 → 8.3.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/.smartconfig.json +10 -4
- package/dist_rust/rustdns-client_linux_amd64_musl +0 -0
- package/dist_rust/rustdns-client_linux_amd64_musl.tsrust-build.json +14 -0
- package/dist_rust/{rustdns-client_linux_arm64 → rustdns-client_linux_arm64_musl} +0 -0
- package/dist_rust/rustdns-client_linux_arm64_musl.tsrust-build.json +14 -0
- package/dist_rust/rustdns_linux_amd64_musl +0 -0
- package/dist_rust/rustdns_linux_amd64_musl.tsrust-build.json +14 -0
- package/dist_rust/rustdns_linux_arm64_musl +0 -0
- package/dist_rust/rustdns_linux_arm64_musl.tsrust-build.json +14 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_client/classes.rustdnsclientbridge.js +4 -1
- package/dist_ts_server/classes.dnsserver.d.ts +1 -1
- package/dist_ts_server/classes.dnsserver.js +2 -2
- package/dist_ts_server/classes.manageddnsserver.d.ts +34 -0
- package/dist_ts_server/classes.manageddnsserver.js +141 -0
- package/dist_ts_server/classes.rustdnsbridge.d.ts +31 -1
- package/dist_ts_server/classes.rustdnsbridge.js +34 -13
- package/dist_ts_server/index.d.ts +2 -0
- package/dist_ts_server/index.js +3 -1
- package/dist_ts_server/interfaces.managed.d.ts +79 -0
- package/dist_ts_server/interfaces.managed.js +2 -0
- package/notices/cargo-dependencies.html +3412 -0
- package/notices/cfg_aliases-0.2.1-license.txt +9 -0
- package/notices/cfg_aliases-0.2.1-notices.txt +26 -0
- package/notices/compiler-builtins-license.txt +275 -0
- package/notices/fiat-crypto-0.2.9-copyright.txt +7 -0
- package/notices/group-0.13.0-copyright.txt +14 -0
- package/notices/inventory.json +1290 -0
- package/notices/llvm-libunwind-license.txt +311 -0
- package/notices/lru-slab-0.1.2-license.txt +7 -0
- package/notices/musl-copyright.txt +193 -0
- package/notices/quinn-0.11.9-license.txt +7 -0
- package/notices/quinn-proto-0.11.13-license.txt +7 -0
- package/notices/quinn-udp-0.5.14-license.txt +7 -0
- package/notices/rand-0.8.5-copyright.txt +12 -0
- package/notices/rand-0.9.2-copyright.txt +12 -0
- package/notices/rand_chacha-0.3.1-copyright.txt +12 -0
- package/notices/rand_chacha-0.9.0-copyright.txt +12 -0
- package/notices/rand_core-0.6.4-copyright.txt +12 -0
- package/notices/rand_core-0.9.5-copyright.txt +12 -0
- package/notices/ring-0.17.14-fiat-license.txt +15 -0
- package/notices/ring-0.17.14-license-boringssl.txt +272 -0
- package/notices/ring-0.17.14-license-other-bits.txt +13 -0
- package/notices/ring-0.17.14-license.txt +9 -0
- package/notices/ring-0.17.14-once-cell-license-apache.txt +201 -0
- package/notices/ring-0.17.14-once-cell-license-mit.txt +23 -0
- package/notices/ring-0.17.14-source-attributions.txt +1544 -0
- package/notices/rust-standard-library.html +8266 -0
- package/notices/rustc-hash-2.1.1-license.txt +23 -0
- package/notices/thiserror-2.0.18-license.txt +23 -0
- package/notices/thiserror-impl-2.0.18-license.txt +23 -0
- package/notices/tinyvec-1.10.0-license.txt +5 -0
- package/notices/tinyvec_macros-0.1.1-license.txt +21 -0
- package/notices/utf8_iter-1.0.4-copyright.txt +42 -0
- package/notices/valuable-0.1.1-license.txt +25 -0
- package/notices/web-time-1.1.0-license.txt +21 -0
- package/notices/zerocopy-derive-0.8.39-license.txt +26 -0
- package/package.json +16 -6
- package/readme.md +172 -1
- package/third-party-notices.md +96 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/dist_rust/rustdns-client_linux_amd64 +0 -0
- package/dist_rust/rustdns-client_linux_amd64.tsrust-build.json +0 -14
- package/dist_rust/rustdns-client_linux_arm64.tsrust-build.json +0 -14
- package/dist_rust/rustdns_linux_amd64 +0 -0
- package/dist_rust/rustdns_linux_amd64.tsrust-build.json +0 -14
- package/dist_rust/rustdns_linux_arm64 +0 -0
- package/dist_rust/rustdns_linux_arm64.tsrust-build.json +0 -14
- package/readme.hints.md +0 -294
- /package/{license → license.md} +0 -0
package/readme.hints.md
DELETED
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
# smartdns - Implementation Hints
|
|
2
|
-
|
|
3
|
-
## Architecture Overview
|
|
4
|
-
|
|
5
|
-
The smartdns library is structured into three main modules:
|
|
6
|
-
|
|
7
|
-
1. **Client Module** (`ts_client/`) - DNS client functionality
|
|
8
|
-
2. **Server Module** (`ts_server/`) - DNS server with Rust backend
|
|
9
|
-
3. **Main Module** (`ts/`) - Re-exports both client and server
|
|
10
|
-
4. **Rust Module** (`rust/`) - High-performance DNS server binary
|
|
11
|
-
|
|
12
|
-
## Rust Backend Architecture (v8.0+)
|
|
13
|
-
|
|
14
|
-
The DNS server's default UDP, TCP, and HTTPS network I/O, packet
|
|
15
|
-
parsing/encoding, and DNSSEC signing run in Rust. TypeScript retains handler
|
|
16
|
-
registration, ACME orchestration, and the public API. `handleHttpSocket()` is
|
|
17
|
-
the deliberate manual-transport exception: after another component terminates
|
|
18
|
-
TLS, TypeScript bounds and parses HTTP/1.1 or prior-knowledge HTTP/2, then sends
|
|
19
|
-
the contained DNS packet to Rust for resolution and response construction.
|
|
20
|
-
|
|
21
|
-
### Rust Crate Structure
|
|
22
|
-
- `rustdns` - Main binary with IPC management loop (`--management` flag)
|
|
23
|
-
- `rustdns-protocol` - DNS wire format parsing/encoding, record types
|
|
24
|
-
- `rustdns-server` - Async UDP + HTTPS DoH servers (tokio, hyper, rustls)
|
|
25
|
-
- `rustdns-dnssec` - ECDSA P-256 / ED25519 key generation and RRset signing
|
|
26
|
-
|
|
27
|
-
### IPC Flow
|
|
28
|
-
```
|
|
29
|
-
DNS Query -> Rust (UDP/HTTPS) -> Parse packet
|
|
30
|
-
-> Try local resolution (localhost)
|
|
31
|
-
-> If handler needed: emit "dnsQuery" event to TypeScript
|
|
32
|
-
-> TypeScript runs minimatch handlers and authorizes DNSKEY, sends "dnsQueryResult" back
|
|
33
|
-
-> Rust builds response, signs DNSSEC if requested, sends packet
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Key Files
|
|
37
|
-
- `ts_server/classes.rustdnsbridge.ts` - TypeScript IPC bridge wrapping smartrust.RustBridge
|
|
38
|
-
- `ts_server/classes.dnsserver.ts` - DnsServer class (public API, delegates to Rust bridge)
|
|
39
|
-
- `rust/crates/rustdns/src/management.rs` - IPC management loop
|
|
40
|
-
- `rust/crates/rustdns/src/resolver.rs` - DNS resolver with callback support
|
|
41
|
-
|
|
42
|
-
## Client Module (Smartdns class)
|
|
43
|
-
|
|
44
|
-
### Key Features:
|
|
45
|
-
- DNS record queries (A, AAAA, TXT, MX, etc.)
|
|
46
|
-
- Support for multiple DNS providers (Google DNS, Cloudflare)
|
|
47
|
-
- DNS propagation checking with retry logic
|
|
48
|
-
- DNSSEC verification support
|
|
49
|
-
- Both HTTP-based (DoH) and Node.js DNS resolver fallback
|
|
50
|
-
|
|
51
|
-
### Implementation Details:
|
|
52
|
-
- Uses Cloudflare's DNS-over-HTTPS API as primary resolver
|
|
53
|
-
- Falls back to Node.js DNS module for local resolution
|
|
54
|
-
- Implements automatic retry logic with configurable intervals
|
|
55
|
-
- Properly handles quoted TXT records and trailing dots in domain names
|
|
56
|
-
|
|
57
|
-
### Key Methods:
|
|
58
|
-
- `getRecordsA()`, `getRecordsAAAA()`, `getRecordsTxt()` - Type-specific queries
|
|
59
|
-
- `getRecords()` - Generic record query with retry support
|
|
60
|
-
- `checkUntilAvailable()` - DNS propagation verification
|
|
61
|
-
- `getNameServers()` - NS record lookup
|
|
62
|
-
- `makeNodeProcessUseDnsProvider()` - Configure system DNS resolver
|
|
63
|
-
|
|
64
|
-
## Server Module (DnsServer class)
|
|
65
|
-
|
|
66
|
-
### Key Features:
|
|
67
|
-
- Full DNS server supporting UDP and HTTPS (DoH) protocols
|
|
68
|
-
- DNSSEC implementation with multiple algorithms
|
|
69
|
-
- Dynamic handler registration for custom responses
|
|
70
|
-
- Let's Encrypt integration for automatic SSL certificates
|
|
71
|
-
- Wildcard domain support with pattern matching
|
|
72
|
-
|
|
73
|
-
### DNSSEC Implementation:
|
|
74
|
-
- Supports ECDSA (algorithm 13), ED25519 (algorithm 15), and RSA (algorithm 8)
|
|
75
|
-
- Automatic DNSKEY and DS record generation
|
|
76
|
-
- RRSIG signature generation for authenticated responses
|
|
77
|
-
- Key tag computation following RFC 4034
|
|
78
|
-
|
|
79
|
-
### Let's Encrypt Integration:
|
|
80
|
-
- Automatic SSL certificate retrieval using DNS-01 challenges
|
|
81
|
-
- Dynamic TXT record handler registration for ACME validation
|
|
82
|
-
- Certificate renewal and HTTPS server restart capability
|
|
83
|
-
- Domain authorization filtering for security
|
|
84
|
-
|
|
85
|
-
### Handler System:
|
|
86
|
-
- Pattern-based domain matching using minimatch
|
|
87
|
-
- Support for all common record types
|
|
88
|
-
- **Multiple Handler Support**: As of v7.4.2+, multiple handlers can contribute records of the same type
|
|
89
|
-
- Handler chaining for complex scenarios
|
|
90
|
-
- Automatic SOA response for unhandled queries
|
|
91
|
-
|
|
92
|
-
### Multiple Records Support (v7.4.2+):
|
|
93
|
-
- Server now processes ALL matching handlers for a query (previously stopped after first match)
|
|
94
|
-
- Enables proper multi-NS record support for domain registration
|
|
95
|
-
- Supports round-robin DNS with multiple A/AAAA records
|
|
96
|
-
- Allows multiple TXT records (SPF, DKIM, domain verification)
|
|
97
|
-
- Each handler contributes its record to the response
|
|
98
|
-
|
|
99
|
-
## Key Dependencies
|
|
100
|
-
|
|
101
|
-
- `dns-packet`: DNS packet encoding/decoding (wire format, used by TS fallback path)
|
|
102
|
-
- `acme-client`: Let's Encrypt certificate automation
|
|
103
|
-
- `minimatch`: Glob pattern matching for domains
|
|
104
|
-
- `@push.rocks/smartrust`: TypeScript-to-Rust IPC bridge
|
|
105
|
-
- `@tsclass/tsclass`: Type definitions for DNS records
|
|
106
|
-
|
|
107
|
-
## Testing Insights
|
|
108
|
-
|
|
109
|
-
The test suite demonstrates:
|
|
110
|
-
- Mock ACME client for testing Let's Encrypt integration
|
|
111
|
-
- Self-signed certificate generation for HTTPS testing
|
|
112
|
-
- Unique port allocation to avoid conflicts
|
|
113
|
-
- Proper server cleanup between tests
|
|
114
|
-
- Both UDP and HTTPS query validation
|
|
115
|
-
|
|
116
|
-
## Common Patterns
|
|
117
|
-
|
|
118
|
-
1. **DNS Record Types**: Internally mapped to numeric values (A=1, AAAA=28, etc.)
|
|
119
|
-
2. **Error Handling**: Graceful fallback and retry mechanisms
|
|
120
|
-
3. **DNSSEC Workflow**: Zone → Key Generation → Signing → Verification
|
|
121
|
-
4. **Certificate Flow**: Domain validation → Challenge setup → Verification → Certificate retrieval
|
|
122
|
-
|
|
123
|
-
## Performance Considerations
|
|
124
|
-
|
|
125
|
-
- Client implements caching via DNS-over-HTTPS responses
|
|
126
|
-
- Server can handle concurrent UDP and HTTPS requests
|
|
127
|
-
- DNSSEC signing is performed on-demand for efficiency
|
|
128
|
-
- Handler registration is O(n) lookup but uses pattern caching
|
|
129
|
-
|
|
130
|
-
## Security Notes
|
|
131
|
-
|
|
132
|
-
- DNSSEC provides authentication but not encryption
|
|
133
|
-
- DoH (DNS-over-HTTPS) provides both privacy and integrity
|
|
134
|
-
- Let's Encrypt integration requires proper domain authorization
|
|
135
|
-
- Handler patterns should be carefully designed to avoid open resolvers
|
|
136
|
-
|
|
137
|
-
## Recent Improvements (v7.4.3)
|
|
138
|
-
|
|
139
|
-
1. **DNSSEC RRset Signing**: Fixed to properly sign entire RRsets together instead of individual records
|
|
140
|
-
2. **SOA Record Serialization**: Implemented proper SOA record encoding for DNSSEC compatibility
|
|
141
|
-
3. **Configurable Primary Nameserver**: Added `primaryNameserver` option to customize SOA mname field
|
|
142
|
-
|
|
143
|
-
## Recent Improvements (v7.4.8)
|
|
144
|
-
|
|
145
|
-
1. **MX Record DNSSEC Support**: Implemented MX record serialization for DNSSEC signing
|
|
146
|
-
- MX records consist of a 16-bit preference value followed by the exchange domain name
|
|
147
|
-
- Properly serializes both components for DNSSEC signature generation
|
|
148
|
-
- Enables mail exchange records to be authenticated with DNSSEC
|
|
149
|
-
|
|
150
|
-
## Authority Model (server)
|
|
151
|
-
|
|
152
|
-
Authority comes from **configuration**, never from the presence of a handler.
|
|
153
|
-
|
|
154
|
-
- `authoritativeZones` is the single source of truth for the `aa` bit. Omission
|
|
155
|
-
falls back to `[dnssecZone]`; an explicit empty array means no authority.
|
|
156
|
-
`setAuthoritativeZones()` validates and copies a replacement set synchronously,
|
|
157
|
-
so listeners stay up while subsequent queries see the new authority.
|
|
158
|
-
- DNSKEY queries for `dnssecZone` cross the TypeScript query callback before
|
|
159
|
-
Rust synthesizes the signed RRset. This keeps built-in DNSSEC answers inside
|
|
160
|
-
the same live authority boundary; an empty set cannot leak an authoritative
|
|
161
|
-
DNSKEY answer from the fixed Rust configuration.
|
|
162
|
-
- `registerHandler(pattern, types, handler, options?)` takes
|
|
163
|
-
`options.authority`:
|
|
164
|
-
- `'authoritative'` (default) — the handler only contributes for names inside
|
|
165
|
-
a configured zone. A match outside every zone is **suppressed**, not
|
|
166
|
-
answered, and reported on the `refused` event. A registration that cannot
|
|
167
|
-
match any configured zone also logs a warning once, at registration time.
|
|
168
|
-
- `'non-authoritative'` — the handler may answer any matching name, but the
|
|
169
|
-
response never carries `aa` and is never DNSSEC-signed. This is the mode
|
|
170
|
-
for split-horizon / private-route overlays.
|
|
171
|
-
- `aa` is a per-message flag, so a single non-authoritative contribution
|
|
172
|
-
downgrades the whole response.
|
|
173
|
-
|
|
174
|
-
Why this matters: before v8, registering a handler *was* the public claim of
|
|
175
|
-
authority. A private-route overlay registered for a domain delegated elsewhere
|
|
176
|
-
made the public nameserver answer with `aa` and an RFC1918 address, while
|
|
177
|
-
refusing every other query type for the same name. Both halves came from the
|
|
178
|
-
same defect — two disagreeing sources of truth.
|
|
179
|
-
|
|
180
|
-
### Response outcomes
|
|
181
|
-
|
|
182
|
-
`TDnsQueryResponseKind` maps one-to-one onto the wire:
|
|
183
|
-
|
|
184
|
-
| kind | rcode | `aa` | authority section |
|
|
185
|
-
| --- | --- | --- | --- |
|
|
186
|
-
| `answer` | 0 | yes | — |
|
|
187
|
-
| `nonAuthoritativeAnswer` | 0 | no | — |
|
|
188
|
-
| `authoritativeNegative` (NODATA) | 0 | yes | zone SOA |
|
|
189
|
-
| `authoritativeNameError` (NXDOMAIN) | 3 | yes | zone SOA |
|
|
190
|
-
| `refused` | 5 | no | — |
|
|
191
|
-
| `servfail` | 2 | no | — |
|
|
192
|
-
|
|
193
|
-
NXDOMAIN is only emitted when the name provably does not exist: no handler
|
|
194
|
-
pattern matches it for any type, it is not the apex of a configured zone, no
|
|
195
|
-
configured zone sits below it, and no handler pattern is anchored strictly
|
|
196
|
-
below it (literal `.name` suffix, or a wildcard that matches a probe label —
|
|
197
|
-
mid-label wildcards such as `x.*.example.com` are not fully inverted by this
|
|
198
|
-
check and can still leave an ancestor at NXDOMAIN). The apex always exists
|
|
199
|
-
(it answers its own SOA), and a name with covered descendants is an empty
|
|
200
|
-
non-terminal — both get NODATA, because NXDOMAIN denies the entire subtree
|
|
201
|
-
(RFC 8020) and a wrong one lets aggressive negative caching darken the zone.
|
|
202
|
-
A catch-all pattern such as `'*'` therefore suppresses NXDOMAIN entirely —
|
|
203
|
-
that is deliberate.
|
|
204
|
-
|
|
205
|
-
The zone apex answers its own SOA even with no registered SOA handler; an
|
|
206
|
-
authoritative server that cannot answer SOA for its own zone breaks negative
|
|
207
|
-
caching and resolver heuristics.
|
|
208
|
-
|
|
209
|
-
One deliberate exception to the table: RFC 6761 localhost handling (when
|
|
210
|
-
`enableLocalhostHandling` is on) answers `localhost` A/AAAA with `aa` set even
|
|
211
|
-
though `localhost` is outside every configured zone — special-use names are
|
|
212
|
-
authoritative by definition, not by delegation.
|
|
213
|
-
|
|
214
|
-
## Handler Lifecycle
|
|
215
|
-
|
|
216
|
-
- `registerHandler` returns an `IDnsHandlerRegistration` with a unique `id` and
|
|
217
|
-
an `unregister()` that removes **only** that registration.
|
|
218
|
-
- `unregisterHandlerById(id)` and `unregisterHandlersByOwner(owner)` are the
|
|
219
|
-
precise teardown primitives; `listHandlers()` exposes the current set for
|
|
220
|
-
leak checks.
|
|
221
|
-
- `unregisterHandler(pattern, types)` is retained and unchanged: it still
|
|
222
|
-
removes *every* handler matching that pattern/type pair. It cannot distinguish
|
|
223
|
-
two consumers sharing a key — prefer the handle.
|
|
224
|
-
- ACME authorization follows the same rule: `filterAuthorizedDomains` /
|
|
225
|
-
`retrieveSslCertificate` admit exactly the domains inside a configured
|
|
226
|
-
authoritative zone. Handler registrations play no part — a DNS-01 challenge
|
|
227
|
-
for an out-of-zone domain could never validate, because its challenge TXT
|
|
228
|
-
handler would be suppressed.
|
|
229
|
-
|
|
230
|
-
## Transport And Protocol Notes
|
|
231
|
-
|
|
232
|
-
- **EDNS0**: a request carrying an OPT record always gets an OPT back
|
|
233
|
-
(RFC 6891 6.1.1), advertising `DNS_ADVERTISED_UDP_PAYLOAD` (1232). Requests
|
|
234
|
-
without OPT get no OPT. Client-advertised payload sizes are clamped up to 512
|
|
235
|
-
so a hostile OPT cannot force pathological truncation.
|
|
236
|
-
- **Truncation**: UDP responses are truncated to the client's advertised payload
|
|
237
|
-
size with the TC bit set, so resolvers retry over TCP. Without this, oversized
|
|
238
|
-
datagrams were emitted and silently dropped by real networks. Truncation is
|
|
239
|
-
size arithmetic, never a re-encode per dropped record — the encoder does not
|
|
240
|
-
compress names, so record sizes are additive (`DnsPacket::encoded_len`).
|
|
241
|
-
`processRawDnsPacketAsync(packet, 'udp')` declares the same UDP bound for the
|
|
242
|
-
manual path (`handleUdpMessage` passes it automatically); without the hint no
|
|
243
|
-
size bound is applied, which is correct for TCP and DoH framing. Manual packet
|
|
244
|
-
work runs through a bounded task set so the management loop remains available
|
|
245
|
-
for handler callbacks and their results. The TypeScript bridge mirrors the
|
|
246
|
-
Rust task bound by admitting at most 256 pending `processPacket` requests;
|
|
247
|
-
excess requests fail before serialization with
|
|
248
|
-
`ERR_RUST_BRIDGE_REQUEST_LIMIT`, while control methods remain unbounded.
|
|
249
|
-
- **RA** is cleared on every path — this server never recurses.
|
|
250
|
-
- **RDATA validation** fails closed: a handler returning an unencodable value
|
|
251
|
-
(for example a non-IPv4 string for an A record) produces SERVFAIL and an error
|
|
252
|
-
log, rather than a malformed record on the wire.
|
|
253
|
-
- **SOA serial** is fixed for the lifetime of the server process and passed to
|
|
254
|
-
Rust via `soaSerial`, so apex answers and negative authorities agree.
|
|
255
|
-
|
|
256
|
-
## Observability
|
|
257
|
-
|
|
258
|
-
- `query` events carry `responseKind`, `authorityZone` and `suppressedHandlers`.
|
|
259
|
-
- `refused` events fire for every refusal and every suppressed handler match,
|
|
260
|
-
carrying the handler `id`, `domainPattern` and `owner`. Wire this up: the
|
|
261
|
-
original incident was invisible for weeks because nothing surfaced it.
|
|
262
|
-
|
|
263
|
-
## Server Lifecycle
|
|
264
|
-
|
|
265
|
-
- `start()` and `stop()` share a serialized lifecycle queue. Each caller keeps
|
|
266
|
-
its own operation result, and a rejection does not poison later operations.
|
|
267
|
-
- Repeated `start()` calls are idempotent at the `DnsServer` facade. Rust also
|
|
268
|
-
rejects duplicate active `start` commands, so low-level bridge callers cannot
|
|
269
|
-
replace listeners while detached HTTPS connection work still exists.
|
|
270
|
-
- `stop()` awaits confirmed Rust child closure before clearing ownership and
|
|
271
|
-
legacy server markers. A failed termination retains them so cleanup can be
|
|
272
|
-
retried safely.
|
|
273
|
-
- If an operation and confirmed cleanup both fail, both errors are preserved in
|
|
274
|
-
an `AggregateError`. A failed stop command is suppressed only after process
|
|
275
|
-
closure has been confirmed.
|
|
276
|
-
- A server may be started again after a confirmed stop; smartrust activates a
|
|
277
|
-
fresh process generation on the same bridge.
|
|
278
|
-
- Packet IPC is admitted only while no lifecycle operation is queued and the
|
|
279
|
-
facade state, ownership marker, and bridge liveness all agree. Certificate
|
|
280
|
-
updates use the same queue so they cannot race startup or shutdown.
|
|
281
|
-
|
|
282
|
-
## Known Limitations
|
|
283
|
-
|
|
284
|
-
1. **Handler Deduplication**: If the same handler is registered multiple times, it will contribute duplicate records (this may be desired behavior for some use cases)
|
|
285
|
-
2. **NXDOMAIN under catch-all patterns**: see the authority model above.
|
|
286
|
-
3. **SOA serial does not track zone changes** — it is a process-lifetime
|
|
287
|
-
constant, not a change counter. Secondaries driven by AXFR/IXFR are not
|
|
288
|
-
supported.
|
|
289
|
-
## Static Rust Binaries
|
|
290
|
-
|
|
291
|
-
- The Rust binaries in `dist_rust/` are statically linked (static-pie) via `"static": true` in the `@git.zone/tsrust` block of `.smartconfig.json` (tsrust >= 1.4.1). They run on both glibc (Debian/Ubuntu) and musl (Alpine) systems.
|
|
292
|
-
- tsrust injects `RUSTFLAGS="-C target-feature=+crt-static"` only into its own per-target cargo invocations and verifies the result (no `PT_INTERP` ELF header). Keep `rust/.cargo/config.toml` free of `rustflags` entries: the injected env variable would replace them, and a repo-wide `rustflags` would also break plain `cargo test`/`cargo check` (proc-macros cannot build with `+crt-static` on linux-gnu without an explicit `--target`).
|
|
293
|
-
- `pnpm run test:rust` runs the Rust unit tests; plain `cargo test` in `rust/` works as well.
|
|
294
|
-
- Verify linkage manually with `ldd dist_rust/<binary>_linux_amd64` → "statically linked".
|
/package/{license → license.md}
RENAMED
|
File without changes
|