The previous click-to-copy behavior wasn't obvious to users. Show the
URL in a modal with an explicit copy button and a brief scrape_configs
example so users understand what the endpoint is for.
When switching between checkers via the sidebar, plan.enabled retained
the previous checker's values because the guard condition prevented
re-initialization. Reset all derived state eagerly on checkerId change
and always repopulate plan.enabled from fresh status.
- Move enable/disable toggle to card header (inverted to "Enable scheduling")
- Replace Save button with debounced autosave (700ms) with inline status indicator
- Show interval controls only when enabled; paused hint when disabled
- Remove obsolete no-schedule-yet alert and save button translation keys
The HTML placeholder attribute is rendered in plaintext even on
type="password" inputs, so an inherited secret value injected as a
placeholder was visible without toggling the eye button. Replace the
placeholder with bullets of the same length while the secret is hidden, and
reveal the real value only when the user explicitly toggles visibility.
Rules are now collapsed under the Advanced options toggle instead of
being always visible, and each rule's description is displayed as
helper text below the checkbox when available.
The GetCheckerOptions controller appends a synthetic positional carrying
resolved auto-fill values (consumed by RunCheckModal). splitPositionalOptions
was treating that last entry as the current scope, pushing actual stored
options into inheritedValues — they then showed as placeholders, broke
<select> value matching, and were sent as nil overrides on save. Callers now
pass the auto-fill key set so the synthetic positional is filtered out before
splitting.
Adds an explicit Disabled field on CheckPlan so users can pause a
checker's automatic execution without clearing per-rule state. The
scheduler skips Disabled plans alongside fully-disabled ones, and the
schedule card exposes a switch bound through the existing save path.
Switch the bulk toggle from every-enabled to some-enabled so the
"All" switch reflects an OR across rules: on when at least one is
active, off only when all are disabled.
Rule toggle switches now call a dedicated handleSavePlan() wrapper with
"rules-updated"/"rules-update-failed" messages, separate from the schedule
card's "Schedule saved" toast. CheckerScheduleCard.save() is split into a
raw export (no toasts) and an internal handleSave() used by its own button.
The SDK's new POST /definition returns per-rule precheck errors for the
current options. happyDomain now calls it (or the in-process equivalent
when no remote endpoint is configured) while building each
CheckerStatus, exposes the result as CheckerStatus.PrecheckFailures,
and the rules card in the UI disables the toggle and shows the reason
for any rule whose prerequisites are unmet.
Adds POST /users/:uid/new_auth so admins can provision a UserAuth for an
existing User without retyping the email; a fresh password is generated
server-side and returned in the response.
The engine now builds the rule-enable map up front, attaches it to the
ctx via sdk.WithEnabledRules so remote providers can skip optional work
for disabled rules, and fingerprints it as ObservationCacheEntry.
EnabledRulesHash. ObservationContext compares that hash against the
current execution's and bypasses the freshness window on mismatch, so a
re-enabled rule never reuses observations collected while it was off.
HTTPObservationProvider forwards the map onto ExternalCollectRequest so
out-of-process checkers see it on /collect.
Replace class?: string with class?: ClassValue across Svelte components,
adopting the idiomatic Svelte 5 array syntax (class={["base", className]})
instead of string interpolation for combining static and dynamic classes.
When opening an execution detail page while the execution is still
pending or running, defer fetching observations/results/metrics and
poll the execution status every 3s until it reaches a terminal state.
The loading view shows a "Running" label in the meantime.
When a check targets a specific service, resolve its subdomain from the
current zone and display the full hostname (e.g. www.example.com) in
the email subject rather than the bare zone domain (example.com).
Subject now reads "[happyDomain] example.com (dns-check) degraded: WARNING"
so recipients can triage by checker and direction without opening the email.
Both writer closures captured `t` by reference; reassigning `t` to the
HTML template before either closure executed made the text/plain part
render the HTML template. Also copy tplData into htmlData before setting
the HTML Content, preventing shared-map mutation between the two writers.
Snapshots were silently omitted from the backup export and never
restored, causing GetSnapshot lookups to fail after a restore.
Add ObservationSnapshots to the Backup model, wire ListAllSnapshots in
Backup() and RestoreSnapshot (new method that preserves the existing ID,
unlike CreateSnapshot) in Restore(). The observation cache is not
serialised — it is rebuilt from the restored snapshots by keeping the
most-recent snapshot per (target, key) pair.