From 288877fe88649360dd08081d7f7b6668f98899b0 Mon Sep 17 00:00:00 2001 From: sneak Date: Thu, 1 Oct 2026 22:23:05 +0000 Subject: [PATCH] docs: add the README sections policy requires (closes #173) REPO_POLICIES.md requires Getting Started, Rationale, Design and TODO sections in the README, and it had none of them. Getting Started clones the repository, builds the image and runs it watching example.com and www.example.com; DNSWATCHER_TARGETS is the only setting it requires. Rationale is drawn from what the README already says. The Architecture section moves below Entrypoints and is renamed Design, its text unchanged, so the required sections come in policy order. TODO points to TODO.md and the 1.0 milestone instead of copying the list. Model: opus-5-5 --- README.md | 127 ++++++++++++++++++++++++++++++++++++------------------ TODO.md | 4 +- 2 files changed, 87 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 0636e9b..d1ec4db 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,29 @@ Contributions that introduce mocked, faked, or stubbed DNS will be rejected. --- +## Getting Started + +You need git and Docker. This builds the image and runs dnswatcher watching +`example.com` and `www.example.com`: + +```sh +git clone https://git.eeqj.de/sneak/dnswatcher.git +cd dnswatcher +docker build -t dnswatcher . +docker run -d --name dnswatcher \ + -p 8080:8080 \ + -v dnswatcher-data:/var/lib/dnswatcher \ + -e DNSWATCHER_TARGETS=example.com,www.example.com \ + dnswatcher +``` + +The build also runs the linter and the test suite, which queries live DNS. Once +the container is running, the dashboard is at . With no +notification endpoint set, changes show only on the dashboard; see +[Configuration](#configuration) to add one. + +--- + ## Features ### DNS Domain Monitoring (Apex Domains) @@ -272,48 +295,6 @@ navigation needs, and its URL may name internal hosts. --- -## Architecture - -``` -cmd/dnswatcher/main.go Entry point (uber/fx bootstrap) - -internal/ - config/config.go Viper-based configuration - globals/globals.go Build-time variables (version) - logger/logger.go slog structured logging (TTY detection) - healthcheck/healthcheck.go Health check service - middleware/middleware.go HTTP middleware (logging, CORS, security - headers, metrics auth and rate limit) - handlers/handlers.go HTTP request handlers - server/ - server.go HTTP server lifecycle - routes.go Route definitions - state/state.go JSON file state persistence - resolver/resolver.go Iterative DNS resolution engine - portcheck/portcheck.go TCP port connectivity checker - tlscheck/tlscheck.go TLS certificate inspector - notify/notify.go Notification service (Slack, Mattermost, ntfy) - watcher/watcher.go Main monitoring orchestrator and scheduler - livednstest/livednstest.go Retry and concurrency limit for tests - against live DNS (imported only by tests) -``` - -### Design Principles - -- **No recursive resolvers**: All DNS resolution is performed iteratively, - tracing from root nameservers through the delegation chain to authoritative - servers. -- **No external database**: State is persisted as a single JSON file. -- **Dependency injection**: All components are wired via - [uber/fx](https://github.com/uber-go/fx). -- **Structured logging**: All logs use `log/slog` with JSON output in production - (TTY detection for development). -- **Graceful shutdown**: All background goroutines respect context cancellation - and the fx lifecycle. In-flight notification deliveries are drained on - shutdown, bounded by the shutdown timeout. - ---- - ## Configuration Configuration is loaded via [Viper](https://github.com/spf13/viper) with the @@ -667,6 +648,68 @@ configuration. --- +## Rationale + +dnswatcher exists to report changes to the DNS records, TCP port availability +and TLS certificates of its configured domains and hostnames, failures and +recoveries included: it is designed as a real-time change feed. It queries the +authoritative nameservers directly, tracing from the root, instead of a +recursive resolver, so no resolver's cache or filtering hides a change and +nameservers that disagree with each other are seen. Its state is a single JSON +file, so it survives a restart without an external database. + +--- + +## Design + +``` +cmd/dnswatcher/main.go Entry point (uber/fx bootstrap) + +internal/ + config/config.go Viper-based configuration + globals/globals.go Build-time variables (version) + logger/logger.go slog structured logging (TTY detection) + healthcheck/healthcheck.go Health check service + middleware/middleware.go HTTP middleware (logging, CORS, security + headers, metrics auth and rate limit) + handlers/handlers.go HTTP request handlers + server/ + server.go HTTP server lifecycle + routes.go Route definitions + state/state.go JSON file state persistence + resolver/resolver.go Iterative DNS resolution engine + portcheck/portcheck.go TCP port connectivity checker + tlscheck/tlscheck.go TLS certificate inspector + notify/notify.go Notification service (Slack, Mattermost, ntfy) + watcher/watcher.go Main monitoring orchestrator and scheduler + livednstest/livednstest.go Retry and concurrency limit for tests + against live DNS (imported only by tests) +``` + +### Design Principles + +- **No recursive resolvers**: All DNS resolution is performed iteratively, + tracing from root nameservers through the delegation chain to authoritative + servers. +- **No external database**: State is persisted as a single JSON file. +- **Dependency injection**: All components are wired via + [uber/fx](https://github.com/uber-go/fx). +- **Structured logging**: All logs use `log/slog` with JSON output in production + (TTY detection for development). +- **Graceful shutdown**: All background goroutines respect context cancellation + and the fx lifecycle. In-flight notification deliveries are drained on + shutdown, bounded by the shutdown timeout. + +--- + +## TODO + +[`TODO.md`](./TODO.md) names the next step and the steps planned after it. The +work for 1.0 is tracked as issues on the +[1.0 milestone](https://git.eeqj.de/sneak/dnswatcher/milestone/7). + +--- + ## License dnswatcher is released under the MIT License, Copyright (c) 2026 diff --git a/TODO.md b/TODO.md index 8972d49..596779e 100644 --- a/TODO.md +++ b/TODO.md @@ -19,6 +19,8 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149 # Completed Steps +- 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 @@ -122,7 +124,5 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149 - 1.0 readiness: run it with a real config and read the logs: https://git.eeqj.de/sneak/dnswatcher/issues/66 - README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108 -- README sections required by policy: - https://git.eeqj.de/sneak/dnswatcher/issues/173 - fixed root server order: https://git.eeqj.de/sneak/dnswatcher/issues/138 - review toward 1.0: https://git.eeqj.de/sneak/dnswatcher/issues/144