Skip to content

Releases: MeshCore-Beacon/beacon-server

v1.5.4

Choose a tag to compare

@github-actions github-actions released this 24 Jun 15:11
4860921

Fixes

  • Packet Observation Duplication - The packet observations were being constrained as unique on observer, packet hash and the heard at TS. The TS has been removed and a migration is in place to clean up bad data.

Full Changelog: v1.5.3...v1.5.4

v1.5.3

Choose a tag to compare

@github-actions github-actions released this 20 Jun 17:41
86b0549

Features

  • Discovery request/response parsing — Beacon now parses DISCOVER_REQ/DISCOVER_RESP control payloads from the mesh, feeding directly into neighbor data.
  • Neighbor SNR tracking — a new optional snr column on node_neighbors, now populated from three independent sources:
    • discovery responses observed by Beacon
    • zero-hop adverts seen directly by observers
    • hop pairs derived from TRACE packets
  • Observer online check uses last seen — ingest now factors in an observer's last-seen timestamp when determining online status, rather than relying solely on connection state.

Fixes

  • Node summary neighbor counts — deduplicated neighbor counts in node summaries that were previously inflated by duplicate rows.
  • Release image publishing — fixed the GitHub Actions release workflow so built images are pushed to the public registry correctly. (Thanks, @MrAlders0n!)

Maintenance

  • Bumped meshcore-go to v1.0.8.
  • SECURITY: Bumped github.com/go-chi/chi/v5 from v5.2.2 to v5.2.4 (dependabot).
  • Documented the remaining parsed ingest payload structs.
  • Added the new neighbor snr field to the swagger docs.

Full Changelog: v1.5.2...v1.5.3

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 15 Jun 22:28
f67fc3b

Testing

This release is primarily a testing overhaul, bringing project coverage from minimal to ~46% with a solid foundation across all major layers.

Infrastructure

  • Introduced sqlc.Querier interface in db.Store, enabling mock-based testing of the database layer without a real PostgreSQL connection
  • Added gomock-generated mock for sqlc.Querier at db/sqlc/mock
  • Converted stubReader in handlers tests to a configurable struct with function fields, eliminating the need for a separate funcReader type
  • CI coverage filtering now correctly excludes generated code (db/sqlc, docs, iatadb/gen) for accurate badge reporting

Coverage by package

  • db — store mapping logic, pagination, nil pointer handling, conditional field mapping, type conversions across channels, observers, nodes, packets, traces, routes, scopes, stats, and IATAs
  • internal/api/handlers — validation paths and happy paths across all handlers including messages, packets, observers, nodes, stats, routes, scopes, and traces
  • internal/cachegetOrSet cache hit/miss/error/corrupt-entry behaviour, TTL resolution fallback chain, node and observer invalidation
  • internal/config — YAML loading, config seeding, default resolution extracted into testable Resolve function
  • internal/hub — full runtime behaviour including broadcast, subscription lifecycle, lagged notification, OR-scope semantics
  • internal/ingest — pure function coverage for payload parsing, transport code derivation, capability detection, observer type normalisation
  • internal/keystore — key derivation, fingerprinting, store lookup, EntryExists (moved from main)
  • internal/scopestore — load, replace, copy-on-read semantics
  • internal/background — scheduler task execution and context cancellation
  • internal/ws — IP limiter acquire/release/cleanup logic

Refactoring

  • config.Resolve() extracted from main.go to derive runtime defaults with fallback chain — now tested and used at startup
  • keystore.EntryExists() moved from main.go into the keystore package where it belongs

Full Changelog: v1.4.1...v1.5.0

v1.4.1 assets only

Choose a tag to compare

@446564 446564 released this 12 Jun 18:29
8c0591c

v1.4.0

Choose a tag to compare

@446564 446564 released this 12 Jun 18:00
3d49503

Features

  • Background task scheduler — periodic maintenance tasks now run on independent configurable intervals via a new internal/background package. Intervals are set per-task under the background: config key; all default to 1h.
  • Route and neighbor reconfirmation — a new background task periodically prunes known_routes and node_neighbors rows that have become stale or ambiguous: routes where any hop has departed node_short_ids or whose prefix now resolves to multiple nodes, and neighbors under the same conditions.

