Skip to content

Use signed plaintext for licensed remote Admin#6184

Draft
RCGV1 wants to merge 2 commits into
meshtastic:mainfrom
RCGV1:codex/licensed-signed-admin
Draft

Use signed plaintext for licensed remote Admin#6184
RCGV1 wants to merge 2 commits into
meshtastic:mainfrom
RCGV1:codex/licensed-signed-admin

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 10, 2026

Copy link
Copy Markdown
Member

Closes #6183

Design: meshtastic/design#123
Firmware dependency: meshtastic/firmware#10972

Summary

  • select channel 0 for remote Admin when the connected local node is in licensed mode, so requests use plaintext transport with no PKI public key;
  • keep self-Admin, normal-mode PKI/admin-channel fallback, and unknown-local compatibility behavior unchanged;
  • determine the transport from the connected local node only, never from the destination node;
  • preserve the existing Admin session/passkey flow for mutations and awaited requests.

This is a transport/UI alignment for the existing XEdDSA signing path. It does not add a new authentication protocol or weaken firmware authorization. Firmware remains responsible for verifying the packet signature, matching the exact verified key against security.admin_key[], and enforcing mutation sessions.

Validation

  • ./gradlew :core:data:spotlessApply :core:data:spotlessCheck :core:data:detekt :core:data:jvmTest
  • independent dedicated security review approved exact commit 11c9c2a83245c8b3b77211616c7d13816c87a147;
  • focused rerun: 27/27 CommandSenderImplTest tests passed with JDK 21.

Tests cover licensed getters, mutation passkey preservation, awaited session requests, normal PKI, self, unknown-local fallback, and destination licensed-state non-influence.

Draft / hardware status

This remains draft until firmware#10972 is validated with two licensed RF nodes. Required hardware checks include signed plaintext getter/session/mutation/reply traffic, rejection of unauthorized or stale-session mutations, and confirmation that normal-mode PKI behavior is unchanged.

Summary by CodeRabbit

  • Bug Fixes
    • Licensed local nodes now send administrative messages as signed plaintext on channel 0.
    • Licensed administrative updates now include the required session passkey.
    • Protocol-level requests continue to avoid PKI and use the correct non-PKI channel behavior.
  • Tests
    • Expanded admin message and admin-await coverage for combinations of local/destination licensing and key availability, asserting expected signed-plaintext vs PKI/encrypted packet behavior.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c67e1e3-81f1-4db6-a9d5-386aad1fb6dd

📥 Commits

Reviewing files that changed from the base of the PR and between 4376126 and 11c9c2a.

📒 Files selected for processing (2)
  • core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt
  • core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt
  • core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt

📝 Walkthrough

Walkthrough

Licensed local nodes now send remote Admin traffic as signed plaintext on channel 0. Existing normal-mode PKI behavior remains intact, with tests covering mutations, session requests, self-destination handling, and fallback cases.

Changes

Licensed Admin transport

Layer / File(s) Summary
Admin channel selection
core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt
Licensed local nodes select channel 0 for signed plaintext Admin packets, while protocol-level PKI restrictions and fallback behavior are documented.
Admin packet behavior tests
core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt
Expanded tests capture and validate plaintext licensed packets, session requests, mutations, normal PKI behavior, self-destination handling, and unknown-mode fallback.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • meshtastic/design#123 — Defines the signed-plaintext licensed Admin transport behavior implemented here.
  • meshtastic/Meshtastic-Apple#2067 — Covers the corresponding licensed-local Admin transport change in the Apple client.
  • meshtastic/firmware#10971 — Addresses the firmware-side licensed signed-plaintext Admin behavior paired with this client change.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: signed plaintext Admin transport for licensed remote nodes.
Linked Issues check ✅ Passed The changes implement licensed-local Admin transport selection on channel 0 and add tests covering the required licensed, normal, self, and unknown cases.
Out of Scope Changes check ✅ Passed The PR stays focused on Admin transport selection and related tests, with no obvious unrelated code changes.

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

@RCGV1

RCGV1 commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@RCGV1

