Commit graph

1,826 commits

Author SHA1 Message Date
8d030071e1 checker: add Janitor goroutine to enforce retention policy
The Janitor periodically walks every CheckPlan, loads its executions,
and deletes the ones that the tiered RetentionPolicy says to drop.

Per-user overrides are honoured: if a user's UserQuota.RetentionDays
is set, that horizon replaces the system default for the user's plans.
User lookups are cached per sweep to avoid repeated storage hits.

The janitor is the long-tail counterpart of the (still TODO) cheap
hard cap that will be applied at execution-creation time. It runs
immediately on Start() and then every configured interval (default 6h).
2026-04-15 19:38:38 +07:00
b9035bb6b4 checker: keep 1 report per hour after the first day
Insert an hourly tier between the full-detail window and the daily
bucket so users still get sub-day resolution for the first week:

  0..1 day  -> all
  1..7 days -> 1 per hour
  7..30     -> 2 per day
  ...
2026-04-15 19:30:29 +07:00
fd5bfb637d checker: add tiered RetentionPolicy
Introduce a pure RetentionPolicy.Decide function that partitions check
executions into keep/drop sets according to a tiered policy:

  - 0..7 days   -> every execution
  - 7..30 days  -> 2 per day per (checker, target)
  - 30..D/2     -> 1 per week per (checker, target)
  - D/2..D days -> 1 per month per (checker, target)
  - > D days    -> dropped

The function is intentionally storage-agnostic so the upcoming janitor
goroutine can call it on any execution slice and so it can be unit
tested directly. All thresholds are configurable to allow per-user
overrides via UserQuota.
2026-04-15 19:30:14 +07:00
ce9da66a76 model: add UserQuota struct for admin-controlled per-user limits
Introduce a UserQuota field on the User model to hold admin-controlled
limits and flags that the user cannot modify. Only checker-related
fields are defined for now (max checks per day, retention days,
inactivity pause days, scheduling kill switch); future paid-plan
attributes will be added here later.

The user-facing API only exposes settings updates and account deletion,
so Quota cannot be written through it. Updates go through the existing
admin user PUT endpoint, with a new editor card in the admin UI under
/users/[uid].
2026-04-15 19:30:14 +07:00
a18237aaa5 New checker: Matrix federation 2026-04-15 19:30:14 +07:00
1bb2592f4d New checker: zonemaster 2026-04-15 19:30:14 +07:00
33279f8c6e New checker: ICMP ping checker with RTT and packet loss metrics 2026-04-15 19:30:14 +07:00
9d76a0a62a checkers: add HTTP transport layer
Introduce a transport abstraction so observation providers can run either
locally or be delegated to a remote HTTP endpoint. When an admin sets the
"endpoint" option, the engine substitutes the local provider with an
HTTPObservationProvider that POSTs to {endpoint}/collect.
2026-04-15 19:30:14 +07:00
ac50d02819 checkers: add incremental scheduler updates on domain/zone changes
Instead of rebuilding the entire scheduler queue, incrementally add or
remove jobs when domains are created/deleted or zones are
imported/published. A wake channel interrupts the run loop so new jobs
are picked up immediately. A jobKeys index prevents duplicate entries.

Hook points: domain creation, domain deletion, zone import, and zone
publish (correction apply) all notify the scheduler via the narrow
SchedulerDomainNotifier interface, wired through setter methods to
avoid initialization ordering issues.
2026-04-15 19:30:14 +07:00
cab205c97f checkers: store observations as json.RawMessage with cross-checker reuse
Refactor observation data pipeline to serialize once after collection and
keep json.RawMessage throughout storage and API responses. This eliminates
double-serialization and makes DB round-trips lossless.
2026-04-15 19:30:14 +07:00
6d0423480d checkers: add NoOverride field support for checker options
Prevent more specific scopes from overriding option values locked at a
higher scope (e.g. admin). Includes defense-in-depth stripping on
Set/Add operations, merge-time preservation, and frontend filtering.
2026-04-15 19:30:14 +07:00
1d8700db74 checkers: show worst check status badge on domain list
Add DomainWithCheckStatus model and GetWorstDomainStatuses usecase to
compute the most critical checker status per domain. The GET /domains
endpoint now returns status alongside each domain. The frontend domain
store, list components, and table row display dynamic status badges
with color and icon instead of a hardcoded "OK".

ZoneList is made generic (T extends HappydnsDomain) so the badges
snippet preserves the caller's concrete type without unsafe casts.
2026-04-15 19:30:14 +07:00
3b3ac3b046 checkers: show children checkers on domain page and hide scheduling for non-domain checkers
Add a separate section on the domain checks page to display zone and
service-level checkers that can be configured but won't produce results
at the domain scope. Hide the scheduling and rules cards when configuring
a non-domain checker from the domain context.
2026-04-15 19:30:14 +07:00
1a39b4322e checkers: add frontend metrics chart on execution pages
Add Chart.js-based line chart for checker metrics. The chart appears
on the executions list page (aggregated) and on individual execution
detail pages. Metrics view mode is selectable via the sidebar alongside
HTML report and raw JSON views.
2026-04-15 19:30:14 +07:00
6f9c653101 checkers: add metrics export in JSON format
Observation providers can now implement CheckerMetricsReporter to
extract time-series metrics from their stored data. The controller
returns the metrics as a JSON array.

Routes: user-level (/api/checkers/metrics), domain-level, per-checker,
and per-execution.
2026-04-15 19:30:14 +07:00
a8062c3eca checkers: add HTML report rendering for observation providers
Introduce CheckerHTMLReporter interface that observation providers can
implement to render rich HTML documents from their data. The Zonemaster
provider implements it with collapsible accordions and severity badges.

Adds API endpoint GET .../observations/:obsKey/report, frontend stores
for view mode switching (HTML/JSON), and wires the sidebar toggle buttons.
2026-04-15 19:30:14 +07:00
09d151b234 checkers: add frontend UI components and routes
Add all checker UI pages and components:
- Checker list, config, schedule, and rules pages
- Execution list, detail, results, and rules pages
- Sidebar components for domain/service checker status
- Run check modal with option overrides and rule selection
- Domain-scoped and service-scoped check routes
- Admin pages for checker configuration and scheduler management
- Header navigation link for checkers section
2026-04-15 19:30:14 +07:00
7b41ed3060 checkers: add frontend API client, stores, and utilities
Add the frontend infrastructure for the checker UI:
- API client with scoped helpers for domain/service-level operations
- Svelte stores for checker state (currentExecution, currentCheckInfo)
- Utility functions for status colors, icons, i18n keys, date formatting
- Shared helpers: withInheritedPlaceholders, downloadBlob, collectAllOptionDocs
- English translations for all checker UI strings
- Zone model and form types extended for checker support
2026-04-15 19:30:14 +07:00
3008e04a8c checkers: add API controllers, routes, and app wiring
Wire up the checker system to the HTTP layer:
- API controllers for checker operations, options, plans, and results
- Scoped routes at domain and service level
- Admin controllers for checker config and scheduler management
- App initialization: create usecases, start/stop scheduler
- Zone controller updated to include per-service check status
2026-04-15 19:30:14 +07:00
f6d0969db0 checkers: add usecases, engine, and scheduler
Implement the checker business logic:
- CheckerOptionsUsecase: scope-based option resolution, validation,
  auto-fill from execution context (domain, zone, service)
- CheckPlanUsecase: CRUD for user scheduling configurations
- CheckStatusUsecase: aggregated status queries, execution history
- CheckerEngine: full execution pipeline (observe, evaluate, aggregate)
- Scheduler: background job executor with auto-discovery, min-heap
  queue, worker pool, and jitter-based scheduling
2026-04-15 19:30:13 +07:00
4ce33ade83 checkers: add storage interfaces, implementations, and tidy
Add the persistence layer for the checker system:
- Storage interfaces (CheckPlanStorage, CheckerOptionsStorage,
  CheckEvaluationStorage, ExecutionStorage, ObservationSnapshotStorage,
  SchedulerStateStorage) in the usecase/checker package
- KV-based implementations for LevelDB/Oracle NoSQL/InMemory backends
- Integrate checker storage into the main Storage interface
- Add tidy methods for checker entities (plans, configurations,
  evaluations, executions, snapshots, observation cache) and
  secondary index cleanup
2026-04-15 19:30:13 +07:00
4bb19bf989 checkers: add map-based option validation for checker fields
Add ValidateMapValues() to the forms package for validating
checker option maps against field documentation (required fields,
allowed choices, type checking).
2026-04-15 19:30:13 +07:00
802d24c4b6 checkers: load external checker plugins from .so files
All checks were successful
continuous-integration/drone/push Build is passing
Scan -plugins-directory paths at startup, open each .so via plugin.Open,
look up the NewCheckerPlugin symbol from checker-sdk-go, and register the
returned definition and observation provider in the global checker
registries. A pluginLoader indirection keeps the door open for future
plugin kinds.
2026-04-15 19:30:13 +07:00
d5ec413b7d checkers: introduce checker subsystem foundation
Add the checker-sdk-go dependency and build the core checker
infrastructure:
- Domain model types: CheckTarget, CheckPlan, Execution,
  CheckEvaluation, CheckerDefinition, CheckerOptions,
  ObservationSnapshot, and associated interfaces
