Skip to content

Block coordinate traffic on configured event channels#11045

Open
ayysasha wants to merge 14 commits into
meshtastic:developfrom
ayysasha:feature/event-channel-coordinate-policy
Open

Block coordinate traffic on configured event channels#11045
ayysasha wants to merge 14 commits into
meshtastic:developfrom
ayysasha:feature/event-channel-coordinate-policy

Conversation

@ayysasha

@ayysasha ayysasha commented Jul 17, 2026

Copy link
Copy Markdown

Summary

This PR adds a compile-time event-channel privacy policy that prevents POSITION_APP, WAYPOINT_APP, and MAP_REPORT_APP packets from being transmitted, relayed, acknowledged, logged, or forwarded to MQTT on channels whose effective key matches USERPREFS_CHANNEL_0_PSK. Enable it by setting USERPREFS_BLOCK_POSITION_ON_EVENT_CHANNEL to true in userPrefs.jsonc; it defaults to USERPREFS_EVENT_MODE, emits no replacement packet, and leaves private-channel and PKI traffic unaffected.

  • identify configured event channels by matching their full effective AES key against USERPREFS_CHANNEL_0_PSK, independent of channel index or name
  • suppress POSITION_APP, WAYPOINT_APP, and MAP_REPORT_APP on event channels across phone ingress, local send, receive, duplicate/reliable relay, ACK, logging, and MQTT paths
  • preserve private-channel and PKI traffic, and leave behavior unchanged when the compile-time policy is disabled
  • default USERPREFS_BLOCK_POSITION_ON_EVENT_CHANNEL to USERPREFS_EVENT_MODE, while allowing an explicit override

The policy emits no replacement or empty position packet; blocked coordinate packets are not queued for transmission.

Testing

  • pio test -e coverage-event-policy -f test_position_precision — 23/23 passed
  • pio test -e coverage -f test_position_precision — 23/23 passed
  • pio run -e native — passed
  • event-policy native build with MESHTASTIC_EXCLUDE_TRACEROUTE=1 — passed
  • Trunk check on all 15 changed files — no new issues
  • git diff --check origin/develop...HEAD — clean

Hardware validation

Equivalent policy behavior was exercised on two ThinkNode M2 devices using the earlier master-based implementation: event-channel position sends were suppressed, private-channel sends succeeded, inbound coordinate packets were not stored or relayed, retries produced no relay, and direct coordinate packets requesting ACK received no ACK/NAK.

This exact develop forward port has not been reflashed to hardware; its validation is the native test/build matrix above. Additional device regression testing is welcome.

Scope

The Burning Mesh event configuration does not use ATAK or lost-and-found position reporting. This policy therefore covers the deployed coordinate-bearing port numbers listed above rather than changing those unrelated modules.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the listed reference devices.

Summary by CodeRabbit

  • New Features

    • Added an optional privacy policy that blocks location sharing on designated event channels.
    • Blocked location transmission, forwarding, reliable delivery, phone processing, and MQTT map reporting when the policy applies.
    • Preserved location sharing on private channels and for eligible encrypted traffic.
    • Event channels now use zero position precision for added privacy.
  • Bug Fixes

    • Improved duplicate and retry handling to prevent blocked packets from being retransmitted or acknowledged incorrectly.
  • Tests

    • Added comprehensive coverage for event-channel routing, phone handling, MQTT reporting, position precision, and retry behavior.

ayysasha and others added 6 commits July 17, 2026 02:40
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds compile-time event-channel coordinate privacy enforcement across mesh routing, phone ingress, reliable delivery, position precision, and MQTT reporting. It also centralizes channel/PKI decisions, updates routing reprocessing, and adds focused native test coverage and CI execution.

Changes

Event channel policy

