Skip to content

Give Kerykeion one authoritative live NodeDb #483

Description

@forkwright

Finding

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 main c8e671845adca3e5b57a205d08aca31eadbc6000.

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.
  • processor.rs:97-105 documents 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-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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions