check / check (push) Waiting to run
The JSON log wrote a Go duration as a bare count of nanoseconds, so the watcher starting line showed dnsInterval 120000000000 for 2m and a delivery retry showed retryIn 1015437050. Each duration logged is now passed through its String() form: dnsInterval and tlsInterval when the watcher starts, retryIn on a delivery retry, and latency on a succeeded port check. A test checks that retryIn is logged as the text of the wait the retry actually took. The request log's latency_ms is left as it is: its key names its unit. Model: opus-5-5
9.2 KiB
9.2 KiB
Workflow
- branch (from
next) - do the work in Next Step
- move Next Step to the top of Completed Steps
- move the top item of Future Steps into Next Step
- commit (
TODO.mdchanges in the same commit as the work) - push
- open a PR against
next
Status
pre-1.0. No git tags. Work lands on next by PR. Open work for 1.0 is tracked
on the 1.0 milestone: https://git.eeqj.de/sneak/dnswatcher/milestone/7
Next Step
trial run of the finished image: #149
Completed Steps
- 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, notdev: 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:
ResolveIPAddressesreturns an error, not no addresses, when no nameserver of the name's zone answered (closes #190). - 2026-10-01:
make fmtandmake fmt-checkcover Markdown with prettier, run in Docker at the version pinned byyarn.lock(closes #119). - 2026-10-01:
make fmt-checkfails on a filegoimportswould change; both format scripts rungoimportsat its pinned commit, not fromPATH(#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_DSNreports 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-Foris 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
errorwith the reason, and NS failure and NS recovery are notified (closes #104). - 2026-10-01: a
DNSWATCHER_DNS_INTERVALorDNSWATCHER_TLS_INTERVALthat is not a positive duration stops startup; empty means the default (closes #177). - 2026-10-01:
/metricsallows 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 dockerreports thegit describeversion, notdev, 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-precommitasks git for the repository's git directory, somake hooksalso works where.gitis a file (closes #129). - 2026-10-01:
TODO.mdbrought 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/stateandinternal/watcherno longer export test-only constructors: two moved toexport_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
dnswatcherand 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 lintfails when program code imports it (closes #164). - 2026-09-29:
.golangci.ymlre-fetched fromsneak/prompts, withgomodguard_v2and the orgdepguardtest-supportrule (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/cibuildandscript/dockerpass--no-cache-filter=lint,builder(closes #115). - 2026-09-28: the server timeout test drives
Runand checks the timeouts on thehttp.Serverit serves (closes #120). - 2026-09-28: upaas deploy readiness: the image runs as user
dnswatcherwith aHEALTHCHECK; README "Running under upaas" (closes #147). - 2026-09-21: added behavioural tests for
internal/globals,internal/healthcheck, andinternal/logger(closes #110). - 2026-09-21:
go mod tidydropped the redundantgolang.org/x/sync// indirectline soscript/bootstrapleaves a clean tree (#132) - 2026-08-10: comment-only corrections to
script/bootstrap,script/cibuildandDockerfile.lint; no behaviour changed. - 2026-08-10: MIT
LICENSEadded 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/lintbuildsDockerfile.lint, and the rootDockerfilehas 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.Serversets all four socket timeouts;WriteTimeoutstays above the 60s handler timeout (#99). - 2026-08-09:
SecurityHeaders()middleware sets HSTS, CSP and the other security headersREPO_POLICIES.mdrequires on every response. - 2026-08-07: golangci-lint bumped to v2.12.2 and
.golangci.ymlset to the org config; fixed the resultinggoconst,duplandlllfindings. - 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