Skip to content

fix(reticulum): RNode TCP keepalive + macOS BLE pairing UX#698

Merged
rinchen merged 4 commits into
mainfrom
runr
Jul 20, 2026
Merged

fix(reticulum): RNode TCP keepalive + macOS BLE pairing UX#698
rinchen merged 4 commits into
mainfrom
runr

Conversation

@rinchen

@rinchen rinchen commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Overlay rsReticulum RNode TCP activity keepalive so Wi‑Fi RNodes do not idle-FIN (~6s) while waiting on upstream fix: send RNode TCP activity detect() keepalives ratspeak/rsReticulum#15.
  • Harden macOS BLE RNode pairing: surface Admin Start pairing PIN in-panel, extend connect grace/hints to 60s for the OS passkey window, latch blePairingTimedOut into Connection + Diagnostics, and debounce pairing-transition reconnect thrash via rsReticulum overlay.
  • Update troubleshooting/docs and i18n so wrong-PIN / blank radio display / empty macOS Bluetooth list guidance matches the new path.

Test plan

  • Fresh clone / pnpm run update applies both rsReticulum overlays (rnode-tcp-activity-keepalive, ble-rnode-pairing-transition-debounce)
  • Wi‑Fi RNode stays connected through idle periods that previously dropped around ~6s
  • Admin → Start pairing shows large in-panel PIN + blank-display warning (not Meshtastic 123456)
  • During OS passkey entry, Connection stays in connecting/grace (~60s) without reconnect thrash
  • Wrong/missed PIN surfaces blePairingTimedOut banner + diagnostics row; Forget/re-pair recovers
  • pnpm run test:run (or at least sidecar issue tracker / diagnostic / flasher-related tests) passes

Summary by CodeRabbit

  • New Features
    • Added a “pairing pending” Bluetooth UI state with improved PIN display and entry guidance.
    • Added BLE pairing-timeout detection with per-interface alerts plus updated diagnostics rows.
    • Added retry debounce for BLE pairing-transition disconnects and activity keepalive for TCP idle responsiveness.
  • Bug Fixes
    • Improved handling of stale OS Bluetooth bonds and pairing cleanup to reduce reconnect thrashing.
  • Documentation
    • Updated Reticulum troubleshooting and multi-platform PIN/passkey guidance (including the ~60s window and “never use 123456”).
  • Tests / Chores
    • Added coverage for pairing timeout, pairing-session behavior, and TCP keepalive scheduling.

rinchen added 2 commits July 20, 2026 13:10
- Add rsReticulum-rnode-tcp-activity-keepalive.patch (Python ACTIVITY_KEEPALIVE
  parity: idle detect() every 3.5s so Wi‑Fi RNodes do not FIN at ~6s).
- Wire apply script into ensure-rsReticulum-patches / clone-ratspeak-stack.
- Track upstream ratspeak/rsReticulum#15 in update.sh RATSPEAK_PATCH_ENTRIES.

Ships the fix in mesh-client builds while the upstream PR may or may not merge.
- Surface Admin Start pairing PIN prominently (large PIN + status) and
  warn that the radio display may stay blank; never use Meshtastic 123456.
- Extend BLE connect grace / connecting hint to 60s to match OS passkey.
- Latch blePairingTimedOut from sidecar logs into Connection + Diagnostics.
- Debounce pairing-transition reconnects (1s → 30s) via rsReticulum overlay.
- Document wrong-PIN / Admin PIN location / empty macOS Bluetooth list.

Reporter used 123456 after Admin Start pairing showed no on-display PIN;
7s hold + real PIN connected. These changes make that path clearer and less
thrashy while the OS passkey dialog is open.
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change adds BLE pairing-timeout tracking and diagnostics, updates pairing UI state and PIN guidance, extends BLE connection polling to roughly 60 seconds, and adds rsReticulum overlays for TCP activity keepalives and pairing-transition retry delays.

Changes

BLE pairing and RNode reliability