Layer / File(s) Summary
Policy contracts and core routing
src/mesh/Channels.*, src/mesh/Router.*, src/mesh/PositionPrecision.cpp
Adds event-channel identification, coordinate-port classification, effective-channel resolution, PKI eligibility centralization, and blocking during packet transmission, decoding, reception, and precision selection.
Routing and external delivery gates
src/mesh/FloodingRouter.*, src/mesh/NextHopRouter.cpp, src/mesh/ReliableRouter.cpp, src/mesh/PhoneAPI.cpp, src/mqtt/MQTT.cpp
Gates reprocessing, rebroadcasts, reliable sends, phone ingress, MQTT forwarding, and map reports according to event-channel policy.
Policy behavior and regression coverage
test/test_event_channel_*/, test/test_nexthop_routing/test_main.cpp, test/test_position_precision/test_main.cpp, test/test_mqtt/MQTT.cpp
Adds coverage for event and private channels, PKI exceptions, retries, acknowledgements, precision, MQTT publication, opaque packets, and packet ownership.
Policy build and test wiring
userPrefs.jsonc, variants/native/portduino/platformio.ini, .github/workflows/test_native.yml, test/native-suite-count
Documents the preference, adds a policy-specific native environment, runs its tests, uploads both reports, and updates the suite count.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested labels: enhancement

Suggested reviewers: thebentern, nomdetom

Sequence Diagram(s)

sequenceDiagram
  participant PhoneAPI
  participant Router
  participant Channels
  participant Radio
  PhoneAPI->>Router: submit coordinate packet
  Router->>Channels: resolve effective channel and event status
  Channels-->>Router: event-channel policy result
  alt blocked coordinate
    Router-->>PhoneAPI: return NOT_AUTHORIZED and notification
  else allowed coordinate
    Router->>Radio: send packet
  end
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: blocking coordinate traffic on configured event channels.
Description check ✅ Passed The description includes summary, testing, hardware validation, scope, and attestations, matching the template well.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ayysasha

Copy link
Copy Markdown
Author

CI follow-up: the branch-caused Native PlatformIO failure has been fixed in 6c941f3. The remaining check-label job requires an accepted PR label; I do not have permission to add labels. Could a maintainer please add the enhancement label?

ayysasha and others added 5 commits July 17, 2026 17:29
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@ayysasha

Copy link
Copy Markdown
Author

Added behavioral unit coverage in 9d35291..470c40b: real Router TX/RX paths, NextHop/Flooding/Reliable relay-retry-ACK paths, StreamAPI/PhoneAPI retry-state handling, and MQTT publication/map reporting. The policy-enabled and gate-off five-suite matrices each pass 121/121 cases; native build and targeted Trunk checks pass. The new suites are registered in the policy CI environment and canonical native suite count.

@ayysasha
ayysasha marked this pull request as ready for review July 18, 2026 04:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/mesh/FloodingRouter.cpp (1)

95-104: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Restrict policy-driven decoding to event-channel candidates.

Setting shouldDecode = true decrypts every private and PKI duplicate/upgraded packet when the policy is enabled. Resolve the effective channel first, while independently retaining traceroute decoding.

Proposed change
 bool shouldDecode = false;
 `#if` USERPREFS_BLOCK_POSITION_ON_EVENT_CHANNEL
