feat(alerts): ntfy.sh notification channel (v0.21.0-beta)

Closes #93.

Routing push notifications through email ingestion was a workaround. ntfy is now
a first-class channel alongside Slack, Discord, Telegram and email, using the
same alert_channels row and the same dispatch switch.

Built to cover the whole plausible configuration space rather than waiting on the
reporter's answers, so no config migration is needed once they arrive:

  - server_url is operator-supplied and defaults to https://ntfy.sh, so a
    self-hosted instance works — the likely case for infrastructure alerting
  - both of ntfy's auth schemes: an access token (preferred; scopable and
    revocable) or username/password, with none required for an open topic
  - optional click_url deep-links each notification to the device it refers to

Published as JSON to the server root rather than POST /{topic} with header
metadata: the header form is ASCII-only and these titles carry per-event emoji.

Severity maps onto ntfy's priority scale so the channel stays worth being woken
by — 4 (breaks through do-not-disturb) for device_offline, log_error and
CPU/memory pressure; 2 for recoveries and discoveries; 3 for everything else.
The event type is attached as a tag so a client can be filtered to wake only for
chosen events without needing a channel per event.

Secrets follow the existing pattern: token and password are added to
SENSITIVE_KEYS, so they are masked on read and the mask placeholder is restored
to the stored value on write rather than overwriting it.

The type column is a CHECK constraint rather than a lookup table, so widening it
means dropping and recreating the constraint; done idempotently for existing
installs.

Note on trust: server_url lets an admin point the channel at an internal address.
That is the same exposure the existing Slack and Discord webhook URLs already
have, and only an admin can configure any of them. Restricting it would break the
self-hosted case this feature is mostly for.

Verified against the real ntfy.sh — a test alert arrived with the correct title,
emoji, body, priority, tag and click URL; masking verified to hide the token on
read while preserving it across a save that did not retype it. 13 unit tests
cover priority mapping, both auth schemes, URL normalisation, and rejection of
a missing topic or non-http server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2GT-Rich
2026-08-19 17:02:56 -07:00
co-authored by Claude Opus 5
parent b03ea87f11
commit 19617e8357
10 changed files with 296 additions and 12 deletions
+11 -2
View File
@@ -2,7 +2,7 @@
A self-hosted, full-stack network management platform for MikroTik devices. Monitor, configure, and manage your entire MikroTik infrastructure — routers, switches, and wireless access points — from a single web interface.
![Version](https://img.shields.io/badge/version-0.20.1_Beta-blue)
![Version](https://img.shields.io/badge/version-0.21.0_Beta-blue)
![License](https://img.shields.io/badge/license-AGPLv3-blue)
![Docker](https://img.shields.io/badge/docker-compose-2496ED?logo=docker&logoColor=white)
![TypeScript](https://img.shields.io/badge/TypeScript-5.3-3178C6?logo=typescript&logoColor=white)
@@ -327,7 +327,16 @@ Configurable alert rules with cooldown periods:
- New device discovered
- Configuration changed (drift detection)
Alert delivery channels: **Email**, **Slack**, **Discord**, **Telegram**
Alert delivery channels: **Email**, **Slack**, **Discord**, **Telegram**, **ntfy**
**ntfy** (`https://ntfy.sh` or your own instance) is configured with a topic and, optionally, an
access token or username/password — a publicly-writable topic lets anyone spoof your alerts, so
protecting it is worth the extra field. Alert severity maps onto ntfy's priority scale so the
notifications that mean something is *down* (device offline, log errors, CPU/memory pressure) arrive
at priority 4 and break through a phone's do-not-disturb, recoveries and discoveries arrive quietly
at 2, and everything else sits at the default 3. Each notification is tagged with its event type, so
a client can be filtered to wake only for the events you care about. Set the optional **Manager URL**
and notifications become tappable, opening the device they refer to.
### Maintenance Windows
- Schedule planned downtime windows per device or group of devices to suppress alerts automatically