fx wiring (main.go): Interface adapters for concrete types
Resolver stub (resolver.go): Updated LookupAllRecords signature to return per-NS results
State helper (state_test_helper.go): NewForTest() for unit testing
Test Results
=== RUN TestFirstRunBaseline --- PASS
=== RUN TestNSChangeDetection --- PASS
=== RUN TestRecordChangeDetection --- PASS
=== RUN TestPortStateChange --- PASS
=== RUN TestTLSExpiryWarning --- PASS
=== RUN TestGracefulShutdown --- PASS
=== RUN TestNSFailureAndRecovery --- PASS
PASS ok sneak.berlin/go/dnswatcher/internal/watcher 1.455s
Lint
All new code passes linting. Only pre-existing gosec warnings in notify.go remain (SSRF taint analysis on webhook URLs from config).
Implements the full monitoring loop:
- Immediate checks on startup, then periodic DNS+port and TLS cycles
- Domain NS change detection with notifications
- Per-nameserver hostname record tracking with change/failure/recovery
and inconsistency detection
- TCP port 80/443 monitoring with state change notifications
- TLS certificate monitoring with change, expiry, and failure detection
- State persistence after each cycle
- First run establishes baseline without notifications
- Graceful shutdown via context cancellation
Defines DNSResolver, PortChecker, TLSChecker, and Notifier interfaces
for dependency injection. Updates main.go fx wiring and resolver stub
signature to match per-NS record format.
Closes#2
The interface and signature are designed for all RR types — the return type is map[nameserver]map[recordType][]values, and the interface doc says "queries all record types for a hostname." However, the actual implementation in internal/resolver/resolver.go is currently a stub that returns ErrNotImplemented.
So the intent is all RR types (A, AAAA, TXT, MX, CNAME, etc.), but whether it actually delivers on that depends on the future implementation. The contract is correct as written.
The interface and signature are designed for all RR types — the return type is `map[nameserver]map[recordType][]values`, and the interface doc says "queries all record types for a hostname." However, the actual implementation in `internal/resolver/resolver.go` is currently a stub that returns `ErrNotImplemented`.
So the *intent* is all RR types (A, AAAA, TXT, MX, CNAME, etc.), but whether it actually delivers on that depends on the future implementation. The contract is correct as written.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Implements the full watcher monitoring orchestrator as described in the README.
Changes
interfaces.go):DNSResolver,PortChecker,TLSChecker,Notifier— enables testing with mocks and future implementation swapswatcher.go): Full monitoring loop with:main.go): Interface adapters for concrete typesresolver.go): UpdatedLookupAllRecordssignature to return per-NS resultsstate_test_helper.go):NewForTest()for unit testingTest Results
Lint
All new code passes linting. Only pre-existing gosec warnings in
notify.goremain (SSRF taint analysis on webhook URLs from config).Closes #2
@clawbot does LookupAllRecords get all RR types or just address records? it should get all RR types incl TXT etc.
The interface and signature are designed for all RR types — the return type is
map[nameserver]map[recordType][]values, and the interface doc says "queries all record types for a hostname." However, the actual implementation ininternal/resolver/resolver.gois currently a stub that returnsErrNotImplemented.So the intent is all RR types (A, AAAA, TXT, MX, CNAME, etc.), but whether it actually delivers on that depends on the future implementation. The contract is correct as written.
make checkaudit result✅ All checks passed.
make check passes ✅