Adds an optional, loopback-only plain-TCP Reticulum interface so archy can be reached by Aurora (or any TCP-based RNS/LXMF client) without physical LoRa hardware, alongside the existing serial/RNode path (unchanged).
Fixes several real bugs surfaced while validating the interop end-to-end against live RNode hardware:
Serial probes (Meshcore/Meshtastic/RNode) never deasserted DTR/RTS on open, which can spuriously reset ESP32-S3 native-USB boards (e.g. Heltec V3/V4) mid-handshake.
auto_detect_and_open/open_preferred_path tried Meshcore and Meshtastic before Reticulum, adding ~10s of unnecessary probing (and, on hardware with slower boot chatter, contributing to missed detections) before a real RNode ever got a turn.
Reticulum peer identity binding: a Reticulum-carried ARCHY:n: identity announce created a second, wrongly-keyed MeshPeer row instead of binding the identity onto the correct RNS-hash-keyed radio peer, so native LXMF sends resolved to a peer keyed by the wrong identifier space and always failed with "Unknown Reticulum prefix ... peer hasn't announced yet" — confirmed live between two real nodes that could see each other's adverts but never exchange a message.
RNode KISS-detect read window was 800ms; confirmed on real hardware that a legitimate, correctly-flashed RNode can take just over 1s to answer, past the old deadline — widened to 2.5s.
Test plan
cargo test -p archipelago — 108/108 mesh tests pass, no regressions
Deployed live to two real RNode nodes (archy-x250-exp, archy-x250-pa); confirmed bidirectional LXMF delivery (event: delivered) in both directions after these fixes plus aligning both radios' spreading factor (separate hardware misconfiguration, unrelated to this code, fixed via the archy-rnodeconf tooling in the stacked PR)
probe_rnode_detects_real_hardware (ignored, real-hardware test) passes against the fixed timeout
## Summary
- Adds an optional, loopback-only plain-TCP Reticulum interface so archy can be reached by Aurora (or any TCP-based RNS/LXMF client) without physical LoRa hardware, alongside the existing serial/RNode path (unchanged).
- Fixes several real bugs surfaced while validating the interop end-to-end against live RNode hardware:
- Serial probes (Meshcore/Meshtastic/RNode) never deasserted DTR/RTS on open, which can spuriously reset ESP32-S3 native-USB boards (e.g. Heltec V3/V4) mid-handshake.
- `auto_detect_and_open`/`open_preferred_path` tried Meshcore and Meshtastic before Reticulum, adding ~10s of unnecessary probing (and, on hardware with slower boot chatter, contributing to missed detections) before a real RNode ever got a turn.
- Reticulum peer identity binding: a Reticulum-carried `ARCHY:n:` identity announce created a *second*, wrongly-keyed `MeshPeer` row instead of binding the identity onto the correct RNS-hash-keyed radio peer, so native LXMF sends resolved to a peer keyed by the wrong identifier space and always failed with "Unknown Reticulum prefix ... peer hasn't announced yet" — confirmed live between two real nodes that could see each other's adverts but never exchange a message.
- RNode KISS-detect read window was 800ms; confirmed on real hardware that a legitimate, correctly-flashed RNode can take just over 1s to answer, past the old deadline — widened to 2.5s.
## Test plan
- [x] `cargo test -p archipelago` — 108/108 mesh tests pass, no regressions
- [x] Deployed live to two real RNode nodes (archy-x250-exp, archy-x250-pa); confirmed bidirectional LXMF delivery (`event: delivered`) in both directions after these fixes plus aligning both radios' spreading factor (separate hardware misconfiguration, unrelated to this code, fixed via the archy-rnodeconf tooling in the stacked PR)
- [x] `probe_rnode_detects_real_hardware` (ignored, real-hardware test) passes against the fixed timeout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Review (pre-merge): LGTM — merging (with #71 already folded in). Highlights and one tracked caveat:
Probe reorder (Reticulum first) is justified with an actual hardware observation (Meshcore/Meshtastic handshake bytes leaving a real RNode unresponsive), and the DTR/RTS deassert + settle is applied consistently across all three serial open paths. The 800ms→2500ms PROBE_READ_TIMEOUT bump has a concrete measurement (~1.05s on Heltec V4 fw 1.86) behind it.
TCP interop is genuinely additive: reticulum_tcp: None leaves the serial path untouched, the server bind is loopback-gated in BOTH Python and Rust (defense in depth), and it's deliberately not exposed via mesh.configure. The #[ignore]d end-to-end test spawning two real daemons is a nice touch.
⚠️Caveat to track (not blocking): the in-band ARCHY: identity blob in an RNS announce is claim-based — any RNS identity can assert any archy ed25519 pubkey, there's no proof-of-possession in that blob — and refresh_contacts now prefers the in-band value over a previously bound arch_pubkey_hex. A hostile announce could re-bind a contact row to a victim's pubkey and get merged into their conversation by group_peer_twins (their signed traffic would still fail verification, but thread-level spoofing/confusion is possible). Suggest a follow-up: only accept an in-band rebind when it matches the existing binding or the slot is empty, or add a signed-announce challenge. Filed mentally against the mesh-signing workstream (§C mesh preimage work is adjacent).
Post-merge, main gets a build + mesh-suite run on .116 before the next fleet deploy.
**Review (pre-merge):** LGTM — merging (with #71 already folded in). Highlights and one tracked caveat:
- Probe reorder (Reticulum first) is justified with an actual hardware observation (Meshcore/Meshtastic handshake bytes leaving a real RNode unresponsive), and the DTR/RTS deassert + settle is applied consistently across all three serial open paths. The 800ms→2500ms `PROBE_READ_TIMEOUT` bump has a concrete measurement (~1.05s on Heltec V4 fw 1.86) behind it.
- TCP interop is genuinely additive: `reticulum_tcp: None` leaves the serial path untouched, the server bind is loopback-gated in BOTH Python and Rust (defense in depth), and it's deliberately not exposed via `mesh.configure`. The `#[ignore]`d end-to-end test spawning two real daemons is a nice touch.
- ⚠️ **Caveat to track (not blocking):** the in-band `ARCHY:` identity blob in an RNS announce is *claim-based* — any RNS identity can assert any archy ed25519 pubkey, there's no proof-of-possession in that blob — and `refresh_contacts` now *prefers* the in-band value over a previously bound `arch_pubkey_hex`. A hostile announce could re-bind a contact row to a victim's pubkey and get merged into their conversation by `group_peer_twins` (their *signed* traffic would still fail verification, but thread-level spoofing/confusion is possible). Suggest a follow-up: only accept an in-band rebind when it matches the existing binding or the slot is empty, or add a signed-announce challenge. Filed mentally against the mesh-signing workstream (§C mesh preimage work is adjacent).
Post-merge, `main` gets a build + mesh-suite run on .116 before the next fleet deploy.
Reviewed and verified: Aurora Reticulum TCP interop (optional plain-TCP Reticulum interface for radio-less interop) plus mesh/RNode reliability fixes — DTR/RTS deassert before serial probes (ESP32-S3 native-USB reset), Reticulum/RNode probed before Meshcore/Meshtastic in auto-detect, peer identity bound directly instead of name-matching, and the KISS-detect read window widened 800ms→2.5s. Includes the #71 rnodeconf packaging via e64e5615. Branch updated with latest main (83352707), clean merge. Merging into main.
Reviewed and verified: Aurora Reticulum TCP interop (optional plain-TCP Reticulum interface for radio-less interop) plus mesh/RNode reliability fixes — DTR/RTS deassert before serial probes (ESP32-S3 native-USB reset), Reticulum/RNode probed before Meshcore/Meshtastic in auto-detect, peer identity bound directly instead of name-matching, and the KISS-detect read window widened 800ms→2.5s. Includes the #71 rnodeconf packaging via e64e5615. Branch updated with latest main (83352707), clean merge. Merging into main.
chaum
merged commit c6b9e5d0c6 into main2026-07-06 12:07:12 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
auto_detect_and_open/open_preferred_pathtried Meshcore and Meshtastic before Reticulum, adding ~10s of unnecessary probing (and, on hardware with slower boot chatter, contributing to missed detections) before a real RNode ever got a turn.ARCHY:n:identity announce created a second, wrongly-keyedMeshPeerrow instead of binding the identity onto the correct RNS-hash-keyed radio peer, so native LXMF sends resolved to a peer keyed by the wrong identifier space and always failed with "Unknown Reticulum prefix ... peer hasn't announced yet" — confirmed live between two real nodes that could see each other's adverts but never exchange a message.Test plan
cargo test -p archipelago— 108/108 mesh tests pass, no regressionsevent: delivered) in both directions after these fixes plus aligning both radios' spreading factor (separate hardware misconfiguration, unrelated to this code, fixed via the archy-rnodeconf tooling in the stacked PR)probe_rnode_detects_real_hardware(ignored, real-hardware test) passes against the fixed timeout🤖 Generated with Claude Code
Review (pre-merge): LGTM — merging (with #71 already folded in). Highlights and one tracked caveat:
PROBE_READ_TIMEOUTbump has a concrete measurement (~1.05s on Heltec V4 fw 1.86) behind it.reticulum_tcp: Noneleaves the serial path untouched, the server bind is loopback-gated in BOTH Python and Rust (defense in depth), and it's deliberately not exposed viamesh.configure. The#[ignore]d end-to-end test spawning two real daemons is a nice touch.ARCHY:identity blob in an RNS announce is claim-based — any RNS identity can assert any archy ed25519 pubkey, there's no proof-of-possession in that blob — andrefresh_contactsnow prefers the in-band value over a previously boundarch_pubkey_hex. A hostile announce could re-bind a contact row to a victim's pubkey and get merged into their conversation bygroup_peer_twins(their signed traffic would still fail verification, but thread-level spoofing/confusion is possible). Suggest a follow-up: only accept an in-band rebind when it matches the existing binding or the slot is empty, or add a signed-announce challenge. Filed mentally against the mesh-signing workstream (§C mesh preimage work is adjacent).Post-merge,
maingets a build + mesh-suite run on .116 before the next fleet deploy.Reviewed and verified: Aurora Reticulum TCP interop (optional plain-TCP Reticulum interface for radio-less interop) plus mesh/RNode reliability fixes — DTR/RTS deassert before serial probes (ESP32-S3 native-USB reset), Reticulum/RNode probed before Meshcore/Meshtastic in auto-detect, peer identity bound directly instead of name-matching, and the KISS-detect read window widened 800ms→2.5s. Includes the #71 rnodeconf packaging via e64e5615. Branch updated with latest main (83352707), clean merge. Merging into main.