-    shouldDecode = true;
-#elif !MESHTASTIC_EXCLUDE_TRACEROUTE
-    shouldDecode = traceRouteModule != nullptr;
+    shouldDecode = !p->pki_encrypted && channels.isEventChannel(getEffectiveChannelIndex(p));
+#endif
+#if !MESHTASTIC_EXCLUDE_TRACEROUTE
+    shouldDecode = shouldDecode || traceRouteModule != nullptr;
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/FloodingRouter.cpp` around lines 95 - 104, Update the decoding
decision around shouldDecode in the duplicate handling path to resolve the
packet’s effective channel first and enable policy-driven decoding only for
event-channel candidates, rather than every packet. Keep traceroute-driven
decoding independently enabled when traceRouteModule is available, including
builds where traceroute is not excluded, and preserve the existing perhapsDecode
flow.
test/test_position_precision/test_main.cpp (1)

274-276: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep changed comments within the two-line limit.

  • test/test_position_precision/test_main.cpp#L274-L276: condense the gate-behavior explanation.
  • test/test_position_precision/test_main.cpp#L408-L410: reflow the private-key explanation.
  • test/test_nexthop_routing/test_main.cpp#L610-L612: remove or shorten the decorative heading.

As per coding guidelines, “Keep code comments minimal—one or two lines maximum.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/test_position_precision/test_main.cpp` around lines 274 - 276, Shorten
the gate-behavior comment at test/test_position_precision/test_main.cpp lines
274-276 to no more than two lines while retaining its meaning; reflow the
private-key explanation at lines 408-410 to the same limit; and remove or
shorten the decorative heading at test/test_nexthop_routing/test_main.cpp lines
610-612. No code changes are required.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mesh/FloodingRouter.cpp`:
- Around line 109-112: Update the LOG_WARN call in
FloodingRouter::reprocessPacket to format the getFrom(p) node ID with the
hexadecimal 0x%08x specifier instead of decimal %u, keeping the existing
arguments and message context unchanged.

---

Nitpick comments:
In `@src/mesh/FloodingRouter.cpp`:
- Around line 95-104: Update the decoding decision around shouldDecode in the
duplicate handling path to resolve the packet’s effective channel first and
enable policy-driven decoding only for event-channel candidates, rather than
every packet. Keep traceroute-driven decoding independently enabled when
traceRouteModule is available, including builds where traceroute is not
excluded, and preserve the existing perhapsDecode flow.

In `@test/test_position_precision/test_main.cpp`:
- Around line 274-276: Shorten the gate-behavior comment at
test/test_position_precision/test_main.cpp lines 274-276 to no more than two
lines while retaining its meaning; reflow the private-key explanation at lines
408-410 to the same limit; and remove or shorten the decorative heading at
test/test_nexthop_routing/test_main.cpp lines 610-612. No code changes are
required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f43b6709-be09-429e-a95c-e81d2bdc9e8c

📥 Commits

Reviewing files that changed from the base of the PR and between cfecef5 and 470c40b.

📒 Files selected for processing (20)
  • .github/workflows/test_native.yml
  • src/mesh/Channels.cpp
  • src/mesh/Channels.h
  • src/mesh/FloodingRouter.cpp
  • src/mesh/FloodingRouter.h
  • src/mesh/NextHopRouter.cpp
  • src/mesh/PhoneAPI.cpp
  • src/mesh/PositionPrecision.cpp
  • src/mesh/ReliableRouter.cpp
  • src/mesh/Router.cpp
  • src/mesh/Router.h
  • src/mqtt/MQTT.cpp
  • test/native-suite-count
  • test/test_event_channel_phone_api/test_main.cpp
  • test/test_event_channel_router/test_main.cpp
  • test/test_mqtt/MQTT.cpp
  • test/test_nexthop_routing/test_main.cpp
  • test/test_position_precision/test_main.cpp
  • userPrefs.jsonc
  • variants/native/portduino/platformio.ini

Comment on lines 109 to +112
// Fatal decoding error, we can't do anything with this packet
LOG_WARN(
"FloodingRouter::reprocessPacket: Fatal decode error (state=%d, id=0x%08x, from=%u), can't check for traceroute",
static_cast<int>(decodedState), p->id, getFrom(p));
return;
LOG_WARN("FloodingRouter::reprocessPacket: decode error (state=%d, id=0x%08x, from=%u)",
static_cast<int>(decodedState), p->id, getFrom(p));
return true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Format from as a node ID.

Use 0x%08x rather than decimal %u.

-            LOG_WARN("FloodingRouter::reprocessPacket: decode error (state=%d, id=0x%08x, from=%u)",
+            LOG_WARN("FloodingRouter::reprocessPacket: decode error (state=%d, id=0x%08x, from=0x%08x)",

As per coding guidelines, “Format node and packet IDs as 0x%08x.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Fatal decoding error, we can't do anything with this packet
LOG_WARN(
"FloodingRouter::reprocessPacket: Fatal decode error (state=%d, id=0x%08x, from=%u), can't check for traceroute",
static_cast<int>(decodedState), p->id, getFrom(p));
return;
LOG_WARN("FloodingRouter::reprocessPacket: decode error (state=%d, id=0x%08x, from=%u)",
static_cast<int>(decodedState), p->id, getFrom(p));
return true;
// Fatal decoding error, we can't do anything with this packet
LOG_WARN("FloodingRouter::reprocessPacket: decode error (state=%d, id=0x%08x, from=0x%08x)",
static_cast<int>(decodedState), p->id, getFrom(p));
return true;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/FloodingRouter.cpp` around lines 109 - 112, Update the LOG_WARN call
in FloodingRouter::reprocessPacket to format the getFrom(p) node ID with the
hexadecimal 0x%08x specifier instead of decimal %u, keeping the existing
arguments and message context unchanged.

Source: Coding guidelines

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants