2026-09-15 - 2026-10-15
Overview
2 Releases published by 1 user
Published
v1.0.0-rc2
Published
v1.0.0-rc1
77 Pull requests merged by 1 user
Merged
#290 watcher: a hostname whose zone's nameservers all stop answering gets NS Failure (closes #284)
Merged
#282 watcher: an IPv6 address is written in brackets before its port (closes #270)
Merged
#283 docs: TODO.md names only open issues as next steps (closes #281)
Merged
#280 watcher: a port check that finds 443 closed removes its certificate entries (closes #265)
Merged
#278 state: a state file without a section loads it empty (closes #267)
Merged
#279 watcher: a stop during the first scan sends no startup notification (closes #271)
Merged
#273 watcher: a removed nameserver is an NS Change, not an NS Failure (closes #262)
Merged
#277 config: a metrics username without a password stops startup (closes #268)
Merged
#276 state: Save syncs the state file before renaming it into place (closes #264)
Merged
#275 server: a port that cannot be bound stops startup (closes #266)
Merged
#274 config: a bad number or true/false setting stops startup (closes #269)
Merged
#272 state: GetSnapshot copies the state's maps (closes #261)
Merged
#259 build: re-vendor canonical files from prompts dd4027b (closes #257)
Merged
#258 watcher, config: no Record Change or Inconsistency for listed names (closes #255)
Merged
#254 resolver: a nameserver with a failed record type is not nodata (closes #253)
Merged
#250 resolver, watcher: a domain's nameservers are only its own delegation (closes #222)
Merged
#252 resolver: the refused-query test asks several operators, one query each (closes #251)
Merged
#246 watcher: a name removed from the targets leaves the state (closes #223)
Merged
#234 resolver, watcher: a record type whose query fails keeps its previous records (closes #231)
Merged
#249 watcher: Port Change notifications list domains apart from hostnames (closes #248)
Merged
#247 dashboard and status API list a port's domains apart from its hostnames (closes #245)
Merged
#242 resolver: ask a referral's nameservers that come without addresses (closes #221)
Merged
#244 dashboard, status API and notifications tell apex domains from hostnames (closes #224)
Merged
#243 dashboard: list record types in the README's order (closes #226)
Merged
#235 dashboard and status API show why a check failed (closes #225)
Merged
#236 resolver: store a name's CNAME once per nameserver (closes #220)
Merged
#237 watcher: a lookup cut short by shutdown is not logged as an error (closes #229)
Merged
#238 watcher: change messages name only the record types that differ (closes #219)
Merged
#241 watcher: startup notification no longer says every endpoint works (closes #230)
Merged
#240 notify: a failed Mattermost delivery's error names Mattermost
Merged
#239 log: write durations as text, not nanoseconds (closes #228)
Merged
#209 watcher: follow a watched name's CNAME for port and TLS checks (closes #203)
Merged
#232 resolver tests: retry an answer missing the record type read (closes #218)
Merged
#213 docker: a plain docker build . stamps the git version (closes #210)
Merged
#212 resolver: never resend a refused query asking for recursion (closes #206)
Merged
#217 ci: a push cancels its branch's older run, checkout keeps no token (closes #216)
Merged
#215 watcher tests: far fewer live queries, longer live attempts (closes #214)
Merged
#199 resolver: try servers in a random order on each resolution (closes #138)
Merged
#205 README: correct claims the code does not bear out (closes #108)
Merged
#211 config: watch a target listed twice only once (closes #207)
Merged
#208 watcher: warn of an expiring certificate on every TLS check (closes #204)
Merged
#202 resolver: take a domain's NS set from its delegation (closes #200)
Merged
#198 docs: add the README sections policy requires (closes #173)
Merged
#201 resolver: pass over a server that answers SERVFAIL or refers no closer (closes #197)
Merged
#195 watcher: keep port state when no nameserver of a name answered (closes #193)
Merged
#194 resolver: error from ResolveIPAddresses when no nameserver answered (closes #190)
Merged
#196 fmt: format and check Markdown with prettier in a container (closes #119)
Merged
#192 fmt: check goimports in fmt-check, run it at its pinned commit (#119)
Merged
#191 resolver: query a hostname at its own zone's servers (closes #189)
Merged
#187 watcher: notify nameserver address changes (closes #105)
Merged
#186 watcher: save state when it stops and wait for that save (closes #114)
Merged
#184 server: report HTTP handler panics to Sentry (closes #107)
Merged
#188 watcher: save and notify nothing for a cut-short port or TLS check (closes #185)
Merged
#183 middleware: take the client address from the right of X-Forwarded-For (closes #181)
Merged
#175 watcher: notify NS query failure and recovery (closes #104)
Merged
#178 config: stop startup on an invalid DNS or TLS interval
Merged
#180 metrics: rate limit /metrics per client address before Basic Auth (closes #101)
Merged
#182 docker: report the real version in the image (closes #109)
Merged
#179 notify: release held deliveries so shutdown tests fail, not hang (closes #176)
Merged
#170 script/install-precommit: work where .git is a file (closes #129)
Merged
#171 docs: bring TODO.md up to date (closes #146)
Merged
#167 docker: set up the data directory in an entrypoint (closes #166)
Merged
#172 server: limit wildcard CORS to the public routes (closes #100)
Merged
#169 Move the test-only constructors into export_test.go (closes #111)
Merged
#174 notify: make the shutdown tests fail with the right message (closes #116)
Merged
#165 tests: rename internal/livedns to livednstest and deny it outside tests
Merged
#163 golangci: re-vendor the org config with gomodguard_v2
Merged
#162 tests: remove the DNS stand-ins from the watcher and resolver tests
Merged
#161 watcher: send the inconsistency alert once per disagreement
Merged
#160 resolver: lower-case DNS names in record values (closes #157)
Merged
#155 script: force lint and test to run in cibuild and docker
Merged
#153 server: assert timeouts on the served http.Server, not just the constructor
Merged
#156 docker: run as non-root, add health check, document upaas
Merged
#112 feat: add security response headers middleware (closes #98)
Merged
#154 Add tests for globals, healthcheck, and logger packages
Merged
#150 gomod: drop stale golang.org/x/sync indirect line
Merged
#151 Merge main into next to restore ancestry (resolve TODO.md)
2 Pull requests proposed by 1 user
Proposed
#152 next
Proposed
#291 A nameserver is asked at each of its addresses in turn
91 Issues closed from 1 user
Closed
#284 A hostname whose zone's nameservers all stop answering gets no NS Failure notification
Closed
#270 An IPv6 address joined with its port, as in a Port Change notification, cannot be told from the port
Closed
#281 TODO.md names closed issues as its next and future steps
Closed
#265 A certificate entry stays ok after its port 443 closes
Closed
#267 A state file holding {} crashes the watcher on its first check
Closed
#271 The startup notification says the initial scan completed when shutdown cut it short
Closed
#262 A nameserver removed from a domain's delegation is also reported as an NS Failure
Closed
#268 /metrics is served with an empty password when only DNSWATCHER_METRICS_USERNAME is set
Closed
#264 The state file is renamed into place without being synced, so a crash can leave it empty and stop the next start
Closed
#266 dnswatcher keeps running without its HTTP server when the listen port is in use
Closed
#269 A setting that is not a valid number or true/false is read as 0 or false instead of stopping startup
Closed
#261 The dashboard and /api/v1/status iterate the state's live maps without the lock, which can crash the process
Closed
#260 Defect hunt before the release candidate: a trial run of next and a read of its code paths
Closed
#263 A non-numeric DNSWATCHER_TLS_EXPIRY_WARNING or PORT is silently read as 0
Closed
#257 Re-vendor the canonical files from sneak/prompts at dd4027b
Closed
#255 Let an admin turn off Record Change and Inconsistency notifications for one name
Closed
#256 Let an admin turn off the record-change notification for one host
Closed
#233 OWNER: names whose nameservers rotate their answers notify on every check
Closed
#144 Review toward 1.0: identify and file all next steps
Closed
#253 A nameserver whose A query got no reply is reported nodata when its other answers were empty
Closed
#222 A name gets a parent zone's nameservers when finding its own fails: a domain that does not exist shows the .com servers
Closed
#251 Red next: the Quad9 refusal test needs all eight of its queries answered at once
Closed
#223 Targets removed from DNSWATCHER_TARGETS stay on the dashboard, in /api/v1/status and in the startup counts
Closed
#231 One lost query saves a nameserver's records with that type missing, and notifies a change
Closed
#248 Port Change notifications list apex domains as hosts
Closed
#245 The dashboard Ports table lists an apex domain as a hostname
Closed
#221 Nameservers that a referral names without addresses are not looked up, so pool.ntp.org cannot be watched
Closed
#224 Apex domains are counted, listed and notified as hostnames
Closed
#226 The dashboard lists each nameserver's records in a random order of record type
Closed
#225 The dashboard and /api/v1/status do not say why a nameserver or certificate check failed
Closed
#220 A hostname's CNAME is stored once for every record type asked for, eight copies in all
Closed
#229 A DNS lookup cut short by shutdown is logged as an error
Closed
#219 Record Change and Inconsistency notifications print every record type in Go map syntax instead of what changed
Closed
#230 The startup notification says all notification channels are working before any delivery is known
Closed
#227 A failed Mattermost delivery is logged as "slack notification failed"
Closed
#228 Durations in the log are bare nanosecond counts
Closed
#203 A watched name whose CNAME points into another zone gets no port or TLS checks
Closed
#218 Resolver tests for AAAA and MX records fail when one query is lost
Closed
#149 Trial run of the finished image against real targets before tagging 1.0
Closed
#210 docker build . stamps dev, not the git tag or short commit
Closed
#206 A query a server refuses is resent asking for recursion, so answers can come from a recursive resolver
Closed
#216 CI runs every pushed head, even after a newer push to the same branch has replaced it
Closed
#214 next is red in CI: watcher tests time out since nameserver addresses are looked up on each domain check
Closed
#138 queryServers always tries servers in fixed order, so every resolution starts at a.root-servers.net
Closed
#108 README accuracy sweep: architecture omissions, undocumented state field, overclaimed MAINTENANCE_MODE and /metrics
Closed
#207 A target listed twice in DNSWATCHER_TARGETS is checked twice
Closed
#204 TLS expiry warning is skipped on some checks, at random
Closed
#200 A domain's NS set comes from whichever server answers first, so it can change between checks when servers disagree
Closed
#173 README lacks the Getting Started, Rationale, Design and TODO sections that REPO_POLICIES.md requires
Closed
#197 Finding a zone's servers gives up after the first server answers SERVFAIL or refers onward
Closed
#193 Saved port state is removed when every nameserver of a hostname fails
Closed
#190 ResolveIPAddresses returns no addresses and no error when every nameserver fails
Closed
#119 fmt tooling is incomplete: fmt-check does not verify goimports, and no formatter covers Markdown
Closed
#189 Hostname records are queried at the servers of the name's last two labels, the wrong zone under co.uk-style suffixes and delegated subdomains
Closed
#105 Nameserver glue/IP changes are never detected — README claims they trigger a notification
Closed
#114 Final state persistence at shutdown depends on implicit fx hook ordering and is untested
Closed
#107 DNSWATCHER_SENTRY_DSN is documented and accepted but does nothing: port the Sentry integration from gohttpserver
Closed
#185 A check cut short by shutdown saves every port as closed and every certificate as failed
Closed
#181 The client address taken from X-Forwarded-For is the first entry, which the client itself can set
Closed
#104 Per-nameserver query status is discarded: NS failure and NS recovery notifications never fire
Closed
#177 An invalid DNSWATCHER_DNS_INTERVAL or DNSWATCHER_TLS_INTERVAL is silently replaced by the default
Closed
#101 No rate limiting on the Basic-Auth-protected /metrics endpoint
Closed
#109 Dockerfile does not implement the mandated fail-fast lint stage, and does not pass VERSION as a build ARG
Closed
#176 notify shutdown tests hang until the 90-second timeout instead of failing when a drain returns early
Closed
#129 script/install-precommit fails in a linked worktree: .git is a file, not a directory
Closed
#146 TODO.md is stale: lists shipped work as future steps and tells the reader to keep DNS tests mocked
Closed
#166 The container sets its data directory permissions itself before startup
Closed
#100 CORS wildcard applies to the authenticated /metrics route, and advertises methods that do not exist
Closed
#111 internal/state ships test-only constructors in the production build
Closed
#116 internal/notify shutdown tests: misleading failure diagnostic and an overloaded timing constant
Closed
#164 Test-only package internal/livedns can be compiled into the binary: rename it and name it in the test-support lint rule
Closed
#159 Watcher tests stub DNS with a mock resolver, against the no-DNS-mocking rule
Closed
#123 DECISION NEEDED: gomodguard linter is deprecated, and .golangci.yml can only be changed by you
Closed
#158 Inconsistency alert repeats on every DNS cycle while nameservers disagree
Closed
#147 Deploy readiness for upaas: non-root image, healthcheck, trial run, README deploy section
Closed
#168 Run every build, test and lint step in the Dockerfiles at nice -n 19
Closed
#157 Record values are compared with letter case, so nameservers that agree are reported as inconsistent
Closed
#115 script/cibuild can report a green it did not earn: RUN make check is served from the Docker layer cache
Closed
#120 Server timeout tests protect the constructor but not the call site, and carry an inverted rationale comment
Closed
#126 DECISION/ACCESS NEEDED: the CI job log Gitea returns for a commit does not correspond to that commit
Closed
#98 Add security response headers middleware (HSTS, CSP, X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy)
Closed
#110 internal/globals, internal/healthcheck, and internal/logger have no tests at all
Closed
#132 go.mod is untidy: golang.org/x/sync listed both direct and indirect, so script/bootstrap mutates a tracked file
Closed
#145 next cannot be merged into main: TODO.md conflicts after the squash of the last milestone
Closed
#124 script/docker has the same layer-cache hole as script/cibuild, so make docker can hand a developer an unearned green
Closed
#125 CHECK_EPOCH freshness is host-conditional: busybox date silently drops %N
Closed
#133 script/lint and script/fmt invoke golangci-lint and goimports by bare name, so a PATH shadow still overrides the pin
Closed
#117 script/bootstrap installs pinned tools only when missing, so the golangci-lint pin is inert on any machine that already has one
Closed
#121 script/lint shares one golangci-lint cache and lock across concurrent worktrees, so results can come from another codebase
Closed
#103 script/test always runs with -v instead of the conditional verbose rerun pattern
Closed
#130 Lint cache follow-ups: same-checkout runs abort instead of queueing, and make clean leaves .lint-cache/
70 Issues created by 1 user
Opened
#144 Review toward 1.0: identify and file all next steps
Opened
#145 next cannot be merged into main: TODO.md conflicts after the squash of the last milestone
Opened
#149 Trial run of the finished image against real targets before tagging 1.0
Opened
#148 OWNER: upaas deployment on fsn1app1 - deploy branch decision and the setup only you can do
Opened
#146 TODO.md is stale: lists shipped work as future steps and tells the reader to keep DNS tests mocked
Opened
#147 Deploy readiness for upaas: non-root image, healthcheck, trial run, README deploy section
Opened
#157 Record values are compared with letter case, so nameservers that agree are reported as inconsistent
Opened
#158 Inconsistency alert repeats on every DNS cycle while nameservers disagree
Opened
#159 Watcher tests stub DNS with a mock resolver, against the no-DNS-mocking rule
Opened
#164 Test-only package internal/livedns can be compiled into the binary: rename it and name it in the test-support lint rule
Opened
#166 The container sets its data directory permissions itself before startup
Opened
#168 Run every build, test and lint step in the Dockerfiles at nice -n 19
Opened
#173 README lacks the Getting Started, Rationale, Design and TODO sections that REPO_POLICIES.md requires
Opened
#176 notify shutdown tests hang until the 90-second timeout instead of failing when a drain returns early
Opened
#177 An invalid DNSWATCHER_DNS_INTERVAL or DNSWATCHER_TLS_INTERVAL is silently replaced by the default
Opened
#181 The client address taken from X-Forwarded-For is the first entry, which the client itself can set
Opened
#185 A check cut short by shutdown saves every port as closed and every certificate as failed
Opened
#189 Hostname records are queried at the servers of the name's last two labels, the wrong zone under co.uk-style suffixes and delegated subdomains
Opened
#190 ResolveIPAddresses returns no addresses and no error when every nameserver fails
Opened
#193 Saved port state is removed when every nameserver of a hostname fails
Opened
#197 Finding a zone's servers gives up after the first server answers SERVFAIL or refers onward
Opened
#200 A domain's NS set comes from whichever server answers first, so it can change between checks when servers disagree
Opened
#203 A watched name whose CNAME points into another zone gets no port or TLS checks
Opened
#204 TLS expiry warning is skipped on some checks, at random
Opened
#206 A query a server refuses is resent asking for recursion, so answers can come from a recursive resolver
Opened
#207 A target listed twice in DNSWATCHER_TARGETS is checked twice
Opened
#210 docker build . stamps dev, not the git tag or short commit
Opened
#214 next is red in CI: watcher tests time out since nameserver addresses are looked up on each domain check
Opened
#216 CI runs every pushed head, even after a newer push to the same branch has replaced it
Opened
#218 Resolver tests for AAAA and MX records fail when one query is lost
Opened
#219 Record Change and Inconsistency notifications print every record type in Go map syntax instead of what changed
Opened
#220 A hostname's CNAME is stored once for every record type asked for, eight copies in all
Opened
#221 Nameservers that a referral names without addresses are not looked up, so pool.ntp.org cannot be watched
Opened
#227 A failed Mattermost delivery is logged as "slack notification failed"
Opened
#226 The dashboard lists each nameserver's records in a random order of record type
Opened
#224 Apex domains are counted, listed and notified as hostnames
Opened
#223 Targets removed from DNSWATCHER_TARGETS stay on the dashboard, in /api/v1/status and in the startup counts
Opened
#222 A name gets a parent zone's nameservers when finding its own fails: a domain that does not exist shows the .com servers
Opened
#225 The dashboard and /api/v1/status do not say why a nameserver or certificate check failed
Opened
#228 Durations in the log are bare nanosecond counts
Opened
#229 A DNS lookup cut short by shutdown is logged as an error
Opened
#230 The startup notification says all notification channels are working before any delivery is known
Opened
#231 One lost query saves a nameserver's records with that type missing, and notifies a change
Opened
#233 OWNER: names whose nameservers rotate their answers notify on every check
Opened
#245 The dashboard Ports table lists an apex domain as a hostname
Opened
#248 Port Change notifications list apex domains as hosts
Opened
#251 Red next: the Quad9 refusal test needs all eight of its queries answered at once
Opened
#253 A nameserver whose A query got no reply is reported nodata when its other answers were empty
Opened
#255 Let an admin turn off Record Change and Inconsistency notifications for one name
Opened
#256 Let an admin turn off the record-change notification for one host
Opened
#257 Re-vendor the canonical files from sneak/prompts at dd4027b
Opened
#260 Defect hunt before the release candidate: a trial run of next and a read of its code paths
Opened
#267 A state file holding {} crashes the watcher on its first check
Opened
#262 A nameserver removed from a domain's delegation is also reported as an NS Failure
Opened
#266 dnswatcher keeps running without its HTTP server when the listen port is in use
Opened
#265 A certificate entry stays ok after its port 443 closes
Opened
#264 The state file is renamed into place without being synced, so a crash can leave it empty and stop the next start
Opened
#263 A non-numeric DNSWATCHER_TLS_EXPIRY_WARNING or PORT is silently read as 0
Opened
#261 The dashboard and /api/v1/status iterate the state's live maps without the lock, which can crash the process
Opened
#268 /metrics is served with an empty password when only DNSWATCHER_METRICS_USERNAME is set
Opened
#269 A setting that is not a valid number or true/false is read as 0 or false instead of stopping startup
Opened
#270 An IPv6 address joined with its port, as in a Port Change notification, cannot be told from the port
Opened
#271 The startup notification says the initial scan completed when shutdown cut it short
Opened
#281 TODO.md names closed issues as its next and future steps
Opened
#284 A hostname whose zone's nameservers all stop answering gets no NS Failure notification
Opened
#285 A nameserver with several addresses is asked at only the first one, so one unreachable address reports it as failed
Opened
#286 The static asset route serves directory listings at /s/ and /s/css/
Opened
#287 A webhook that answers with a redirect is counted as a successful delivery
Opened
#288 Debug logging writes the Slack, Mattermost and ntfy webhook URLs to the log on every delivery
Opened
#289 TESTING.md describes a root-server fan-out and a calibrated query timeout that the resolver does not have
2 Unresolved Conversations
Open
#59
No DNSSEC validation in iterative resolution
Open
#66
1.0/mvp