RCGV1 commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

The labeler check requires a repository label that this contributor account cannot apply. A maintainer will need to add the appropriate feature/enhancement label; implementation CI is still running independently.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt (1)

102-108: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the duplicated documentation phrase.

Line 106 ends with Protocol-level requests, and Line 107 starts with the same phrase. Remove the duplicate so the KDoc clearly describes the PKI fallback behavior.

Proposed fix
-     * is appropriate, except licensed local nodes use signed plaintext on channel 0. Protocol-level requests
-     * Protocol-level requests must NOT use PKI. Relay nodes need to read or modify the inner payload. For example,
+     * is appropriate, except licensed local nodes use signed plaintext on channel 0.
+     * Protocol-level requests must NOT use PKI. Relay nodes need to read or modify the inner payload. For example,
🤖 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
`@core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt`
around lines 102 - 108, Remove the repeated “Protocol-level requests” phrase in
the KDoc above the channel-resolution method, keeping a single occurrence while
preserving the explanation that such requests must not use PKI and fall back to
the node’s heard-on channel.
🧹 Nitpick comments (1)
core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt (1)

260-296: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert the session passkey on the await path.

This test verifies acceptance, plaintext transport, and want_response, but a regression in sendAdminAwait could still omit or alter session_passkey without failing. Configure a non-empty passkey, decode the captured AdminMessage, and assert it.

Proposed test enhancement
         configureNodes(nodes)
+        val passkey = "session-passkey".encodeUtf8()
+        every { sessionManager.getPasskey(DEST_NODE) } returns passkey
         var capturedPacket: MeshPacket? = null
         ...
-        assertTrue(requireNotNull(capturedPacket).decoded?.want_response == true)
+        val packet = requireNotNull(capturedPacket)
+        assertTrue(packet.decoded?.want_response == true)
+        val adminMessage = AdminMessage.ADAPTER.decode(requireNotNull(packet.decoded).payload)
+        assertEquals(passkey, adminMessage.session_passkey)
🤖 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
`@core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt`
around lines 260 - 296, Enhance
sendAdminAwait_licensedSessionRequest_usesSignedPlaintextPacket by configuring a
non-empty session passkey, decoding the captured AdminMessage from the packet,
and asserting that its session_passkey matches the configured value. Preserve
the existing acceptance, plaintext transport, and want_response assertions.
🤖 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.

Outside diff comments:
In
`@core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt`:
- Around line 102-108: Remove the repeated “Protocol-level requests” phrase in
the KDoc above the channel-resolution method, keeping a single occurrence while
preserving the explanation that such requests must not use PKI and fall back to
the node’s heard-on channel.

---

Nitpick comments:
In
`@core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt`:
- Around line 260-296: Enhance
sendAdminAwait_licensedSessionRequest_usesSignedPlaintextPacket by configuring a
non-empty session passkey, decoding the captured AdminMessage from the packet,
and asserting that its session_passkey matches the configured value. Preserve
the existing acceptance, plaintext transport, and want_response assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 219b98cc-6ec3-4297-83c1-21ad3bc38b18

📥 Commits

Reviewing files that changed from the base of the PR and between a3aa976 and 4376126.

📒 Files selected for processing (2)
  • core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/CommandSenderImpl.kt
  • core/data/src/commonTest/kotlin/org/meshtastic/core/data/manager/CommandSenderImplTest.kt

@RCGV1

RCGV1 commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

Addressed both CodeRabbit suggestions in 11c9c2a: removed the duplicated KDoc phrase and strengthened the awaited licensed Admin test to decode and verify the exact destination-scoped session passkey. Focused 27/27 tests and formatting pass; the full GitHub validation matrix is green except the maintainer-only labeler. @coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

@RCGV1 Thanks for the update — glad the duplicated KDoc phrase and the destination-scoped session passkey assertion in the awaited licensed Admin test are sorted out. I'll take a fresh look at commit 11c9c2a now.

(=^・ω・^=)

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[2.8.0] Select signed plaintext transport for licensed remote Admin

2 participants