You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Kerykeion maintains two independently mutable NodeDb instances for the same live mesh: one inside MeshCollector for display/handshake state and a cloned copy inside PacketProcessor for topology and signal emission.
The collector therefore processes each received FromRadio once into its own state and then dispatches it again into the processor. Top-level NodeInfo frames require explicit mirroring to keep the second database current. The separation has already caused a security repair to protect only one copy before a second regression test was added for the other.
Verified against mainc8e671845adca3e5b57a205d08aca31eadbc6000.
Evidence
crates/kerykeion/src/collector.rs:70-108 gives MeshCollector its own Arc<Mutex<NodeDb>> and exposes it as the shared node database.
collector.rs:254-266 creates PacketProcessor by cloning the collector database into a new owned NodeDb; there is no shared state after construction.
collector.rs:227-250 explicitly mirrors top-level NodeInfo into the processor database because otherwise a runtime node learned by the collector is invisible to the processor.
collector.rs:465-500 handles every received message twice: process_packet updates the collector/display database, then dispatch_to_processor updates processor state and emits signals.
crates/kerykeion/src/processor.rs:48-78 gives PacketProcessor its own mutable NodeDb.
crates/kerykeion/src/processor_tests_attribution.rs:1-15 repeats that history in executable form: a second test file exists because the first fix protected the wrong/only-one copy.
No open issue owns convergence of the two databases.
Why this matters
NodeDb is not a cache of an immutable source; it is the authoritative live interpretation of node identity, reachability, SNR, hops, metrics, position, and last-seen state. Two owners create several failure modes:
a packet path added to one processor can be absent from the other;
security filtering and sentinel rejection must be implemented twice;
CLI/display state can disagree with the state used for topology and signal generation;
background tasks can read a different node snapshot from the main receive path; and
every new node field or update policy requires an inventory of both mutation graphs.
The #246 history demonstrates that this is already-diverged maintenance risk, not hypothetical DRY cleanup.
Desired correction
Choose one authoritative live NodeDb. Prefer making packet processing the owner and exposing read-only snapshots/views for CLI and background consumers, or share one actor/guarded database between collector and processor if that ownership better fits the runtime. Handshake discoveries and top-level NodeInfo frames should enter the same mutation path as packet-derived updates rather than be copied between stores.
Keep MeshTopology separate if it is genuinely a derived graph; the finding concerns duplicate ownership of the node database, not forced consolidation of every mesh data structure.
Done when:
one live NodeDb receives handshake, top-level node info, and packet-derived updates;
the receive loop does not independently mutate two node databases;
CLI/status/topology/signal consumers observe the same node state;
sentinel/identity/update policy has one production implementation;
the duplicate attribution regression files collapse to tests against one authority; and
no comment needs to describe one NodeDb as a copy or mirror of another.
Finding
Kerykeion maintains two independently mutable
NodeDbinstances for the same live mesh: one insideMeshCollectorfor display/handshake state and a cloned copy insidePacketProcessorfor topology and signal emission.The collector therefore processes each received
FromRadioonce into its own state and then dispatches it again into the processor. Top-levelNodeInfoframes require explicit mirroring to keep the second database current. The separation has already caused a security repair to protect only one copy before a second regression test was added for the other.Verified against
mainc8e671845adca3e5b57a205d08aca31eadbc6000.Evidence
crates/kerykeion/src/collector.rs:70-108givesMeshCollectorits ownArc<Mutex<NodeDb>>and exposes it as the shared node database.collector.rs:254-266createsPacketProcessorby cloning the collector database into a new ownedNodeDb; there is no shared state after construction.collector.rs:227-250explicitly mirrors top-levelNodeInfointo the processor database because otherwise a runtime node learned by the collector is invisible to the processor.collector.rs:465-500handles every received message twice:process_packetupdates the collector/display database, thendispatch_to_processorupdates processor state and emits signals.crates/kerykeion/src/processor.rs:48-78givesPacketProcessorits own mutableNodeDb.processor.rs:97-105documents that this database and topology are separate from the collector’s display-only copy and says Unauthenticated mesh source attribution lets any node spoof any NodeNum in the node DB #246’s original attribution fix guarded only the collector side.crates/kerykeion/src/processor_tests_attribution.rs:1-15repeats that history in executable form: a second test file exists because the first fix protected the wrong/only-one copy.Why this matters
NodeDbis not a cache of an immutable source; it is the authoritative live interpretation of node identity, reachability, SNR, hops, metrics, position, and last-seen state. Two owners create several failure modes:The #246 history demonstrates that this is already-diverged maintenance risk, not hypothetical DRY cleanup.
Desired correction
Choose one authoritative live
NodeDb. Prefer making packet processing the owner and exposing read-only snapshots/views for CLI and background consumers, or share one actor/guarded database between collector and processor if that ownership better fits the runtime. Handshake discoveries and top-levelNodeInfoframes should enter the same mutation path as packet-derived updates rather than be copied between stores.Keep
MeshTopologyseparate if it is genuinely a derived graph; the finding concerns duplicate ownership of the node database, not forced consolidation of every mesh data structure.Done when:
NodeDbreceives handshake, top-level node info, and packet-derived updates;NodeDbas a copy or mirror of another.