Skip to content

v0.8.0-rc

Pre-release
Pre-release

Choose a tag to compare

@nemunaire nemunaire released this 16 Apr 10:31
· 425 commits to master since this release

This release cycle was made possible thanks to the financial support of NLnet, whose funding enabled the development of the new checker subsystem, its integrations and the observability work that ships in this version.

Highlights

  • New checker subsystem. happyDomain can now schedule, run and track recurring checks against your domains, zones and services. The subsystem ships with its own scheduler, execution history, retention policy, per-user quotas, rule engine, HTML/JSON/metrics reports, and a full frontend experience (list, configuration, schedule, rules, executions and charts).
  • Pluggable checkers. External checkers can be distributed as .so plugins and loaded at startup through the -plugins-directory flag, or delegated to a remote HTTP endpoint via the new observation transport layer. Seven new checkers are bundled: ICMP ping, Zonemaster, Matrix federation, domain expiration, NS security restrictions, domain contact consistency, and domain lock status.
  • RDAP / WHOIS domain information. A new /whois page and a zone sidebar modal display registrar, important dates, nameservers and status for any domain, backed by a new DomainInfoUsecase and /api/domaininfo/:domain endpoint.
  • Prometheus observability. happyDomain now exposes a /metrics endpoint on the admin socket, covering HTTP traffic, the checker scheduler, DNS provider adapters, storage operations, business entity counts and build info. The admin dashboard has been rewritten on top of this feed.

Features

Checker subsystem

  • Foundational domain model for checkers: CheckTarget, CheckPlan, Execution, CheckEvaluation, CheckerDefinition, CheckerOptions, ObservationSnapshot and associated interfaces.
  • Observation collection engine with concurrent per-key gathering and a WorstStatusAggregator for combining rule evaluation results.
  • Checker and observation provider registries, wrapping checker-sdk-go.
  • Full business logic: scope-based option resolution, validation and auto-fill (CheckerOptionsUsecase); CRUD for user scheduling configurations (CheckPlanUsecase); aggregated status queries and history (CheckStatusUsecase); full execution pipeline (CheckerEngine).
  • Background Scheduler with min-heap queue, worker pool, jitter and auto-discovery; incremental updates on domain/zone create, delete, import and publish, via a narrow SchedulerDomainNotifier interface.
  • Persistence layer: CheckPlanStorage, CheckerOptionsStorage, CheckEvaluationStorage, ExecutionStorage, ObservationSnapshotStorage and SchedulerStateStorage, with KV-based implementations for LevelDB / Oracle NoSQL / InMemory backends, tidy methods for every checker entity and secondary index cleanup.
  • HTTP API controllers and scoped routes at the user, domain and service levels, plus admin routes for checker configuration and scheduler management.
  • External plugin loader: .so files discovered in -plugins-directory are opened via plugin.Open, NewCheckerPlugin is looked up from checker-sdk-go, and the returned definition and observation provider are registered in the global registries.
  • Remote observation transport: when an admin configures an endpoint option, the engine substitutes the local provider with an HTTPObservationProvider that POSTs to {endpoint}/collect.
  • Observation data pipeline stores json.RawMessage end-to-end, eliminating double-serialization and enabling cross-checker reuse of cached observations.
  • NoOverride field on checker options prevents more specific scopes from overriding values locked at a higher scope (typically admin), with defense-in-depth stripping on Set/Add, merge-time preservation and frontend filtering.
  • Map-based option validation (ValidateMapValues) for required fields, allowed choices and type checking.

Bundled checkers

  • ICMP ping — RTT and packet-loss metrics.
  • Zonemaster — full Zonemaster report rendering.
  • Matrix federation — federation readiness checks.
  • Domain expiration — monitors the registry expiration date.
  • NS security restrictions — probes authoritative nameservers for AXFR/IXFR acceptance, recursion, RFC 8482 ANY handling and authoritative status, via the external checker-ns-restrictions plugin.
  • Domain contact consistency — compares RDAP/WHOIS registrant, admin and tech contacts against user-specified expected values, with redaction detection for privacy-protected domains.
  • Domain lock status — reports registry lock flags.

Retention, quotas & safety

  • Tiered RetentionPolicy:
    • 0–1 day: every execution
    • 1–7 days: one report per hour
    • 7–30 days: 2 per day per (checker, target)
    • 30–D/2 days: 1 per week per (checker, target)
    • D/2–D days: 1 per month per (checker, target)
    • beyond D: dropped
  • Janitor goroutine enforces the retention policy on every CheckPlan, honours per-user overrides and caches user lookups per
    sweep. Default interval 6h; runs once at startup.
  • UserQuota model for admin-controlled per-user limits and flags (max checks per day, retention days, inactivity pause days,
    scheduling kill switch). Exposed through the admin user PUT endpoint and a new editor card under /users/[uid]; not reachable from user-facing settings.
  • Scheduler UserGater pauses scheduling for paused users and for users whose LastSeen is older than their effective inactivity horizon, with 5 min caching and an Invalidate hook.
  • MaxChecksPerDay enforcement with interval-aware throttling: short-interval jobs are skipped first once 80 % of the daily budget is consumed, so rare / important checks are not starved by frequent pings. Planned executions that breach the quota are surfaced with a new ExecutionRateLimited status; manual API triggers bypass the quota.

