Commit Graph

556 Commits

Author SHA1 Message Date
Andreas Wrede 37b8e35a26 docs: add DARK_MODE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:34:59 -04:00
Andreas Wrede fa317a3b78 feat: add dark mode with light/dark/auto theme setting
Theme preference stored in localStorage (auto follows the OS setting).
The chosen data-theme attribute is applied synchronously in <head> to
avoid any flash of unstyled content. CSS custom properties handle all
surface, text, border and input colours across every page. The
Appearance section on the profile page lets each user switch modes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:33:37 -04:00
Andreas Wrede 8729fe7038 feat: sort hosts, thresholds, and channels alphabetically on settings page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 13:01:47 -04:00
Andreas Wrede f4231dd5f3 fix: preserve log message order when replaying history on connect
Send history messages newest-first from the server, tagged with
history=True so the client appends rather than prepends them, avoiding
reverse-chronological display on initial load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:18:05 -04:00
andreas c47576637f feat: suppress alerts for unwatched hosts
Hosts with watch: false in config no longer appear in the Alerts page
or nav bar alert counts. Events still appear in the Log of Events.
Hosts without a config entry default to watch: false.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 14:54:53 -04:00
Andreas Wrede 2b9523ec28 finetune tabe and font sizes 2026-05-14 06:29:00 -04:00
Andreas Wrede 610ad0af30 feat: add UNKNOWN level filter to Log of Events
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:01:57 -04:00
Andreas Wrede 69b5b410ed feat: replace Dynamic DNS YAML editor with a web form
Adds structured form fields for nsupdate_bin, rndc_key, and dyndomains
(comma-separated list). Wires list-type editable fields through the
generic stageFormSection path and adds DNS support to
apply_structured_section in configio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 07:12:44 -04:00
Andreas Wrede 8b2b0fd9d0 feat: add per-metric grace period input to thresholds settings page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 06:56:21 -04:00
Andreas Wrede 756b2323be version 5.3.6
Release / release (push) Successful in 5s
v5.3.6
2026-05-13 06:42:31 -04:00
Andreas Wrede 6e7156b42d chore: remove redundant license classifier from pyproject.toml
The license expression field (PEP 639) supersedes the classifier.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 06:42:19 -04:00
Andreas Wrede 928035df50 fix: move dependencies back under [project] in pyproject.toml
The key had drifted below [project.urls], making setuptools interpret it
as a URL entry and failing validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 06:37:14 -04:00
Andreas Wrede 0f90be659e fix: correct ZFS pool status threshold operator and add per-metric grace
The default zfs_monitor.*.status threshold used operator '>' with warning=1,
so a DEGRADED pool (status=1) never alerted (1 > 1 is false) and a FAULTED
pool (status=2) only triggered WARNING instead of CRITICAL.

Fix the operator to '>=' in THRESHOLD_DEFAULTS and the example config.

Also adds a per-metric grace period override (ThresholdConfig.grace) so
individual thresholds can bypass or shorten the global grace delay. Alerts
with grace=0 fire immediately on state change rather than waiting for a
second collection cycle. Sets grace=0 on zfs_monitor.*.status so pool
degradation alerts fire on the first data report after the event.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 06:33:06 -04:00
Andreas Wrede 4160e34a96 chore: remove commented-out step from release workflow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 00:02:24 -04:00
Andreas Wrede 6430d2ddf3 chore: add classifiers and project URL to pyproject.toml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 00:00:30 -04:00
Andreas Wrede 4b87a90e76 chore: declare license-files in pyproject.toml
Associates LICENSE.md with the package for pip/PyPI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:58:25 -04:00
Andreas Wrede 450814daca chore: remove docs/superpowers from repo
Add to .gitignore to keep local copies untracked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:56:56 -04:00
Andreas Wrede e7786ac5da chore: rename "CLAUDE. md" to CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:56:21 -04:00
Andreas Wrede fed71d97d6 chore: clean up dev scratch files from project root
- Remove rndc-key from tracking, add to .gitignore
- Move async_sms_send.py, demo_threshold.py, nagios_bad.sh to scripts/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:54:27 -04:00
Andreas Wrede ba96da9622 refactor: move loose test files out of project root
- tests/test_threshold.py: has proper pytest test functions
- scripts/test_*.py: manual run scripts with no test functions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:52:34 -04:00
Andreas Wrede 7f17ddc2ff chore: fix tox.ini to install dev deps from pyproject.toml
Replace the missing requirements-dev.txt reference with extras = dev,
which installs the [dev] optional dependencies declared in pyproject.toml.
Also remove skipsdist so tox installs the package before running tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:50:47 -04:00
Andreas Wrede 7750c5a303 chore: set author to Andreas Wrede in pyproject.toml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:49:46 -04:00
Andreas Wrede e58530df7d docs: add MIT license
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:45:55 -04:00
Andreas Wrede fe7143759c docs: rewrite README from source code
Replace the previous README with documentation derived from reading
the actual code, including a new section covering the C client
(scripts/c/hbc_mini.c).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 23:42:24 -04:00
Andreas Wrede 236b40cfe4 fix: email and domain normalize 2026-05-12 17:02:02 -04:00
Andreas Wrede 4e5bafd26c version 5.3.4
Release / release (push) Successful in 5s
v5.3.4
2026-05-12 15:06:24 -04:00
Andreas Wrede 817ae064af fix: run full reload after HTTP config publish, not just config.reload()
HTTP config-mutating endpoints (publish, rollback, channel CRUD, user
self-update) were calling config.reload() directly, which only refreshed
the in-memory config dict. This skipped re-applying host.dyn/host.watched
flags to live Host objects, so enabling dyndns via the UI had no effect
until a SIGHUP was sent.