Fixes

  • Neighbor recording — neighbors are now only recorded when the resolved first-hop node is a repeater or room. Previously a prefix collision could cause a companion or other non-infrastructure node to be written as a neighbor. Thanks to @gadgethd for the contributing fix to IATA seeding that triggered this investigation.
  • IATA seedingUpsertIATADetails is now a true upsert, correctly updating existing records rather than silently doing nothing on conflict. Contributed by @gadgethd .
  • Graceful shutdown — added a timeout to the shutdown sequence to prevent possible hangs on exit.

Maintenance

  • Switched to dedicated CodeQL action.
  • Corrected route list handler cursor documentation.
  • Fixed broken README API reference chart.
  • Minor code cleanup: renamed mustEnvgetEnv, fixed view refresh comment, added note on node type helper.

Contributors

Welcome and thank you to @gadgethd — first contribution to Beacon!

v1.3.1

Choose a tag to compare

@446564 446564 released this 11 Jun 23:00
23e016e

Traces & Pings

Single-hop traces are now classified as pings and tagged accordingly. The /traces list response now includes the path and SNR values from the most complete observation of each trace, making it possible to assess signal quality and hop progression at a glance without opening the detail view. A new type query parameter allows filtering traces by TRACE or PING.

Routes

Single-hop routes are no longer stored — direct links are already captured by neighbor relationships, making them redundant.

Nodes

knownNeighborCount added to node summaries, and publicKey added to node neighbor responses.

Database Migrations

Migrations are now embedded in the binary and applied automatically on startup, removing the dependency on external tooling or container entrypoints. Existing deployments will bootstrap cleanly on first run.

Full Changelog: v1.3.0...v1.3.1

BUGFIX: v1.2.1

Choose a tag to compare

@446564 446564 released this 10 Jun 20:49
c7d2d11

Just a silly bug in a query for radio preset stats.

v1.2.0

Choose a tag to compare

@446564 446564 released this 10 Jun 20:23
6fef4be

New features

CORS support

  • Configurable CORS headers for cross-origin frontend deployments

Node type breakdown

  • New GET /api/v1/stats/node-types endpoint returning node counts by type (companion, repeater, room server, sensor)
  • Supports the same multi-IATA and region filtering as all other stats endpoints

Multi-IATA and region filtering on stats endpoints

  • All /stats/* endpoints now accept iatas, iata, regionId, and region query params
  • Previously only a single exact-match IATA was supported
  • Top nodes chart now returns data correctly in the default all-regions view

Bug fixes

Observer telemetry

  • Timestamps were being returned in seconds instead of milliseconds — now consistent with the rest of the API
  • Bucketed telemetry (6h, 24h intervals) was grouping by hour-of-day rather than by time window, causing incorrect bucket boundaries and near-zero deltas in the 30-day view
  • Running total fields (airtime_tx_pct, airtime_rx_pct, receive_errors) were being averaged across buckets instead of computing the delta — now correctly returns increase per bucket

Maintenance

  • Removed unused queries
  • Updated dependencies (SHOULDERS.md)
  • CodeQL security scanning via GitHub integration

Full Changelog: v1.1.0...v1.2.0

v1.1.0 Redis!

Choose a tag to compare

@446564 446564 released this 09 Jun 21:15
afa152e

v1.1.0 — Redis caching layer

This release adds an optional Redis-backed caching layer that reduces redundant
PostgreSQL reads for read-heavy, slow-changing endpoints.

What's new

  • Redis cache layer (internal/cache) — a CachedReader wraps the database
    store and transparently caches responses using a generic getOrSet helper with
    graceful degradation. If Redis is unavailable, all reads fall through to
    PostgreSQL with no impact on availability.
  • Explicit cache invalidation — node and observer cache entries are
    invalidated immediately on upsert from the ingest path, keeping detail
    responses accurate despite caching.
  • TTL-based expiry for stats and reference data, with a per-category
    override system and a global fallback. Defaults to 1h, aligned with the
    materialized view refresh cycle.
  • Fully optional — set REDIS_ADDR to enable. Unset, Beacon behaves
    exactly as before.

Configuration

Add to .env:

REDIS_ADDR=localhost:6379
REDIS_PASSWORD=
REDIS_DB=0

Add to config.yaml (all optional, defaults to 1h):

cache:
  ttl: "1h"
  ttls:
    stats: "1h"
    reference: "1h"
    nodes: "1h"
    observers: "1h"

v1.0.4

Choose a tag to compare

@446564 446564 released this 09 Jun 16:23
2669ad5

[v1.0.4] — 2026-06-09

Security

Fix no bounds check on region IDs.

Full Changelog: v1.0.3...v1.0.4