Layer / File(s) Summary
Sidecar alert pipeline
src/main/reticulumSidecarIssueTracker.ts, src/renderer/lib/diagnostics/*, src/renderer/components/ReticulumSidecarIssueAlertsBlock.tsx
Tracks blePairingTimedOut events, exposes diagnostic rows, renders issue alerts, and updates related contracts and tests.
Pairing-state UI and refresh timing
src/renderer/components/flasher/*, src/renderer/lib/flasher/*, src/renderer/lib/reticulum/*
Displays pairing-waiting and PIN states, prevents duplicate pairing actions, applies pairing timeouts, and extends BLE refresh timing to 60 seconds.
rsReticulum overlays
reticulum-sidecar/patches/*, scripts/*
Adds TCP activity keepalive and BLE pairing-transition retry overlays, applies them during setup, and tracks them for updates.
Pairing guidance and localization
docs/*, AGENTS.md, src/renderer/locales/*
Documents pairing timeout behavior, PIN presentation, bond recovery, and updated BLE troubleshooting messages across locales.

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

Sequence Diagram(s)

sequenceDiagram
  participant AdminPanel
  participant RNodeFlasherSection
  participant BluetoothConfig
  participant OSBluetooth
  AdminPanel->>RNodeFlasherSection: Start pairing
  RNodeFlasherSection->>BluetoothConfig: Show pairing pending
  RNodeFlasherSection->>OSBluetooth: Start Bluetooth pairing
  OSBluetooth-->>RNodeFlasherSection: Return generated PIN
  RNodeFlasherSection->>BluetoothConfig: Show PIN and clear pending state
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main changes: RNode TCP keepalive and macOS BLE pairing UX improvements.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch runr

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (4)
src/main/reticulumSidecarIssueTracker.ts (2)

196-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Update the retention documentation for BLE latches.

retainInterfaces() now prunes bleBondRemoved and blePairingTimedOut, but the preceding comment only describes TCP/TX issues. Mention the BLE maps so future changes do not accidentally omit them.

🤖 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/main/reticulumSidecarIssueTracker.ts` around lines 196 - 197, Update the
comment immediately preceding the retainInterfaces logic to document that
retainMapKeys also prunes the BLE latch maps bleBondRemoved and
blePairingTimedOut, alongside the existing TCP/TX retention behavior.

21-22: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid super-linear backtracking in the BLE interface regex.

The combination of .*?, (.+?), and the end-of-line alternative can cause excessive backtracking on long or malformed sidecar lines. Parse the known prefix/delimiter deterministically or use a bounded expression.

🤖 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/main/reticulumSidecarIssueTracker.ts` around lines 21 - 22, Update
BLE_RNODE_CONNECT_FAILED_IFACE_RE used for parsing BLE RNode connection failures
to avoid the unbounded lazy wildcards and end-of-line backtracking. Parse the
known prefix and name delimiter deterministically, or bound the captured
interface name so malformed or very long sidecar lines cannot cause super-linear
matching, while preserving extraction of valid interface names.

Source: Linters/SAST tools

src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts (1)

16-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the shared time constant for new durations.

Express the added values with MS_PER_SECOND (for example, 55 * MS_PER_SECOND and 60 * MS_PER_SECOND) instead of inline millisecond literals.

As per coding guidelines, “Use shared validation and time helpers, including clampTcpPort(), MS_PER_SECOND, and src/renderer/lib/timeConstants.ts, rather than inline equivalents.”

🤖 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/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts` around lines 16
- 23, Update the duration values in the reticulum refresh configuration,
including RETICULUM_BLE_CONNECT_GRACE_MS, to derive from the shared
MS_PER_SECOND constant instead of inline millisecond literals. Preserve the
existing duration values and locate the shared constant through the established
timeConstants import.

Source: Coding guidelines

src/renderer/locales/cs/translation.json (1)

1090-1091: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Translate the newly added pairing guidance.

The Czech, German, and Spanish locales now display English text for pairing-critical UI and diagnostics.

  • src/renderer/locales/cs/translation.json#L1090-L1091: translate BLE offline and connecting guidance.
  • src/renderer/locales/cs/translation.json#L1163-L1164: translate pairing-timeout alert text.
  • src/renderer/locales/cs/translation.json#L1517-L1517: translate the runtime timeout message.
  • src/renderer/locales/cs/translation.json#L1683-L1686: translate flasher pairing labels and hint.
  • src/renderer/locales/de/translation.json#L1090-L1091: translate BLE offline and connecting guidance.
  • src/renderer/locales/de/translation.json#L1163-L1164: translate pairing-timeout alert text.
  • src/renderer/locales/de/translation.json#L1517-L1517: translate the runtime timeout message.
  • src/renderer/locales/de/translation.json#L1683-L1686: translate flasher pairing labels and hint.
  • src/renderer/locales/es/translation.json#L1090-L1091: translate BLE offline and connecting guidance.
  • src/renderer/locales/es/translation.json#L1163-L1164: translate pairing-timeout alert text.
  • src/renderer/locales/es/translation.json#L1517-L1517: translate the runtime timeout message.
  • src/renderer/locales/es/translation.json#L1683-L1686: translate flasher pairing labels and hint.
🤖 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/renderer/locales/cs/translation.json` around lines 1090 - 1091, Translate
all newly added pairing-related strings into the appropriate locale languages,
replacing English text while preserving the existing translation keys and JSON
structure: BLE offline/connecting guidance, pairing-timeout alerts, runtime
timeout messages, and flasher pairing labels/hints in
src/renderer/locales/cs/translation.json at lines 1090-1091, 1163-1164, 1517,
and 1683-1686; apply the same updates in
src/renderer/locales/de/translation.json and
src/renderer/locales/es/translation.json at the corresponding ranges.
🤖 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 `@reticulum-sidecar/README.md`:
- Line 33: Update the required manual overlay sequence in the README to include
apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh alongside the
existing overlays, ensuring full-stack manual builds apply the BLE pairing
debounce fix.

In `@scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh`:
- Around line 44-62: Make both overlay scripts fail closed when the patch cannot
be applied: in
scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh lines 44-62
and scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh lines 45-63, use a
failed git apply --check to trigger the pinned-ref fallback, then exit nonzero
if application on that ref fails unless an explicit applied or upstream marker
is verified; preserve successful application and confirmed
already-upstream/incompatible handling.

In `@src/main/reticulumSidecarIssueTracker.test.ts`:
- Line 6: Update the import of parseBlePairingTimedOutIfaceForTests in
reticulumSidecarIssueTracker.test.ts to reference its defining module,
reticulumSidecarIssueTracker.ts, instead of ../shared/reticulum-types; leave
other imports unchanged.

In `@src/renderer/components/flasher/RNodeFlasherSection.tsx`:
- Around line 492-512: Update the pairing flow around onStartPairing and its
component lifecycle to store the pending timer and attempt generation in refs.
Clear the timer and invalidate the generation when Bluetooth is disabled, before
starting a new attempt, and during unmount; ensure timeout, completion, error,
and PIN callbacks only update state for the current attempt. Add a fake-timer
test covering disable, re-enable, and starting pairing again.

In `@src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx`:
- Around line 116-131: Update the BLE pairing-timeout test around
ReticulumSidecarIssueAlertsBlock to capture the rendered container, call
hydrateAxeThemeColors(), run vitest-axe against that container, and assert
toHaveNoViolations() while preserving the existing text assertions.

In `@src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts`:
- Around line 252-256: Update the BLE pairing timeout diagnostic in
ReticulumDiagnosticEngine, including the cause text and runtimeCauseI18n key or
locale entries for blePairingTimedOut, to use neutral wording such as “passkey
exchange timed out” rather than asserting that a passkey was not entered. Keep
the alert contract and interpolation of the node name unchanged.

In `@src/renderer/locales/fr/translation.json`:
- Around line 1090-1091: Translate all newly added BLE pairing guidance into the
appropriate locale-specific user-facing copy, preserving the English source
meaning and existing JSON keys. In src/renderer/locales/fr/translation.json,
src/renderer/locales/id/translation.json,
src/renderer/locales/it/translation.json,
src/renderer/locales/ja/translation.json,
src/renderer/locales/ko/translation.json,
src/renderer/locales/nl/translation.json, and
src/renderer/locales/pl/translation.json, update the BLE hint keys at lines
1090-1091, sidecar keys at lines 1163-1164, the runtime key at line 1517, and
flasher keys at lines 1683-1686; do not leave these strings in English.

In `@src/renderer/locales/it/translation.json`:
- Line 1682: Update the wifiNetmaskPlaceholder translation value to remove the
trailing period, leaving the valid netmask literal 255.255.255.0.

In `@src/renderer/locales/pt-BR/translation.json`:
- Around line 1090-1091: Translate the newly added BLE pairing, timeout,
diagnostic, and flasher strings at all listed sites in
src/renderer/locales/pt-BR/translation.json,
src/renderer/locales/ru/translation.json,
src/renderer/locales/tr/translation.json,
src/renderer/locales/uk/translation.json, and
src/renderer/locales/zh/translation.json, covering ranges 1090-1091, 1163-1164,
1517, and 1683-1686 in each file. Keep the English locale as the source of
truth, preserve the existing translation keys, remove any unused English keys if
applicable, and run the i18n checks.

---

Nitpick comments:
In `@src/main/reticulumSidecarIssueTracker.ts`:
- Around line 196-197: Update the comment immediately preceding the
retainInterfaces logic to document that retainMapKeys also prunes the BLE latch
maps bleBondRemoved and blePairingTimedOut, alongside the existing TCP/TX
retention behavior.
- Around line 21-22: Update BLE_RNODE_CONNECT_FAILED_IFACE_RE used for parsing
BLE RNode connection failures to avoid the unbounded lazy wildcards and
end-of-line backtracking. Parse the known prefix and name delimiter
deterministically, or bound the captured interface name so malformed or very
long sidecar lines cannot cause super-linear matching, while preserving
extraction of valid interface names.

In `@src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts`:
- Around line 16-23: Update the duration values in the reticulum refresh
configuration, including RETICULUM_BLE_CONNECT_GRACE_MS, to derive from the
shared MS_PER_SECOND constant instead of inline millisecond literals. Preserve
the existing duration values and locate the shared constant through the
established timeConstants import.

In `@src/renderer/locales/cs/translation.json`:
- Around line 1090-1091: Translate all newly added pairing-related strings into
the appropriate locale languages, replacing English text while preserving the
existing translation keys and JSON structure: BLE offline/connecting guidance,
pairing-timeout alerts, runtime timeout messages, and flasher pairing
labels/hints in src/renderer/locales/cs/translation.json at lines 1090-1091,
1163-1164, 1517, and 1683-1686; apply the same updates in
src/renderer/locales/de/translation.json and
src/renderer/locales/es/translation.json at the corresponding ranges.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: adf57a95-50b6-4c6c-bb8f-a08a5d628f3d

📥 Commits

Reviewing files that changed from the base of the PR and between 89a9300 and cbabd72.

📒 Files selected for processing (42)
  • AGENTS.md
  • docs/diagnostics.md
  • docs/reticulum-sidecar-ipc.md
  • docs/reticulum.md
  • docs/troubleshooting.md
  • reticulum-sidecar/README.md
  • reticulum-sidecar/patches/README.md
  • reticulum-sidecar/patches/rsReticulum-ble-rnode-pairing-transition-debounce.patch
  • reticulum-sidecar/patches/rsReticulum-rnode-tcp-activity-keepalive.patch
  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh
  • scripts/clone-ratspeak-stack.sh
  • scripts/ensure-rsReticulum-patches.sh
  • scripts/update.sh
  • src/main/reticulumSidecarIssueTracker.test.ts
  • src/main/reticulumSidecarIssueTracker.ts
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.tsx
  • src/renderer/components/ReticulumStackPanel.test.tsx
  • src/renderer/components/flasher/BluetoothConfig.tsx
  • src/renderer/components/flasher/RNodeFlasherSection.tsx
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.test.ts
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts
  • src/renderer/lib/reticulum/useReticulumInterfaceSnapshot.test.ts
  • src/renderer/locales/cs/translation.json
  • src/renderer/locales/de/translation.json
  • src/renderer/locales/en/translation.json
  • src/renderer/locales/es/translation.json
  • src/renderer/locales/fr/translation.json
  • src/renderer/locales/id/translation.json
  • src/renderer/locales/it/translation.json
  • src/renderer/locales/ja/translation.json
  • src/renderer/locales/ko/translation.json
  • src/renderer/locales/nl/translation.json
  • src/renderer/locales/pl/translation.json
  • src/renderer/locales/pt-BR/translation.json
  • src/renderer/locales/ru/translation.json
  • src/renderer/locales/tr/translation.json
  • src/renderer/locales/uk/translation.json
  • src/renderer/locales/zh/translation.json
  • src/shared/reticulum-types.ts

Comment thread reticulum-sidecar/README.md
Comment on lines +44 to +62
if git -C "${RNS_DIR}" apply --check "${PATCH_FILE}" 2>&1 | grep -q 'patch does not apply'; then
echo "ble_rnode pairing-transition debounce overlay not needed (already upstream or incompatible with current rsReticulum HEAD)"
exit 0
fi

echo "ble_rnode pairing-transition debounce patch did not apply on current HEAD; checking out pinned ref ${RS_RETICULUM_REF:0:12}"
current_head="$(git -C "${RNS_DIR}" rev-parse HEAD)"
if [[ "${current_head}" != "${RS_RETICULUM_REF}" ]]; then
git -C "${RNS_DIR}" fetch origin --tags
git -C "${RNS_DIR}" checkout "${RS_RETICULUM_REF}"
fi

if apply_patch 2> /dev/null; then
echo "applied ${PATCH_FILE} on rsReticulum @ ${RS_RETICULUM_REF:0:12}"
exit 0
fi

echo "ble_rnode pairing-transition debounce overlay not needed (already upstream or incompatible with pinned rsReticulum ref)"
exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail when a required overlay cannot be applied.

git apply --check normally emits “patch does not apply” for a conflict, so the early success path makes the pinned-ref fallback unreachable. A failure on the pinned ref also exits successfully, allowing builds to proceed without either reliability fix.

  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh#L44-L62: fall back to the pinned ref on a failed check, and exit nonzero if application still fails unless an explicit applied/upstream marker is verified.
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh#L45-L63: apply the same fail-closed behavior.
📍 Affects 2 files
  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh#L44-L62 (this comment)
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh#L45-L63
🤖 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 `@scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh` around
lines 44 - 62, Make both overlay scripts fail closed when the patch cannot be
applied: in scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh
lines 44-62 and scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh lines
45-63, use a failed git apply --check to trigger the pinned-ref fallback, then
exit nonzero if application on that ref fails unless an explicit applied or
upstream marker is verified; preserve successful application and confirmed
already-upstream/incompatible handling.

import { RETICULUM_INTERFACE_ISSUE_ALERT_STALE_MS } from '../shared/reticulum-types';
import {
parseBleBondRemovedIfaceForTests,
parseBlePairingTimedOutIfaceForTests,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Import the test helper from its defining module.

parseBlePairingTimedOutIfaceForTests is exported by src/main/reticulumSidecarIssueTracker.ts at Lines [319-321], but the changed import targets ../shared/reticulum-types. Importing from the DTO module will fail because the helper is not defined there.

Proposed fix
-import { parseBlePairingTimedOutIfaceForTests } from '../shared/reticulum-types';
+import { parseBlePairingTimedOutIfaceForTests } from './reticulumSidecarIssueTracker';
📝 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
parseBlePairingTimedOutIfaceForTests,
import { parseBlePairingTimedOutIfaceForTests } from './reticulumSidecarIssueTracker';
🤖 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/main/reticulumSidecarIssueTracker.test.ts` at line 6, Update the import
of parseBlePairingTimedOutIfaceForTests in reticulumSidecarIssueTracker.test.ts
to reference its defining module, reticulumSidecarIssueTracker.ts, instead of
../shared/reticulum-types; leave other imports unchanged.

Comment thread src/renderer/components/flasher/RNodeFlasherSection.tsx
Comment thread src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
Comment on lines +252 to +256
id: rfRowId(homeNodeId, `reticulum/ble-pairing-timed-out/${name}`),
nodeId: homeNodeId,
condition: 'reticulum/ble-pairing-timed-out',
cause: `BLE RNode "${name}" pairing timed out (passkey not entered)`,
causeI18n: runtimeCauseI18n('blePairingTimedOut', { name }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use neutral wording for the pairing timeout.

The alert contract records a timeout while waiting for the OS passkey/TX-characteristic/SMP exchange; it does not prove that the user failed to enter a PIN. Change this to wording such as “passkey exchange timed out” and update the corresponding locale strings.

🤖 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/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts` around lines 252 -
256, Update the BLE pairing timeout diagnostic in ReticulumDiagnosticEngine,
including the cause text and runtimeCauseI18n key or locale entries for
blePairingTimedOut, to use neutral wording such as “passkey exchange timed out”
rather than asserting that a passkey was not entered. Keep the alert contract
and interpolation of the node name unchanged.

Comment on lines +1090 to +1091
"offlineHintBle": "Your OS may prompt for a 6-digit Bluetooth PIN (macOS, Windows, or Linux). RNode generates a new code each pairing — never use 123456 (that is Meshtastic’s default, not RNode). The RNode need not appear in System Settings → Bluetooth before mesh-client connects; the OS dialog appears when the stack pairs. Headless radios: connect USB → Reticulum Admin → Bluetooth → Start pairing → enter the PIN shown in the Admin panel (not on the radio display) into the OS dialog. Radios with a display: hold the button ~7 s on Heltec devices (timing varies; ~10 s on many boards enables Wi-Fi AP instead), read the PIN on screen, then enter it in the OS dialog. Clear failed bonds in your OS Bluetooth settings before retrying.",
"connectingHintBle": "BLE RNode links can take up to 60 seconds after the stack starts (OS passkey window). Enter the current RNode PIN if prompted — never 123456. This is normal, not an error. The device may not appear in System Settings until after a successful bond."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Translate the new BLE pairing guidance in every affected locale. The same English-only regression appears in the local-interface hints, sidecar alerts, runtime diagnostics, and flasher strings.

  • src/renderer/locales/fr/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/id/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/it/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/ja/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/ko/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/nl/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].
  • src/renderer/locales/pl/translation.json#L1090-L1091: translate the BLE hints, sidecar keys at Lines [1163-1164], runtime key at Line [1517], and flasher keys at Lines [1683-1686].

As per coding guidelines: English is the source of truth, but locale files should not replace user-facing localized copy with English.

📍 Affects 7 files
  • src/renderer/locales/fr/translation.json#L1090-L1091 (this comment)
  • src/renderer/locales/id/translation.json#L1090-L1091
  • src/renderer/locales/it/translation.json#L1090-L1091
  • src/renderer/locales/ja/translation.json#L1090-L1091
  • src/renderer/locales/ko/translation.json#L1090-L1091
  • src/renderer/locales/nl/translation.json#L1090-L1091
  • src/renderer/locales/pl/translation.json#L1090-L1091
🤖 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/renderer/locales/fr/translation.json` around lines 1090 - 1091, Translate
all newly added BLE pairing guidance into the appropriate locale-specific
user-facing copy, preserving the English source meaning and existing JSON keys.
In src/renderer/locales/fr/translation.json,
src/renderer/locales/id/translation.json,
src/renderer/locales/it/translation.json,
src/renderer/locales/ja/translation.json,
src/renderer/locales/ko/translation.json,
src/renderer/locales/nl/translation.json, and
src/renderer/locales/pl/translation.json, update the BLE hint keys at lines
1090-1091, sidecar keys at lines 1163-1164, the runtime key at line 1517, and
flasher keys at lines 1683-1686; do not leave these strings in English.

Source: Coding guidelines

Comment thread src/renderer/locales/it/translation.json Outdated
Comment on lines +1090 to +1091
"offlineHintBle": "Your OS may prompt for a 6-digit Bluetooth PIN (macOS, Windows, or Linux). RNode generates a new code each pairing — never use 123456 (that is Meshtastic’s default, not RNode). The RNode need not appear in System Settings → Bluetooth before mesh-client connects; the OS dialog appears when the stack pairs. Headless radios: connect USB → Reticulum Admin → Bluetooth → Start pairing → enter the PIN shown in the Admin panel (not on the radio display) into the OS dialog. Radios with a display: hold the button ~7 s on Heltec devices (timing varies; ~10 s on many boards enables Wi-Fi AP instead), read the PIN on screen, then enter it in the OS dialog. Clear failed bonds in your OS Bluetooth settings before retrying.",
"connectingHintBle": "BLE RNode links can take up to 60 seconds after the stack starts (OS passkey window). Enter the current RNode PIN if prompted — never 123456. This is normal, not an error. The device may not appear in System Settings until after a successful bond."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Translate the new pairing strings in every reviewed locale. The same newly added keys are English in five non-English locale files, affecting core pairing and diagnostics flows.

  • src/renderer/locales/pt-BR/translation.json#L1090-L1091: translate BLE connection guidance.
  • src/renderer/locales/pt-BR/translation.json#L1163-L1164: translate timeout alert text and hint.
  • src/renderer/locales/pt-BR/translation.json#L1517-L1517: translate the runtime diagnostic message.
  • src/renderer/locales/pt-BR/translation.json#L1683-L1686: translate flasher pairing labels and instructions.
  • src/renderer/locales/ru/translation.json#L1090-L1091: translate BLE connection guidance.
  • src/renderer/locales/ru/translation.json#L1163-L1164: translate timeout alert text and hint.
  • src/renderer/locales/ru/translation.json#L1517-L1517: translate the runtime diagnostic message.
  • src/renderer/locales/ru/translation.json#L1683-L1686: translate flasher pairing labels and instructions.
  • src/renderer/locales/tr/translation.json#L1090-L1091: translate BLE connection guidance.
  • src/renderer/locales/tr/translation.json#L1163-L1164: translate timeout alert text and hint.
  • src/renderer/locales/tr/translation.json#L1517-L1517: translate the runtime diagnostic message.
  • src/renderer/locales/tr/translation.json#L1683-L1686: translate flasher pairing labels and instructions.
  • src/renderer/locales/uk/translation.json#L1090-L1091: translate BLE connection guidance.
  • src/renderer/locales/uk/translation.json#L1163-L1164: translate timeout alert text and hint.
  • src/renderer/locales/uk/translation.json#L1517-L1517: translate the runtime diagnostic message.
  • src/renderer/locales/uk/translation.json#L1683-L1686: translate flasher pairing labels and instructions.
  • src/renderer/locales/zh/translation.json#L1090-L1091: translate BLE connection guidance.
  • src/renderer/locales/zh/translation.json#L1163-L1164: translate timeout alert text and hint.
  • src/renderer/locales/zh/translation.json#L1517-L1517: translate the runtime diagnostic message.
  • src/renderer/locales/zh/translation.json#L1683-L1686: translate flasher pairing labels and instructions.

As per coding guidelines: English is the source of truth; add strings to English and use t('your.key'); remove unused English keys and run the i18n checks when changing translations.

📍 Affects 5 files
  • src/renderer/locales/pt-BR/translation.json#L1090-L1091 (this comment)
  • src/renderer/locales/pt-BR/translation.json#L1163-L1164
  • src/renderer/locales/pt-BR/translation.json#L1517-L1517
  • src/renderer/locales/pt-BR/translation.json#L1683-L1686
  • src/renderer/locales/ru/translation.json#L1090-L1091
  • src/renderer/locales/ru/translation.json#L1163-L1164
  • src/renderer/locales/ru/translation.json#L1517-L1517
  • src/renderer/locales/ru/translation.json#L1683-L1686
  • src/renderer/locales/tr/translation.json#L1090-L1091
  • src/renderer/locales/tr/translation.json#L1163-L1164
  • src/renderer/locales/tr/translation.json#L1517-L1517
  • src/renderer/locales/tr/translation.json#L1683-L1686
  • src/renderer/locales/uk/translation.json#L1090-L1091
  • src/renderer/locales/uk/translation.json#L1163-L1164
  • src/renderer/locales/uk/translation.json#L1517-L1517
  • src/renderer/locales/uk/translation.json#L1683-L1686
  • src/renderer/locales/zh/translation.json#L1090-L1091
  • src/renderer/locales/zh/translation.json#L1163-L1164
  • src/renderer/locales/zh/translation.json#L1517-L1517
  • src/renderer/locales/zh/translation.json#L1683-L1686
🤖 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/renderer/locales/pt-BR/translation.json` around lines 1090 - 1091,
Translate the newly added BLE pairing, timeout, diagnostic, and flasher strings
at all listed sites in src/renderer/locales/pt-BR/translation.json,
src/renderer/locales/ru/translation.json,
src/renderer/locales/tr/translation.json,
src/renderer/locales/uk/translation.json, and
src/renderer/locales/zh/translation.json, covering ranges 1090-1091, 1163-1164,
1517, and 1683-1686 in each file. Keep the English locale as the source of
truth, preserve the existing translation keys, remove any unused English keys if
applicable, and run the i18n checks.

Source: Coding guidelines

- Fail closed on rsReticulum overlay apply (match packet-tap); document BLE
  debounce overlay in sidecar README.
- Isolate Admin pairing pending timer/generation so disable/re-pair cannot
  clear a newer attempt; cover with fake-timer unit tests.
- Neutralize blePairingTimedOut copy (passkey exchange timed out), parse BLE
  iface names without backtracking regex, use <output> for pairing status,
  derive local-health delays from MS_PER_SECOND, and axe-test the new alert.
- Translate pairing/timeout strings across locales; fix IT wifi netmask typo.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh`:
- Around line 51-54: The existing-overlay guards use substring checks that can
match unrelated text; update both
scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh (lines 51-54)
and scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh (lines 53-55) to
verify the relevant constant declaration and its expected use, so each guard
only exits when the complete semantic marker is present.

In `@src/renderer/components/flasher/RNodeFlasherSection.tsx`:
- Around line 509-526: Keep the RNode session active in the pairing flow around
startBluetoothPairing until the PIN callback delivers a value, the pairing
timeout expires, or an error occurs. Make the callback settle a promise and
await that promise before returning, while preserving attempt cancellation and
cleanup behavior. Add or update tests to verify the PIN response is received
before runWithRNode closes the connection, including timeout and error
settlement paths.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f3d47428-b9c9-4e60-a64e-53929fde38d4

📥 Commits

Reviewing files that changed from the base of the PR and between cbabd72 and d6ac7fa.

📒 Files selected for processing (27)
  • reticulum-sidecar/README.md
  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh
  • src/main/reticulumSidecarIssueTracker.ts
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
  • src/renderer/components/flasher/BluetoothConfig.tsx
  • src/renderer/components/flasher/RNodeFlasherSection.tsx
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.test.ts
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.ts
  • src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts
  • src/renderer/locales/cs/translation.json
  • src/renderer/locales/de/translation.json
  • src/renderer/locales/en/translation.json
  • src/renderer/locales/es/translation.json
  • src/renderer/locales/fr/translation.json
  • src/renderer/locales/id/translation.json
  • src/renderer/locales/it/translation.json
  • src/renderer/locales/ja/translation.json
  • src/renderer/locales/ko/translation.json
  • src/renderer/locales/nl/translation.json
  • src/renderer/locales/pl/translation.json
  • src/renderer/locales/pt-BR/translation.json
  • src/renderer/locales/ru/translation.json
  • src/renderer/locales/tr/translation.json
  • src/renderer/locales/uk/translation.json
  • src/renderer/locales/zh/translation.json
🚧 Files skipped from review as they are similar to previous changes (19)
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
  • src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts
  • reticulum-sidecar/README.md
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/components/flasher/BluetoothConfig.tsx
  • src/renderer/locales/en/translation.json
  • src/renderer/locales/nl/translation.json
  • src/renderer/locales/tr/translation.json
  • src/renderer/locales/ja/translation.json
  • src/renderer/locales/zh/translation.json
  • src/renderer/locales/it/translation.json
  • src/renderer/locales/es/translation.json
  • src/renderer/locales/id/translation.json
  • src/renderer/locales/fr/translation.json
  • src/renderer/locales/de/translation.json
  • src/renderer/locales/ko/translation.json
  • src/renderer/locales/pl/translation.json
  • src/renderer/locales/cs/translation.json
  • src/renderer/locales/uk/translation.json

Comment thread scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh Outdated
Comment thread src/renderer/components/flasher/RNodeFlasherSection.tsx
- startBluetoothPairing now settles on CMD_BT_PIN or timeout (not the KISS
  write), so runWithRNode no longer closes USB before the PIN arrives.
- Cover PIN delivery and timeout with fake-timer SerialPort mocks.
- Strengthen rsReticulum overlay "already present" guards to require const
  declaration + use site; bound BLE iface name parse whitespace for Sonar.
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/main/reticulumSidecarIssueTracker.ts`:
- Around line 31-43: The errorMatch expression in
parseBleRNodeConnectFailedIfaceName permits unbounded whitespace before “error”,
causing excessive backtracking on long non-matching input. Replace it with an
indexOf-based separator or a regex that bounds the preceding whitespace, while
preserving extraction of the name before the error marker.

In `@src/renderer/lib/flasher/rnode.ts`:
- Around line 452-461: Update the RNode.CMD_BT_PIN callback to catch errors
thrown by pinCallback(pin) and reject the pairing promise while ensuring the
flasher session is closed, rather than allowing the exception to escape after
finish(). Add a regression test covering a throwing PIN callback and verify the
promise rejects and cleanup completes.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b38753ce-c984-402f-b0fc-a83ad51789f0

📥 Commits

Reviewing files that changed from the base of the PR and between cbabd72 and b4de6f6.

📒 Files selected for processing (29)
  • reticulum-sidecar/README.md
  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh
  • src/main/reticulumSidecarIssueTracker.ts
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
  • src/renderer/components/flasher/BluetoothConfig.tsx
  • src/renderer/components/flasher/RNodeFlasherSection.tsx
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/lib/flasher/rnode.test.ts
  • src/renderer/lib/flasher/rnode.ts
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.test.ts
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.ts
  • src/renderer/lib/reticulum/reticulumLocalInterfaceRefresh.ts
  • src/renderer/locales/cs/translation.json
  • src/renderer/locales/de/translation.json
  • src/renderer/locales/en/translation.json
  • src/renderer/locales/es/translation.json
  • src/renderer/locales/fr/translation.json
  • src/renderer/locales/id/translation.json
  • src/renderer/locales/it/translation.json
  • src/renderer/locales/ja/translation.json
  • src/renderer/locales/ko/translation.json
  • src/renderer/locales/nl/translation.json
  • src/renderer/locales/pl/translation.json
  • src/renderer/locales/pt-BR/translation.json
  • src/renderer/locales/ru/translation.json
  • src/renderer/locales/tr/translation.json
  • src/renderer/locales/uk/translation.json
  • src/renderer/locales/zh/translation.json
🚧 Files skipped from review as they are similar to previous changes (24)
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.ts
  • reticulum-sidecar/README.md
  • src/renderer/lib/flasher/rnodeBluetoothPairingSession.test.ts
  • scripts/apply-rsReticulum-rnode-tcp-activity-keepalive.sh
  • src/renderer/lib/diagnostics/ReticulumDiagnosticEngine.ts
  • src/renderer/components/ReticulumSidecarIssueAlertsBlock.test.tsx
  • src/renderer/components/flasher/RNodeFlasherSection.tsx
  • scripts/apply-rsReticulum-ble-rnode-pairing-transition-debounce.sh
  • src/renderer/locales/it/translation.json
  • src/renderer/locales/id/translation.json
  • src/renderer/locales/en/translation.json
  • src/renderer/locales/pl/translation.json
  • src/renderer/locales/ko/translation.json
  • src/renderer/locales/pt-BR/translation.json
  • src/renderer/locales/de/translation.json
  • src/renderer/locales/uk/translation.json
  • src/renderer/locales/nl/translation.json
  • src/renderer/locales/ja/translation.json
  • src/renderer/locales/ru/translation.json
  • src/renderer/locales/tr/translation.json
  • src/renderer/locales/cs/translation.json
  • src/renderer/locales/zh/translation.json
  • src/renderer/locales/es/translation.json
  • src/renderer/locales/fr/translation.json

Comment on lines +31 to +43
/** Deterministic parse — avoids super-linear regex backtracking on long sidecar lines. */
function parseBleRNodeConnectFailedIfaceName(plain: string): string | null {
const failedIdx = plain.toLowerCase().indexOf(BLE_RNODE_CONNECT_FAILED_PREFIX.toLowerCase());
if (failedIdx < 0) return null;
const afterFailed = plain.slice(failedIdx + BLE_RNODE_CONNECT_FAILED_PREFIX.length);
const nameKey = /\bname[ \t]{0,16}=[ \t]{0,16}/i.exec(afterFailed);
if (nameKey?.index == null) return null;
const rest = afterFailed.slice(nameKey.index + nameKey[0].length);
const errorMatch = /[ \t]+error[ \t]{0,16}=/i.exec(rest);
const name = (errorMatch?.index != null ? rest.slice(0, errorMatch.index) : rest).trim();
return name.length > 0 ? name : null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,120p' src/main/reticulumSidecarIssueTracker.ts

Repository: Colorado-Mesh/mesh-client

Length of output: 5041


🏁 Script executed:

node - <<'JS'
const re = /[ \t]+error[ \t]{0,16}=/i;

function timeFor(n) {
  const s = ' '.repeat(n) + 'x';
  const t0 = process.hrtime.bigint();
  re.exec(s);
  const t1 = process.hrtime.bigint();
  return Number(t1 - t0) / 1e6;
}

for (const n of [1e3, 2e3, 4e3, 8e3, 16e3, 32e3, 64e3]) {
  console.log(n, timeFor(n).toFixed(3), 'ms');
}
JS

Repository: Colorado-Mesh/mesh-client

Length of output: 275


Bound the whitespace before error (src/main/reticulumSidecarIssueTracker.ts:39)

/[ \t]+error[ \t]{0,16}=/i backtracks badly on long non-matching whitespace runs; use a bounded separator or an indexOf-based split instead.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 39-39: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.

See more on https://sonarcloud.io/project/issues?id=Colorado-Mesh_mesh-client&issues=AZ-BK7LxwjD55e8h9BUX&open=AZ-BK7LxwjD55e8h9BUX&pullRequest=698

🪛 OpenGrep (1.25.0)

[ERROR] 36-36: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)


