feat(meshcore): region discovery from nearby repeaters — phase 3 (#3667)#3679
Conversation
Completes #3667: discover the regions/scopes served by nearby repeaters so users can pick a valid scope instead of guessing. Mechanism (firmware docs/payloads.md): a "regions request" is an ANON_REQ sub-type 0x01 sent to a repeater (CMD_SEND_ANON_REQ = 57); the repeater replies via PUSH_CODE_BINARY_RESPONSE (0x8C) with clock(4 LE) + a NUL-terminated, comma-separated ASCII list of region names ('*' = legacy null region). meshcore.js (ours and upstream) doesn't expose CMD 57, but it DOES parse the 0x8C reply, so we build the raw frame and match the reply by tag in the native backend — no fork change. - Native backend: `request_regions` bridge command — builds [57][pubkey:32][0x01] [0x00], awaits Sent(tag)+BinaryResponse(0x8C), parses clock + region names. - Manager: `discoverRegions()` — queries each repeater/room-server contact sequentially (tag-correlation requires it), de-dupes, drops the '*' wildcard, skips non-responders. Zero-hop/direct request → no scope assertion needed. - Route: POST /api/sources/:id/meshcore/regions/discover. - UI: "Discover regions from repeaters" button in the default-scope section; discovered regions render as chips that fill the scope field on click. - Tests: native-backend frame layout + reply parsing (clock/NUL/CSV); manager dedupe/sort, '*' filtering, non-repeater skip, non-responder tolerance. Coverage depends on repeaters in the contact list — the UI hints to run "Discover Repeaters" first (mirrors the official app; see upstream #1881). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
|
Claude finished @Yeraze's task —— View job PR Review: feat(meshcore): region discovery from nearby repeaters — phase 3Tasks
Overall AssessmentThis is a well-structured implementation of the region discovery feature. The protocol-level work is careful and correct, and the test coverage is solid. A few observations below.
|
…#3667) Address Claude review feedback on PR #3679: - Harden request_regions reply matching: only accept a BinaryResponse once the Sent ack has set our tag (tag===null no longer resolves on a stray reply). - /regions/discover now requires 'nodes' 'write' (it transmits radio frames), matching POST /discover instead of the weaker 'read'. - discoverRegions logs at debug when a repeater returns an error response (not just on throw). - UI: cross-disable the node-discovery and region-discovery buttons so overlapping radio requests can't be triggered; clear the suggestion chips once a scope is saved. - Test: discoverRegions returns empty (and queries nothing) on a non-companion device. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
|
Thanks! Addressed in 788792f:
Full suite green (7341 passed). |
|
Claude finished @Yeraze's task —— View job PR Review: feat(meshcore): region discovery from nearby repeaters — phase 3Tasks
Overall AssessmentThis is a clean, well-reasoned implementation that correctly addresses all feedback from the first review pass. The protocol framing is precise, the concurrency design is well-justified, and the new tests close every gap that was called out. Ready to merge from a code quality standpoint; the notes below are all minor.
|
|
Thanks — on the three remaining observations, all are intentional/already-handled, so no code change:
Calling this complete. |
Summary
Phase 3 of MeshCore region/scope support (#3667), completing the feature. Phases 1+2 (merged) let users set per-channel and default scopes; this lets them discover the regions nearby repeaters actually serve, so they pick a valid scope instead of guessing.
Mechanism
Per the firmware (
docs/payloads.md), a "regions request" is an ANON_REQ sub-type0x01sent to a repeater viaCMD_SEND_ANON_REQ (57). The repeater replies withPUSH_CODE_BINARY_RESPONSE (0x8C)=clock(4 LE)+ a NUL-terminated, comma-separated ASCII list of region names (*= legacy null region).meshcore.js (ours and upstream) doesn't expose command 57 — but it does parse the
0x8Creply. So we build the raw frame and tag-match the reply in the native backend. No meshcore.js fork change required.Changes
request_regionsbridge command: builds[57][pubkey:32][0x01][0x00], awaitsSent(tag) +BinaryResponse(0x8C), parses clock + region names.discoverRegions(): queries each repeater/room-server contact sequentially (the firmware tag only arrives on theSentack, so overlapping requests could cross-match), de-dupes, drops the*wildcard, tolerates non-responders. The request is zero-hop/direct → no scope assertion needed.POST /api/sources/:id/meshcore/regions/discover.Coverage note
Like the official app, coverage depends on which repeaters are in the contact list — the UI hints to run "Discover Repeaters" first (see upstream #1881).
Testing
tsctypecheck clean (server + frontend)*filtering, non-repeater skip, non-responder tolerance.Completes #3667 (Phases 1–3).
🤖 Generated with Claude Code