Files
meshcore-analyzer/docs/release-notes/v3.14.0.md
T
efitenandClaude Opus 5.5 9dbc287579 docs: release notes for v3.14.0 (#2143)
Release notes and the CHANGELOG entry for v3.14.0. The release workflow
reads `docs/release-notes/v3.14.0.md` from the tagged commit as the
release body, so this lands before the tag.

23 commits since v3.13.1: 13 fix, 8 feat, 1 ci, and this docs commit.
The headline is optional user accounts (#2128). "Read this before
upgrading" covers the new limits on unauthenticated endpoints, the
`traffic_share_score` drop (#2117), the region filter window (#2114) and
the config file mode (#2126).

After merge: tag this commit as `v3.14.0` once its `:edge` image is
built, then dispatch the CI/CD pipeline on the tag.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:19:04 +02:00

6.3 KiB

v3.14.0

23 commits since v3.13.1: 13 fix, 8 feat, 1 ci, 1 docs (these notes). Eight feats and no breaking change, so minor.

The headline is optional user accounts (#2128). They are off by default: without a userManagement block in config.json, nothing in this section changes anything.

Read this before upgrading

These change what a running instance does without being asked.

  • Limits on unauthenticated endpoints. Requests above them now get an error instead of an answer:
    • GET /api/packets?nodes= takes at most 50 entries and answers 400 above that (#2120). 12,000 entries took 1.3 s per request under the store's read lock.
    • POST /api/decode and POST /api/packets/observations cap the request body (#2119). One 100 MB request raised the process's memory on a test instance.
    • GET /api/nodes/{pubkey}/reach runs at most 2 cold scans at once and answers 429 with Retry-After: 5 beyond that (#2127). Cached answers are not affected.
    • The ingestor truncates observer ids, names and other status fields to 128 characters and IATA codes to 16, and strips control characters (#2123). The /neighbors report only accepts 64-hex pubkeys and a scope list of up to 256 bytes (#2122).
  • traffic_share_score drops after the upgrade (#2117). The score counted a transmission once per observation through a relay, so it grew with uptime until many relays sat at 1.0. It now counts distinct transmissions. Expect lower values; they no longer drift.
  • The /api/nodes region filter covers the packet store's window (#2114), the same window the rest of the UI shows, instead of all database history. A node heard in a region only before that window no longer matches.
  • The geo-filter save keeps config.json's file mode (#2126). A 0600 config stayed 0600 only until the first save; now it stays 0600.

Optional user accounts

Turn them on with a userManagement block. Setup and every option are in docs/user-guide/accounts.md. Accounts live in a separate users.db; the server still opens the analyzer database read-only.

  • Accounts and roles (#2129). Register with an email address, activate through a mailed link that also sets the password, log in. Roles user and admin. Admins manage users and use the operator actions (geo-filter, backup, perf reset) without the shared API key. Mail goes through Brevo, with delivery status.
  • Settings sync (#2130). A logged-in user's own nodes, favorites, theme, customizer settings and filters follow them to every device. Private channel keys and decrypted messages are never synced.
  • Admin area (#2138). #/admin with an overview of what needs attention (stuck activations, bouncing mail, password guessing, a dropped MQTT source), the user table, and an audit log that now records logins.
  • Hashtag channel proposals (#2139, closes #2092). Logged-in users propose a channel; after an admin approves it, the ingestor decrypts it without a restart and it is listed for everyone. Opt in with userManagement.channelProposals. Every approved key is tried on each GRP_TXT no key opens: 204 to 216 µs per packet with 320 keys, 272 to 320 µs with 128 approved keys added.
  • Mail notifications for watched nodes (#2140). "Notify me" on a node page sends one mail when that node goes offline, comes back or reports a low battery, using the thresholds the node page uses. Admins can add new foreign nodes and observers going offline. Bundled per user, 20 mails per user and 100 per instance per rolling 24 hours, one-click unsubscribe. Opt in with userManagement.notifications.
  • Data export and users.db backup (#2141). "Download my data" gives a user one JSON file with everything stored about their account, credentials excluded. The server keeps daily users.db snapshots (7 by default) and admins can download one.

Fixes

  • Regional /api/nodes queries no longer exhaust the database pool (#2114, closes #2101). A regional node count took 154.8 s on a 10.3 GB database and tied up the readers. The region set now comes from the packet store: 37 ms uncached in the benchmark, then cached for 30 s. A follow-up matches observers by id, so a changed observer region applies at once (#2115).
  • Escaping: observer IATA, name and id and node names in eight render sinks (#2118), and the route string on the unknown-route page (#2124).
  • CDN scripts are pinned with integrity hashes (#2121): chart.js@4.5.1, leaflet.heat@0.2.0, swagger-ui-dist@5.33.1.

Interface

  • Path hash size on each channel message (#2089): 1-byte, 2-bytes or 3-bytes before the scope chip.
  • RF noise-floor layer on the Mobile RX coverage page (#2113), for instances with clientRfSamples enabled.
  • Node details explain the packet and observation counts (#2132, closes #2131).

CI

  • Tests and the image build run side by side (#2135, closes #2134). Only the GHCR push waits for all of them, and E2E runs in 3 shards.

Issues closed

  • #2092 Feature proposal: user-suggested shared hashtag channels with admin approval and revoke
  • #2101 bug: Regional /api/nodes queries exhaust the SQLite connection pool
  • #2128 No user accounts: settings are tied to one browser and operator actions to a shared API key
  • #2131 ui(nodes): explain transmission and observation counts in node details
  • #2134 CI takes ~30 min because every job waits for the previous one

#2092 and #2128 were closed by hand after their pull requests merged; the others through the pull request.

Contributors

Pull request authors: @efiten (11), @nullrouten0 (9), @dborup (1), @n30nex (1), @sylr (1).

Issue reporters: @efiten (2), @dborup (1), @mannkind (1), @n30nex (1).

No co-authors other than tooling are credited in the commits.

Upgrade notes

  • No manual migration step. With user management off, no new file or table is created.
  • With user management on, users.db is created next to the analyzer database (or at userManagement.dbPath) and migrated at startup; backups/ is created next to it.
  • channelProposals and notifications are opt-in under userManagement; the backup is on by default when user management is on and can be turned off with userManagement.backup.enabled: false.