feat: connect-scripts + opt-in route gossip - #125
Merged
Conversation
Two related changes that compose:
**Connect-scripts** automate the operator's manual
"C nodeA / C nodeB / DAPPS" sequence for reaching a far-end DAPPS
peer through a chain of bare packet nodes that don't speak DAPPS or
NET/ROM. The script lives on the neighbour row as an ordered list of
(send, expect) steps; the daemon plays it over the AGW connection
before falling into the DAPPSv1 prompt. Probe and poll paths use the
same script for consistency. Dashboard form takes the script as
SEND|EXPECT[|TIMEOUT] one step per line; controller validates the
final step lands on DAPPSv1>.
**Route gossip** piggybacks a `routes` exchange on otherwise-open
sessions (push, probe, poll) when a per-(local, remote) staleness
gate allows. Receiver imports advertised destinations into
`learnedroutes` with `Source = "gossip"`; existing failure-counter
machinery handles invalidation. Advertiser filters: only routes with
ConsecutiveFailures=0 that the daemon has actually used; never
re-export gossip-imported rows (avoids distance-vector loops);
manual neighbours always advertised (highest trust). Bounded by
RouteGossipStalenessHours (default 6, 0 disables) - no scheduled
transmission, only piggybacks.
The two compose: a connect-script unblocks the cold-start case (A
manually configured to reach C through a chain), and the routes
piggyback then propagates further reach beyond that initial pair
(C tells A about destinations behind C without further operator
config).
Wire additions:
- DAPPSv1: new `routes` command. Server emits `route <dest> hops=N
ageSeconds=N` per line, `end` terminator. Forward-compatible:
unknown KVs ignored, daemons that don't implement it return
`eh?\n` and senders learn to stop trying.
- BackhaulRoute carries a ConnectScript when the resolved neighbour
has one; intermediate forwarders see only an opaque session.
Schema additions:
- DbNeighbour.ConnectScriptJson
- DbLearnedRoute.Source ("traffic" | "gossip", default "")
- DbRouteGossipState (per-(local, remote) last-pulled timestamp)
- SystemOptions.RouteGossipStalenessHours
Tests:
- ConnectScriptTests: parse round-trip, runner happy path, timeout,
EOF mid-script, substring boundary across reads.
- RouteGossipTests: staleness gate (never-pulled / recent / elapsed
/ disabled), upsert priority (gossip vs traffic), self-route
rejection, gossip-replaces-gossip on next-hop change.
Docs:
- New docs/multi-hop.md covering the through-non-DAPPS-intermediates
scenario end-to-end.
- docs/implement.md: new `routes` verb section with wire example +
emission filter.
- docs/discovery-and-routing.md: route gossip section + cross-link
to multi-hop.
- docs/configure.md: RouteGossipStalenessHours entry.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two composing changes:
Connect-scripts automate the operator's manual `C nodeA / C nodeB / DAPPS` chain for reaching a far-end DAPPS peer through a chain of bare packet nodes that don't speak DAPPS or NET/ROM. Script lives on the neighbour row as a list of (send, expect) steps; the daemon plays it before falling into the DAPPSv1 prompt. Used by forwarder, probe, and poll paths.
Route gossip piggybacks a new `routes` command on otherwise-open sessions (push / probe / poll), bounded by a per-(local, remote) staleness gate. Imported routes land in `learnedroutes` with `Source="gossip"`; existing failure-counter machinery handles invalidation. Advertiser filter suppresses unproven routes and never re-exports hearsay (avoids distance-vector loops).
These compose: a connect-script unblocks the cold-start case A→C through bare nodes; gossip then propagates further-reach destinations beyond the manually configured pair.
What's new
Test plan
🤖 Generated with Claude Code