New Domains page listing when each domain registration expires, read from
the registry. Domains behind the DNS zones already synced are picked up
automatically; others can be added by hand. You're reminded daily from N
days before expiry (Settings > Notifications, default 30) until it's
renewed, and told when an expiry date hasn't been refreshable for several
days so a stale date isn't trusted silently.
RDAP alone would not have covered this homelab: .se, .nu, .io, .eu and .de
are not in IANA's RDAP bootstrap. Lookups therefore try RDAP where the TLD
publishes a server and fall back to WHOIS on port 43, found via IANA's
own referral, parsing the expiry line out of the free-text answer. Only
the expiry date and registrar are read or stored. Verified live against
the real registries: .se and .nu via WHOIS, .com/.org/.dev via RDAP.
Behaviour worth knowing:
- A DNS zone that is a subdomain (lab.example.se) resolves to the
registration that actually expires by trying the name and then its
parents, so no public-suffix list is needed. Zones already covered by a
tracked domain are not looked up again.
- "Couldn't ask" is never confused with "not registered": network errors,
rate limits and garbled answers are errors, and a transient error at any
level stops the walk from concluding the domain doesn't exist.
- A failed refresh keeps the last known expiry and records why, rather
than blanking a date that's still relied on.
- Zones that don't resolve to a real registration (.lan, .local, unregistered
names) simply get no row. Zone-derived rows disappear when their zone
does; manual rows stay. Zone-derived rows can't be deleted by hand.
- Registries that don't publish an expiry (.de, .eu) are tracked with a
note instead of a date.
- Input like "example.com/path" is refused rather than silently reduced
to its host.
- Runs on the daily secret-expiry schedule and reminder time, on demand
(Check all now / per domain), and once at startup if nothing has been
read in a day. Never blocks startup, one lookup at a time with a pause.
The warning window lives with the other thresholds in settings.
New table domains (migration 0011); two settings fields (toggle and
warning days).
Verified with 90 checks against fake RDAP/WHOIS backends (name
normalization, date formats, WHOIS parsing including rate-limit and
no-expiry answers, bootstrap and referral caching, stale-cache fallback,
parent walking, add/sync/check/refresh, concurrency guard, alert
selection and stale detection, the daily notification and its toggle,
role rules) plus a live smoke test against real registries and a browser
check of the page against the real router. Real dev database mtime
untouched. Not checked: a screenshot of the finished page (the capture
timed out); structure, sorting, errors and the viewer view were verified.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>