Wire a reload_callback through http.start() that calls the same
reload_configuration() function used by the SIGHUP handler, ensuring
host attributes, notify module, users, and threshold checker are all
updated on every config publish.

Also fix unmatched quote in udp.py f-string log message.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 15:05:52 -04:00
Andreas Wrede a00282913b version 5.3.3
Release / release (push) Successful in 5s
v5.3.3
2026-05-12 14:34:58 -04:00
Andreas Wrede d699a29fa9 refactor: remove dyndnshosts/drophosts legacy config keys, fix DNS event logging
- Remove dyndnshosts legacy list; dyndns is now set per-host in the hosts section
- Remove drophosts config key and load-time deletion loop
- Simplify get_dyndnshosts() to only read per-host dyndns attributes
- Fix dns_update_worker to call eventlog with correct (host, level, msg) signature
- Log INFO/ERROR events per domain on each DNS update instead of one batched message
- Add logger to dns.py (was missing, causing NameError on update failure)
- Update README and tests to reflect removed config keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 14:34:11 -04:00
Andreas Wrede 4ce7eacfdd fix: remove container max-width and stop stretching inputs on settings page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 11:42:54 -04:00
Andreas Wrede 1cefc2676e feat: replace YAML editor with form UI for threshold configurations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 10:57:03 -04:00
Andreas Wrede 668a135e53 feat: replace multi-select fields with dual-panel picker on settings page
Replaces the 5 native <select multiple> fields (Managers, Monitors,
Threshold config, Channels in Hosts; Channels in Users) with a compact
picker widget: a truncated pill display with tooltip, and a click-to-open
panel split into Available / Selected columns for moving items between sides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 10:10:18 -04:00
Andreas Wrede 59e256a042 feat: add nav bar button to publish pending config changes
Shows an orange "Publish Config" button to the left of the alert-pie
for admin users when there are staged config changes. Uses localStorage
to persist staged changes across page navigations so the button appears
on any page, not just settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 09:32:32 -04:00
Andreas Wrede 708508157f feat: add host, level, and message filters to Log of Events
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 08:29:26 -04:00
Andreas Wrede f67fa9baff version 5.3.2
Release / release (push) Successful in 5s
v5.3.2
2026-05-12 08:16:04 -04:00
Andreas Wrede 588eb2a792 feat: retry DNS resolution indefinitely and add -4/-6 flags in hbc and hbc_mini.c
Mirror the same changes from hbc_mini.py: retry host resolution with
exponential backoff (5s→60s) instead of exiting on DNS failure, and add
mutually exclusive -4 / -6 flags to restrict connections to IPv4 or IPv6.

In hbc (main.py) the retry sleep is interruptible via the shutdown_event.
In hbc_mini.c signal handlers are moved before the resolution loop so
SIGINT/SIGTERM can break the retry during startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 08:15:53 -04:00
Andreas Wrede b907343e36 feat: retry DNS resolution indefinitely and add -4/-6 flags in hbc_mini
On startup, retry host resolution with exponential backoff (5s→60s) instead
of exiting when DNS fails. Add mutually exclusive -4 / -6 CLI flags to
restrict connections to IPv4 or IPv6 only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 08:07:54 -04:00
Andreas Wrede e50a3996ae fix: support list-valued threshold_config in hosts table
threshold_config in .hb.yaml can be a list (e.g. [local, zrepl]).
The hosts table was treating it as a single string, so the pre-selected
value never matched. Normalize to a list in settings.py, switch the
select to multiple, and fix the JS to collect all selected options.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 08:22:07 -04:00
Andreas Wrede e1056a0365 fix: derive hosts threshold config list from config file keys
Previously all_threshold_configs was built from the threshold_checker
object, which may not be populated at render time, leaving the select
empty. Read directly from config["threshold_configs"] instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 08:09:27 -04:00
Andreas Wrede 1dbe0f8e64 feat: replace YAML hosts editor with form-based CRUD table
Settings > Hosts now renders a table with per-column controls
(watch, dyndns, owner, managers/monitors multi-select, threshold
config, notification channels) instead of a raw YAML textarea.
Changes stage via the existing Publish flow like other form sections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 07:57:28 -04:00
Andreas Wrede 12e8812070 docs: update notification channel and API docs for form-based management
- NOTIFICATIONS.md: document owner/private fields, channel visibility
  rules, and user-created channels; add troubleshooting note for
  private channel visibility
- HTTP_API.md: add notification channel API endpoints table and full
  endpoint reference (GET types, GET/POST/PUT/DELETE channels)
- USERS.md: add missing PUT /api/0/users/me endpoint documentation
  with all three update modes (identity, channels, password)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 07:45:30 -04:00
Andreas Wrede 9b5d8ac9b1 fix: replace channel checkboxes in Users table with multi-select
The per-user notification channel selector in the admin settings Users
section was a column of checkboxes; replaced with a <select multiple>
for consistency with the profile chip picker and to reduce table width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 07:38:56 -04:00
Andreas Wrede 500d256d76 feat: replace YAML notification channel editor with form-based UI
Notification channels are now managed through a proper web form instead
of a raw YAML textarea. Any authenticated user can create channels; private
channels (owner-scoped) are hidden from other users. The user profile
channel selector becomes a tag/chip picker with a "My Channels" CRUD section.

- settings.py: add CHANNEL_TYPE_SCHEMAS for all 6 notifier types; channel
  section switches to section_mode="channels"; cards include owner/private/min_level
- configio.py: add apply_channel() and delete_channel() for per-entry CRUD
- notify.py: strip owner/private metadata before dispatching to drivers
- http.py: add GET/POST /api/0/notification_channels, PUT/DELETE /{name},
  GET /api/0/notification_channel_types; visibility helper filters private
  channels per user; PUT /api/0/users/me validates against visible channels
- settings.html: card grid with edit/delete per channel; add/edit modal
  with type dropdown and dynamically rendered type-specific fields
- profile.html: chip picker replaces checkbox list; My Channels section
  for creating/editing/deleting user-owned channels
- tests: update test_settings_sections, test_http_users_me; add
  test_notification_channels_api (16 new tests, 46 total passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 07:34:26 -04:00
Andreas Wrede a7a45bf8c3 fix: support plugin-level enabled: false in threshold config
Setting enabled: false at the plugin level (e.g. memory_monitor: {enabled: false})
was silently ignored because the non-dict value was skipped by the metric parser,
leaving THRESHOLD_DEFAULTS entries active.

- _parse_plugin_thresholds: detect plugin-level enabled/enable flag and delete
  all matching entries from target_dict (covers legacy and default config paths)
- _parse_multi_config named configs: inject disabled stubs from effective_defaults
  into raw_overrides so the merge step overwrites inherited defaults
- Accept 'enable' as a tolerated alias for 'enabled' in both code paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 17:40:29 -04:00
Andreas Wrede 3e9b052f71 fix: always populate glance-strip for all hosts on page load
fetchHostGlance was only called for the initially expanded host, leaving
all other hosts showing "—" until manually expanded. Now fetches glance
for every host-card on DOMContentLoaded and refreshes all (not just
expanded) on the 30s auto-refresh interval.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:13:10 -04:00
Andreas Wrede 7444262985 fix: fetch host info on initial page load
DOMContentLoaded was calling fetchHostGlance but not fetchHostInfo,
leaving the info-meta section stuck on "Loading…". Both the URL-hash
and default first-host paths now call fetchHostInfo and populate
infoCache on load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:08:37 -04:00
Andreas Wrede 3401cc0dbb version 5.3.1
Release / release (push) Successful in 6s
v5.3.1
2026-05-10 14:03:58 -04:00
Andreas Wrede ab0132a38d fix: correct THRESHOLD_DEFAULTS metric keys and add missing defaults
- Rename memory_monitor threshold key from 'percent' to 'memory_percent'
  so it matches exactly rather than relying on suffix stripping, which was
  causing swap_percent to be evaluated against the memory threshold
- Add swap_percent default thresholds (warning: 40%, critical: 75%)
- Add zfs_monitor pool capacity default thresholds (warning: 80%, critical: 90%)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:03:44 -04:00
andreas 9e389736f8 feat: show suffix-matched metric coverage in host info threshold table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 09:18:49 -04:00
andreas b64a2a9313 feat: move hbc_version and hbc_type out of os_info into host info section 2026-05-10 08:33:28 -04:00