Skip to content

v0.4.2

Choose a tag to compare

@github-actions github-actions released this 21 Sep 08:33
· 25 commits to main since this release

What changed

Take this one if you have ever waited for a restart to make a setting
count.
Saved settings now apply to the running daemon — channels, escalation,
rules, quiet hours, hooks and consoles — and so does a config.yaml you edit
by hand. Only the listen addresses still need the daemon stopped.

Also fixes two things reported from a live site: time zones could not be set at
all on Windows, and every Network offline incident claimed the device had been
down for three minutes.

Added

  • Silence an alarm from the alarm. A card for something you have decided
    you do not want to hear about — a camera on a failing PoE port, a door sensor
    being worked on — now carries Silence…, which writes the ignore rule for
    you and closes the incident.

    The rule is built from the incident, not from anything the page sends, and it
    matches exactly that alarm: that condition, from that device, on that source.
    Nothing wider. It is an ordinary rule: it appears in Settings › Rules and is
    removed there, and the audit record names it, so "why was I not told about
    that camera" has an answer months later.

    A critical alarm cannot be silenced this way, and the refusal is in the
    API rather than only in the page. Quiet hours never apply to critical either.
    If a critical alarm really should be silenced, the rule can be written in
    Settings, deliberately, with the whole rule list in front of you.

Changed

  • Saved settings take effect immediately. Channels, escalation ladders,
    rules, quiet hours and inbound hooks were all built once when the daemon
    started and never rebuilt, so every save updated the file, updated the
    screen, and left the running process deciding by the old configuration —
    with nothing anywhere saying the two had parted company. A restart was the
    only way to close the gap, and a restart is not a neutral act: it drops every
    console connection and re-polls everything.

    The worst of it was invisible. A channel enabled and saved was a channel this
    daemon had never heard of: "ntfy is not enabled" when you pressed Test,
    contradicting the screen you were looking at — and the same stale set
    delivered the real alarms, so it would have been told nothing at 3am. A new
    inbound hook's URL returned the same 404 as a mistyped token until you
    restarted.

    A change that cannot be applied is refused rather than half-applied, and says
    which subsystem kept its old configuration and that a restart will close the
    gap.

    Consoles too, and a console nobody touched keeps its connection. Protect
    holds a WebSocket, a backoff ladder and the table that turns an update frame
    into a clear; saving an unrelated setting no longer costs any of them. Which
    sources are unchanged is decided by what each was built from — host,
    application, that application's key, the pinned fingerprint — rather than by
    its name, because every source of an application shares one name and a
    corrected API key would otherwise be taken for the broken source it replaces.

    A config.yaml edited by hand is applied too, a few seconds after you
    finish editing it — the setup guide tells you to edit that file, so the
    documented path was the one that silently did nothing. The log says when a
    change was applied, and says why if the file will not load.

    The listen addresses still need a restart — a socket already bound cannot
    be moved under the connections using it. That is now the only thing that
    does, and the Web section offers the restart itself, only when one of those
    addresses actually changed. Everywhere else, a save says it is in effect.

Fixed

  • Every Network offline incident claimed the device had been down for three
    minutes.
    Three minutes is the threshold — how long a device must be seen
    down before it counts as an outage at all — and the incident quoted that
    constant instead of measuring anything. Access points that had been off for
    weeks were reported as three-minute outages.

    It now says how long the device has actually been down. And when the device
    was already down at the first poll — which is every pre-existing outage,
    every time the daemon restarts — it says that instead, because the age of
    that outage is genuinely unknown: this API carries no events and no timestamp
    on a device, so the only clock available is our own, which started at the
    restart. An incident that quotes it reads as something that has just broken.

  • On Windows, every time zone name was refused. Setting quiet hours to
    America/New_York — the example printed beside the field — failed, while
    UTC worked, which reads as the slash in the name breaking the field. It was
    not the slash: those two are simply the only names that resolve without a
    time zone database, and Windows has none. The binary fell back to a copy
    inside a Go installation, which no machine running a release has.

    Worse than a rejected field: quiet hours are checked when the configuration
    loads, so a zone written into config.yaml by hand refused the daemon's
    start outright, and the site was then watched by nothing.

    The database now travels inside the binary, which also covers a Linux install
    whose image carries no tzdata package. It costs 402KB.

    The site's time zone is not only about quiet hours — it is the clock every
    alert is announced in, so anyone running on Windows who left it blank has
    been getting times in the server's zone.

Verifying this release

Every binary is signed. Verification instructions, including how to
rebuild from source and compare hashes, are in
docs/RELEASING.md.

Linux / macOS — cosign (keyless, no key to trust in advance):

cosign verify-blob notifymatrix-linux-amd64 \
  --bundle notifymatrix-linux-amd64.sigstore.json \
  --certificate-identity-regexp '^https://github\.com/suburbazine/Unifi-Notification-Matrix/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Download the .sigstore.json next to the binary; it carries the
signature, the certificate and the transparency-log proof. Keep
--certificate-identity-regexp — without it cosign verifies a
signature from anyone.

Build provenance (any platform):

gh attestation verify notifymatrix-linux-amd64 --repo suburbazine/Unifi-Notification-Matrix

Windows: the .exe is Authenticode-signed and timestamped.
Right-click → Properties → Digital Signatures, or:

Get-AuthenticodeSignature .\notifymatrix-windows-amd64.exe

This is source-available software under the
PolyForm Noncommercial License 1.0.0. Commercial use
requires a licence: licensing@xtremission.com

Full Changelog: v0.4.1...v0.4.2