mirror of
https://github.com/gadgethd/ukmesh.git
synced 2026-09-02 17:43:44 +00:00
1.9 KiB
1.9 KiB
Canonical node identity
Why one physical device can appear as multiple nodes, and how the stack merges them at the data layer (not in the UI).
The problem
nodes is keyed by the exact 64-hex node_id. Two failure modes create
ghost rows / "repeater not showing data":
- A device that re-keys (or advertises a one-nibble-corrupted key) becomes a separate row — same name, near-identical keys (GNOME-MSG-RPT ×3, 2E0MTU RPT Hilperton ×2).
- MQTT status rows carry the OBSERVER key while advert/position rows carry the node's own key — one device's status and position live under DIFFERENT rows.
Every flow (history, adverts, owner dashboard, links, aggregates) queries exact IDs, so data appears split/stale and the owner dashboard lists repeaters multiple times.
The fix
backend/src/db/nodeIdentity.ts+ migrations 036/037: evidence-based canonical identity merging at the repository layer. Canonical views return one row per device withidentity_source_ids(the merged member keys).- Perf: canonical views are wrapped in a materialized CTE (migration 037);
/api/node-status/latestresolves canonical members first, then reads per member via the(node_id, time)index. A naive canonical projection over the 5.6M-row telemetry view was >8s; the fixed path is ~1.5s. - Owner dashboard: the owner API exposes
canonicalId+membersfor authorized keys; the UI collapses same-name identities into one entry with the member key list.
False-merge guard (hard-won)
- Active-to-active packet-pairing alone is NOT identity proof — colocated
families named
Dunston-1/2/3,NorthMesh RPT-1/2,Reach Yagi E/NWWmust stay separate. - Differing ordinal/directional suffixes = hard ambiguity, never merge.
- Metadata-only observer rows DO qualify for merging.
Diagnose
SELECT name, public_key, last_seen, advert_count
FROM nodes WHERE name ILIKE '<name>';