mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-07-11 23:38:51 +00:00
f12911dcc9
Firmware 1.16 publishes a `repeat: on|off` flag in the MQTT /status
JSON (confirmed by cwichura on the issue; see
MQTTMessageBuilder.cpp:58 in agessaman/MeshCore
mqtt-bridge-implementation-flex). Listener-only observers
(repeat:off) by firmware contract never relay packets, so they
cannot legitimately be a hop in someone else's resolved path.
Pipeline:
* internal/dbschema: idempotent `can_relay BOOLEAN DEFAULT 1`
migration on observers, plus AssertReady probe (server fatal-logs
if absent). Mirrored in cmd/ingestor/db.go CREATE TABLE for fresh
DBs.
* cmd/ingestor: `extractObserverMeta` accepts `repeat` as bool,
case-insensitive string (`on|off|true|false|yes|no`), or numeric
0/1; missing field → nil → COALESCE preserves prior column value
(back-compat with legacy observers). Plumbed through
UpsertObserverAt and the prepared upsert statement.
* cmd/server: GetNonRelayObserverPubkeys + new prefixMap.markNonRelay
drop matching candidates inside resolveWithContext. Filter is
applied at the top of the resolver so all 4 tiers see the
pruned candidate set. ObserverResp.CanRelay is surfaced to
/api/observers and /api/observers/{id}; GetNodeHealth enriches
the per-observer rows with can_relay so the node-detail badge
works. Probe-and-fall-back when can_relay column is absent
(legacy test fixtures).
* public/: listener vs repeater pill on observers list,
observer detail Relay stat card, and node-detail Heard By table.
CSS pill styles inherit existing theme vars.
Green for the test added in the prior red commit:
TestResolveWithContext_ExcludesNonRelayObservers_Issue1290.
Back-compat preserved: legacy observers (no `repeat` field) keep
the default can_relay=1 and remain candidates.
cross-stack: justified — backend persists firmware-side `repeat` hint to a new observers column, frontend surfaces the listener/repeater status as a badge on the observers list and node-detail Heard By table per the issue's UI acceptance criterion.