Frontend for checkers

  • Checker list, configuration, schedule and rules pages.
  • Execution list, detail, results and rules pages with sidebar view switching (HTML report / JSON / metrics / rules).
  • Chart.js-based metrics chart on execution lists and per-execution detail pages.
  • HTML report rendering via the new CheckerHTMLReporter interface; the Zonemaster provider ships with collapsible accordions and severity badges.
  • "Run check" modal with option overrides and rule selection.
  • Domain-scoped and service-scoped check routes.
  • Admin pages for checker configuration and scheduler management.
  • Checks status summary badge in the zone viewer PageHeader; worst check status badge on the domain list, with dynamic colour and icon.
  • Zone and service-level checkers visible on the domain checks page, with scheduling / rules hidden for non-domain checkers configured from the domain context.
  • English translations for all checker UI strings.

RDAP / WHOIS

  • New domaininfo package with RDAP and WHOIS getters.
  • DomainInfoUsecase and /api/domaininfo/:domain route, also mounted under the domain scope.
  • /whois frontend page and zone sidebar modal.
  • ContactInfo extracted from both RDAP and WHOIS responses; the WHOIS observation provider exposes contact data for reuse by the domain_contact checker.
  • Per-IP rate limiter on /api/domaininfo/:domain (10 req/min, using gin-rate-limit) to mitigate enumeration and proxy abuse on this unauthenticated endpoint.

Prometheus metrics

  • New internal/metrics package with all metric variables registered via promauto, a Gin HTTP middleware recording request count, duration and in-flight gauge (using c.FullPath() to keep label cardinality bounded), and an InstrumentedStorage wrapper recording operation counts and durations for every entity.
  • /metrics endpoint served via promhttp on the admin socket.
  • App wiring: HTTP middleware on the public router, storage wrapped after initialisation, build info metric populated from main() with the real version string; prometheus/client_golang promoted to a direct dependency.
  • Storage stats collector exposes live gauges queried at each scrape: happydomain_registered_users_total, happydomain_domains_total, happydomain_zones_total, happydomain_providers_total.
  • DNS provider adapter (DNSControlAdapterNSProvider) records happydomain_provider_api_calls_total and happydomain_provider_api_duration_seconds for GetZoneRecords, GetZoneCorrections, CreateDomain and ListZones.
  • Check scheduler tracks queue depth, active worker count, check execution duration per checker, and check result status counters.
  • Checker metrics endpoints negotiate format via the Accept header: application/json returns the JSON array, anything else returns the Prometheus text exposition format.
  • Metrics endpoints skip incomplete / planned executions via a new doneExecution filter on ListExecutionsBy*, so only fully evaluated runs contribute to the Prometheus output.
  • Admin dashboard rewritten on top of /metrics: a single scrape every 15 s replaces the three REST count calls, featured cards surface queue / workers / in-flight / RSS / version / uptime, and the full counter set + Go runtime stats are hidden under a "Show more metrics" collapse.
  • New link to the Prometheus metrics URL on the checker configuration page.
  • Prometheus export documentation added under docs/.

Improvements

  • Tidy, scheduler and auto-fill now consider the WIP zone (ZoneHistory[0]) in addition to the latest published zone, so services being drafted are not cleaned up or ignored and auto-fill resolves from the right zone for the best user experience.
  • JWT middleware now silently hands off to the session store when a bearer token is a valid session ID (base32, 103 chars) instead of logging a misleading "bad JWT claims" error. IsValidSessionID is exported, and the session ID length is derived from a constant tied to the key size in the usecase package.
  • Tests covering success, error and panic paths of DNSControlAdapterNSProvider metrics instrumentation for GetZoneRecords, GetZoneCorrections, CreateDomain and ListZones.

Bug fixes

  • Checker subsystem used the wrong zone snapshot. ZoneHistory is ordered [WIP, newest-published, …, oldest-published], but the tidy, scheduler and auto-fill code read ZoneHistory[len-1] (the oldest zone). This caused the scheduler to enumerate services from an outdated snapshot, tidy to check service existence against stale data, and auto-fill to resolve from the wrong zone. Fixed to use ZoneHistory[1] (the latest published zone).

Funding

This project is funded through NGI Zero Core, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program. Learn more at the NLnet project page.

NLnet foundation logo
NGI Zero Logo