update_ip raises AuthenticationError for a bad/disabled token (401 via the
global handler, as before) and ValidationError for a bad IP; the route's
except-ValueError message sniff is gone. Sniffing census 8 -> 7.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- DdnsHost model: a hostname bound to a DNS zone plus a secret token; the
token is masked in API responses except when first minted.
- DdnsService.update_ip reuses DNSZoneService so a configured provider
(e.g. Cloudflare) is synced automatically; chooses A vs AAAA by IP family;
no-op when the IP is unchanged.
- API: admin CRUD for hosts + a public, token-authenticated /ddns/update
endpoint that a router or cron calls when its IP changes (IP from ?ip= or
the request source). Wrong token -> 401, bad IP -> 400.
- 8 tests covering the service flow and both endpoints.
UI panel to follow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>