- Observation collection engine with concurrent per-key gathering
- Checker and observation provider registries (wrapping checker-sdk-go)
- WorstStatusAggregator for combining rule evaluation results
2026-04-15 19:30:13 +07:00
3f0ca0b37e tidy: delete User record when cleaning up unverified AuthUsers
When TidyUsers removes an AuthUser with unverified email and no login
after 7 days, the corresponding User record was left orphaned in the
database. Now DeleteUser is called before dropping the AuthUser.
2026-04-14 18:56:57 +07:00
90e4d30ae4 web: Make images occupy the background
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-14 09:08:47 +07:00
3163a10c45 web: add collapsible domain groups with persistent state
All checks were successful
continuous-integration/drone/push Build is passing
Add click-to-collapse and double-click-to-solo behavior on group
headers in ZoneList, with a chevron indicator. Collapsed state is
persisted in localStorage and cleared on login/logout.
2026-04-14 05:08:01 +07:00
197fd9c796 Redesign UI: modernize layout, login, resolver, and some components
Refresh the overall visual design across the frontend: floating labels
and centered card layout for auth pages, animated sidebar+results view
for the resolver, polished dropdown menus, toasts, and feedback widget,
and cleaner global styles (navbar shadow, border, transitions).
2026-04-14 05:08:01 +07:00
52e176c73a chore(deps): lock file maintenance
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-13 00:12:13 +00:00
effb588d3c fix: use one-way binding for record line rr prop
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-11 12:25:10 +07:00
e73ed40d5c fix: use validate instead of binding for zero-value fields
Switch ServiceMeta.Domain, ServiceMeta.Ttl, ServiceMeta.NbResources,
and ZoneMeta.DefaultTTL from binding:"required" to validate:"required".
This keeps them marked as required in the OpenAPI spec (swaggo reads
both tags) without gin rejecting valid zero values (0 for uint32,
"" for root domain).
2026-04-11 12:25:10 +07:00
99edd8a66c fix: use DomainCreationInput for domain creation endpoint and service
CreateDomain now takes a DomainCreationInput and returns the created
Domain, so the controller no longer needs to construct an intermediate
Domain struct and the response includes the server-assigned fields.

Fixes: https://github.com/happyDomain/happydomain/issues/44
2026-04-11 12:25:10 +07:00
5354c861c2 Improve README 2026-04-11 11:19:56 +07:00
4989e38fbc fix: migration: use safe type assertions in SRV record migration
Avoid potential panics from nil or missing fields when migrating SRV
records by using comma-ok type assertions and guarding against empty
name/proto values.
2026-04-11 11:19:48 +07:00
692a549437 tidy: drop auth users with unverified email and no login after one week 2026-04-11 03:21:44 +07:00
384a749b8c inmemory: remove unused fields and simplify test setup
All checks were successful
continuous-integration/drone/push Build is passing
The InMemoryStorage struct carried per-entity maps and fields that were
never used: all storage goes through the generic KV data map. Strip the
struct down to just mu + data, and update tests to use
inmemory.Instantiate() instead of manually wrapping with kv.NewKVDatabase.
2026-04-11 00:18:31 +07:00
1ae99b4e2e Update go deps and tidy
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-10 19:25:09 +07:00
8a65edc50a fix(deps): update module golang.org/x/crypto to v0.50.0
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-09 17:10:17 +00:00
c7d424725a fix(deps): update module github.com/coreos/go-oidc/v3 to v3.18.0
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-09 12:14:24 +00:00
4c6a0ae502 chore(deps): update dependency go to v1.26.2
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-09 11:15:04 +00:00
a31f78cd48 ci: sync frontend package version with git tag on tag builds
All checks were successful
continuous-integration/drone/push Build is passing
2026-04-07 15:30:21 +07:00
de6eb2b3b4 fix: add missing fields to zone mock in thiszone test
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
v0.7.0
The mock zone object was missing `services` and `last_modified` fields
required by the response transformer, causing Object.keys to fail on
undefined.
2026-04-05 22:23:52 +07:00
8e2e38757f fix: guard against undefined entry in domainLink helper
Some checks failed
continuous-integration/drone/push Build is failing
Add null checks to prevent runtime errors when the domain index entry
does not exist for the given identifier.
2026-04-05 22:08:46 +07:00
6dfe3f9d42 ci: run svelte-kit sync before generate:api in Drone pipelines
openapi-ts v0.95.0 now requires a valid tsconfig chain to resolve.
Since tsconfig.json extends .svelte-kit/tsconfig.json which is generated,
we need to run svelte-kit sync first to create it.
2026-04-05 22:07:44 +07:00
397e19b745 fix(deps): update module @hey-api/openapi-ts to v0.95.0
Some checks failed
continuous-integration/drone/push Build is failing
2026-04-04 22:22:06 +07:00
cae8658f61 web: Tighten TypeScript types and fix toast API across frontend
Replace `any` with precise types (unknown, Record<string, any>, specific
interfaces) in props, function signatures, and index signatures. Introduce
ServiceWithValue to bridge SDK's HappydnsService.Service from unknown to
its runtime shape. Simplify updateDomain to take explicit id + body params.
2026-04-04 22:22:06 +07:00
f92cab2abf web: Prefer pointer as grab in ZoneList 2026-04-04 22:16:27 +07:00
30506e9731 web: Fix state_referenced_locally warning in ZoneList
Replace $state + $effect pattern with $derived for localDomains to properly react to prop changes. Also reformat genGroups signature and sort callback indentation.
2026-04-04 22:16:27 +07:00
15f014cf5a web: Replace null defaults with undefined for optional props
Aligns optional prop types and defaults with TypeScript/Svelte 5 idioms
by dropping explicit null in favor of undefined throughout components.
2026-04-04 22:16:27 +07:00
b2e85cb9f2 web: Fix variable not declared as $state 2026-04-04 22:16:27 +07:00