From 716f1b9b06fddd278130e8bb65a45d08807bb880 Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 11 Nov 2026 00:10:51 +0000 Subject: [PATCH] TODO.md: drop the Completed Steps log; keep only open work (closes #307) Git holds the history the list recorded. Model: opus-5-5 --- TODO.md | 215 -------------------------------------------------------- 1 file changed, 215 deletions(-) diff --git a/TODO.md b/TODO.md index e3d269b..4f4fa99 100644 --- a/TODO.md +++ b/TODO.md @@ -17,221 +17,6 @@ milestone: https://git.eeqj.de/sneak/dnswatcher/milestone/7 1.0 tracking issue: https://git.eeqj.de/sneak/dnswatcher/issues/66 -# Completed Steps - -- 2026-10-18: the health check answers 503 with `status` `error` when every - lookup in the most recent round of DNS checks failed because no root server - gave a usable reply, as on a network that intercepts DNS queries (closes - #302). -- 2026-10-16: the first reply marked "recursion available" from a root server's - address, a refusal included, stops the lookup with "this network intercepts - DNS queries", so on a network that sends DNS to a resolver dnswatcher and its - tests fail, by design (closes #300). -- 2026-10-15: a query its caller's context ends before it is sent records no - reason about the nameserver, and a try the context's deadline cuts short is a - timeout, so a nameserver whose only failures were timeouts is `timeout`, not a - network error or `ok` (closes #298). -- 2026-10-15: the resolver no longer says its query timeout grows on each try; - every try waits the same 2 seconds, and the unused `timeoutMultiplier` is gone - (closes #296). -- 2026-10-15: `TESTING.md` Constraints give the resolver's 2-second query - timeout and second try, say a zone's servers are asked one at a time in a - random order, give the 60-second cap and 20-second target for `make test`, and - say a flaky live test is fixed with robustness, not with mocks (closes #289). -- 2026-10-15: a request under `/s/` that names a directory, such as `/s/` or - `/s/css`, answers 404 instead of a listing of its files (closes #286). -- 2026-10-15: a notification endpoint that answers with a redirect, or any - status other than 2xx, is a failed delivery, retried and logged (closes #287). -- 2026-10-15: a nameserver is asked at each of its IPv4 addresses in turn, so it - has failed only when none of them gives a usable reply (closes #285). -- 2026-10-15: the log names a notification endpoint (`slack`, `mattermost`, - `ntfy`) and never shows its URL's path or query (closes #288). -- 2026-10-13: a hostname or a domain whose zone's nameservers all stop answering - gets an NS Failure for each, then an NS Recovery (closes #284). -- 2026-10-13: an IPv6 address is written in brackets before its port, as in - `[2001:db8::1]:443`, in keys and Port Change notifications (closes #270). -- 2026-10-13: `TODO.md` names only open issues as next and future steps, and its - Status says nothing about git tags (closes #281). -- 2026-10-13: a port check that finds port 443 closed removes that address's - certificate entries, so none is left shown as `ok` (closes #265). -- 2026-10-13: a state file holding `{}`, or leaving out a section, loads with - that section empty; the first check no longer crashes on it (closes #267). -- 2026-10-13: a stop before the first scan completes sends no startup - notification; a scan that ran to the end still sends it (closes #271). -- 2026-10-13: a nameserver leaving a domain's delegation sends only NS Change; - one leaving a hostname's zone sends NS Change, not NS Failure (closes #262). -- 2026-10-13: `DNSWATCHER_METRICS_USERNAME` set without - `DNSWATCHER_METRICS_PASSWORD` stops startup (closes #268). -- 2026-10-13: a save syncs the state file to disk before renaming it into place, - so a crash cannot leave it empty and stop the next start (closes #264). -- 2026-10-13: a `PORT` that cannot be bound stops startup with an error naming - the address, instead of running without the HTTP server (closes #266). -- 2026-10-13: a bad `PORT`, `DNSWATCHER_TLS_EXPIRY_WARNING` or true/false - setting stops startup instead of being read as 0 or false (closes #269). -- 2026-10-13: a check saving the state while the dashboard or `/api/v1/status` - is read cannot crash the process (closes #261). -- 2026-10-06: canonical files re-fetched from `sneak/prompts` at `dd4027b`; lint - and test are phases of the `Dockerfile`, every scripted build uncached (closes - #257). -- 2026-10-05: a name listed in `DNSWATCHER_SKIP_RECORD_NOTIFICATIONS` gets no - Record Change or Inconsistency notification; a name listed there that is not - in `DNSWATCHER_TARGETS` stops startup (closes #255). -- 2026-10-02: a nameserver whose query for one record type failed while the - others answered with no records is `ok`, not `nodata` (closes #253). -- 2026-10-02: a domain that does not exist is shown so, with no nameservers; no - name gets a parent's nameservers when its own did not answer (closes #222). -- 2026-10-02: the refused-query test sends one query to four operators' public - resolvers in turn until one replies, not eight to one operator (closes #251). -- 2026-10-02: a name removed from `DNSWATCHER_TARGETS` leaves the state, and so - the dashboard and API, at startup, before the first check (closes #223). -- 2026-10-02: a record type whose query to a nameserver fails keeps its previous - records and alerts nothing; the other types are still saved (closes #231). -- 2026-10-02: a Port Change notification lists the port's domains on a - `Domains:` line and its hostnames on a `Hostnames:` line (closes #248). -- 2026-10-02: the dashboard's Ports table and `/api/v1/status` port entries list - a port's domains apart from its hostnames (closes #245). -- 2026-10-02: nameservers a referral names without addresses are looked up, - three deep at most; `pool.ntp.org`'s nameservers resolve (closes #221). -- 2026-10-02: an apex domain is not counted or listed as a hostname; its records - show under Domains, and notifications about them say `Domain:` (closes #224). -- 2026-10-02: the dashboard lists each nameserver's record types in one fixed - order, the README's, then any other type, not a random one (closes #226). -- 2026-10-02: the dashboard and `/api/v1/status` show why a nameserver query or - a certificate check failed, which only the state file showed (closes #225). -- 2026-10-02: a name's CNAME is stored once per nameserver, not once per record - type asked for; a state file with repeats loads each value once (closes #220). -- 2026-10-02: a DNS lookup that shutdown cuts short logs no error; one that - fails otherwise, or runs out of time, still does (closes #229). -- 2026-10-02: Record Change and Inconsistency notifications list only the record - types that differ, each with its values as plain text (closes #219). -- 2026-10-02: the startup notification no longer says every notification - endpoint works; it says it is a test sent to each of them (closes #230). -- 2026-10-02: a Mattermost webhook that answers an HTTP error is logged as - `mattermost notification failed`, not as a Slack failure (closes #227). -- 2026-10-02: durations in the log are written as text such as `2m0s`, not as a - bare count of nanoseconds (closes #228). -- 2026-10-02: a watched name whose nameservers answer with a CNAME and no - address gets port and TLS checks at the end of its CNAME chain (closes #203). -- 2026-10-02: a resolver test that reads one record type from a nameserver's - answer asks again when that type is missing from it (closes #218). -- 2026-10-02: a plain `docker build .` of a clone stamps its tag or short - commit, not `dev`: the build context now carries `.git` (closes #210). -- 2026-10-02: a query a server refuses is not resent asking for recursion, and - every root server refusing is reported as DNS interception (closes #206). -- 2026-10-02: a push to a branch cancels that branch's older CI run, and the - checkout leaves no token in `.git/config` (closes #216). -- 2026-10-02: watcher tests send far fewer queries and a live attempt may take - 18s; nameserver addresses are asked only for A, AAAA, CNAME (closes #214). -- 2026-10-02: the resolver tries root servers, and every other server list it - walks, in a random order each time, not always from the top (closes #138). -- 2026-10-02: a name listed more than once in `DNSWATCHER_TARGETS`, in any - letter case or with a trailing dot, is watched once (closes #207). -- 2026-10-01: README checked against the code and corrected: metrics, CORS, - notification retries, CNAMEs, state file fields, Design tree (closes #108). -- 2026-10-01: a certificate within the expiry warning period is warned about on - every TLS check, where some checks used to skip it at random (closes #204). -- 2026-10-01: a domain's NS set is its delegation from the parent zone's - servers, not whichever of its own servers answered first (closes #200). -- 2026-10-01: README has Getting Started, Rationale and TODO sections, and its - Architecture section is now Design, in the order policy sets (closes #173). -- 2026-10-01: a zone's server that answers SERVFAIL or a referral leading no - closer is passed over for the next, as one that times out is (closes #197). -- 2026-10-01: when none of a configured name's nameservers answered, the port - state saved for its addresses is kept, not removed (closes #193). -- 2026-10-01: `ResolveIPAddresses` returns an error, not no addresses, when no - nameserver of the name's zone answered (closes #190). -- 2026-10-01: `make fmt` and `make fmt-check` cover Markdown with prettier, run - in Docker at the version pinned by `yarn.lock` (closes #119). -- 2026-10-01: `make fmt-check` fails on a file `goimports` would change; both - format scripts run `goimports` at its pinned commit, not from `PATH` (#119). -- 2026-10-01: a hostname is queried at the servers of the zone it is in, found - by following delegations for the name, not its last two labels (closes #189). -- 2026-10-01: each nameserver's addresses are saved with its domain, and a - change while it stays in the delegation is notified (closes #105). -- 2026-10-01: the watcher saves state when it stops, and shutdown waits for that - save, so it no longer relies on the state's own stop hook (closes #114). -- 2026-10-01: `DNSWATCHER_SENTRY_DSN` reports panics in HTTP handlers to Sentry, - and a DSN Sentry cannot parse stops startup (closes #107). -- 2026-10-01: a port or TLS check that shutdown cuts short saves nothing and - sends no notification, as a cut-short DNS lookup already did (closes #185). -- 2026-10-01: the client address from `X-Forwarded-For` is the last entry that - is not a trusted proxy, not the first, which the client sets (closes #181). -- 2026-10-01: a nameserver that does not answer is saved as `error` with the - reason, and NS failure and NS recovery are notified (closes #104). -- 2026-10-01: a `DNSWATCHER_DNS_INTERVAL` or `DNSWATCHER_TLS_INTERVAL` that is - not a positive duration stops startup; empty means the default (closes #177). -- 2026-10-01: `/metrics` allows each client address 30 requests a minute, - counted before Basic Auth, and answers 429 beyond that (closes #101). -- 2026-10-01: the image built by `make docker` reports the `git describe` - version, not `dev`, and the startup log now shows it (closes #109). -- 2026-10-01: two notify shutdown tests always release the delivery they hold, - so a drain that returns early fails them instead of hanging (closes #176). -- 2026-10-01: `script/install-precommit` asks git for the repository's git - directory, so `make hooks` also works where `.git` is a file (closes #129). -- 2026-10-01: `TODO.md` brought up to date: open issues listed by URL, every - Completed Steps entry cut to at most two lines (closes #146). -- 2026-10-01: wildcard CORS now applies only to the public routes, not to - `/metrics`, and allows only the methods they serve (closes #100). -- 2026-10-01: `internal/state` and `internal/watcher` no longer export test-only - constructors: two moved to `export_test.go`, one is deleted (closes #111). -- 2026-10-01: notify shutdown tests use one timing constant per meaning, name - the bound they check, and require the drain's debug line (closes #116). -- 2026-09-29: the entrypoint chowns the data directory to `dnswatcher` and runs - dnswatcher as that user, so a host bind mount needs no chown (closes #166). -- 2026-09-29: the live-DNS test package is renamed `internal/livednstest`; - `make lint` fails when program code imports it (closes #164). -- 2026-09-29: `.golangci.yml` re-fetched from `sneak/prompts`, with - `gomodguard_v2` and the org `depguard` `test-support` rule (closes #123). -- 2026-09-29: watcher and resolver tests that look something up in DNS use the - real resolver against live DNS servers (closes #159). -- 2026-09-28: the inconsistency alert is sent once, when two nameservers start - to disagree; every pair of nameservers is compared (closes #158). -- 2026-09-28: DNS names in record values (CNAME, MX, SRV and NS targets) are - lower-cased, so letter case alone is not a change (closes #157). -- 2026-09-28: lint and tests run on every build: `script/cibuild` and - `script/docker` pass `--no-cache-filter=lint,builder` (closes #115). -- 2026-09-28: the server timeout test drives `Run` and checks the timeouts on - the `http.Server` it serves (closes #120). -- 2026-09-28: upaas deploy readiness: the image runs as user `dnswatcher` with a - `HEALTHCHECK`; README "Running under upaas" (closes #147). -- 2026-09-21: added behavioural tests for `internal/globals`, - `internal/healthcheck`, and `internal/logger` (closes #110). -- 2026-09-21: `go mod tidy` dropped the redundant `golang.org/x/sync` - `// indirect` line so `script/bootstrap` leaves a clean tree (#132) -- 2026-08-10: comment-only corrections to `script/bootstrap`, `script/cibuild` - and `Dockerfile.lint`; no behaviour changed. -- 2026-08-10: MIT `LICENSE` added at the repository root; the README's first - line and License section name the licence. -- 2026-08-10: policy scaffold present: `REPO_POLICIES.md`, `.editorconfig`, - `.dockerignore`, CI workflow, `make fmt-check`, `make docker`, `make hooks`. -- 2026-08-10: Go's test cache disabled in `script/test` (`-count=1`), so every - run queries live DNS; a failed run is rerun with `-v`. -- 2026-08-10: live-DNS tests made robust rather than gated (#93): a limit on - concurrent lookups, retries, and a quorum across nameservers. -- 2026-08-10: all linting moved into Docker: `script/lint` builds - `Dockerfile.lint`, and the root `Dockerfile` has its own lint stage. -- 2026-08-09: in-flight notification deliveries are drained at shutdown, bounded - by the shutdown deadline (#106). -- 2026-08-09: `http.Server` sets all four socket timeouts; `WriteTimeout` stays - above the 60s handler timeout (#99). -- 2026-08-09: `SecurityHeaders()` middleware sets HSTS, CSP and the other - security headers `REPO_POLICIES.md` requires on every response. -- 2026-08-07: golangci-lint bumped to v2.12.2 and `.golangci.yml` set to the org - config; fixed the resulting `goconst`, `dupl` and `lll` findings. -- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile - shims, README Entrypoints section -- 2026-02-20: iterative DNS resolver implemented -- 2026-02-20: CI actions and go install refs pinned to commit SHAs; Gitea - Actions workflow added -- 2026-02-20: watcher monitoring orchestrator merged to main (#8) -- 2026-02-20: DOMAINS/HOSTNAMES unified into single TARGETS config (#11) -- 2026-02-19: TCP port connectivity checker, made concurrent with port - validation; gosec G704 SSRF findings fixed without suppression -- 2026-02-19: TLS certificate inspector with no-peer-certificates error path and - IP SANs -- 2026-02-19: gosec SSRF and formatting fixes on main -- 2026-02-19: initial scaffold with per-nameserver DNS monitoring model - # Future Steps - DNSSEC validation, after 1.0: https://git.eeqj.de/sneak/dnswatcher/issues/59