[ERROR] 39-39: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 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/main/reticulumSidecarIssueTracker.ts` around lines 31 - 43, The
errorMatch expression in parseBleRNodeConnectFailedIfaceName permits unbounded
whitespace before “error”, causing excessive backtracking on long non-matching
input. Replace it with an indexOf-based separator or a regex that bounds the
preceding whitespace, while preserving extraction of the name before the error
marker.

Source: Linters/SAST tools

Comment on lines +452 to 461
this.callbacks.set(RNode.CMD_BT_PIN, (response) => {
const pin =
((response[0] ?? 0) << 24) |
((response[1] ?? 0) << 16) |
((response[2] ?? 0) << 8) |
(response[3] ?? 0);
finish(() => {
pinCallback(pin);
resolve();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate relevant files
fd -a 'rnode.ts' src || true
fd -a '*rnode*test*' test src || true
fd -a '*flasher*test*' test src || true

# Show outlines if available, otherwise fall back to targeted reads
if command -v ast-grep >/dev/null 2>&1; then
  echo '--- AST outline: src/renderer/lib/flasher/rnode.ts ---'
  ast-grep outline src/renderer/lib/flasher/rnode.ts --view expanded || true
fi

echo '--- target source excerpt ---'
nl -ba src/renderer/lib/flasher/rnode.ts | sed -n '380,520p'

echo '--- search for pairing tests ---'
rg -n "startBluetoothPairing|CMD_BT_PIN|pinCallback|Bluetooth Pairing|pairing" src test || true

Repository: Colorado-Mesh/mesh-client

Length of output: 6611


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- rnode.ts around command dispatch ---'
sed -n '180,240p' src/renderer/lib/flasher/rnode.ts

echo '--- rnode.ts around startBluetoothPairing ---'
sed -n '425,470p' src/renderer/lib/flasher/rnode.ts

echo '--- candidate test files ---'
git ls-files | rg '(^|/)(.*rnode.*|.*flasher.*|.*pair.*test.*)\.(test|spec)\.(ts|tsx|js|jsx)$|(^|/)(.*rnode.*|.*flasher.*|.*pair.*)\.(test|spec)\.(ts|tsx|js|jsx)$|(^|/).*__tests__/.*(rnode|flasher|pair).*'

echo '--- pairing-related references ---'
rg -n "startBluetoothPairing|CMD_BT_PIN|pinCallback|Bluetooth Pairing|pairing" src test .

Repository: Colorado-Mesh/mesh-client

Length of output: 50382


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- rnode.test.ts pairing block ---'
sed -n '1,220p' src/renderer/lib/flasher/rnode.test.ts

echo '--- rnodeBluetoothPairingSession.test.ts ---'
sed -n '1,220p' src/renderer/lib/flasher/rnodeBluetoothPairingSession.test.ts

Repository: Colorado-Mesh/mesh-client

Length of output: 6471


Reject when the PIN callback throws. finish() clears the timeout and marks the attempt settled before pinCallback(pin), so a thrown callback escapes onCommandReceived() but never reaches resolve() or reject(). That leaves the pairing promise pending and the flasher session open. Add a regression test for a throwing callback.

🤖 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/renderer/lib/flasher/rnode.ts` around lines 452 - 461, Update the
RNode.CMD_BT_PIN callback to catch errors thrown by pinCallback(pin) and reject
the pairing promise while ensuring the flasher session is closed, rather than
allowing the exception to escape after finish(). Add a regression test covering
a throwing PIN callback and verify the promise rejects and cleanup completes.

@rinchen
rinchen merged commit 7a024cc into main Jul 20, 2026
22 checks passed
@rinchen
rinchen deleted the runr branch July 20, 2026 20:41
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.

1 participant