feat(meshcore): channel create/edit/delete UI + source-type-aware routes (phase 3/3)#3039
Conversation
…tes (phase 3/3) Closes the MeshCore channels feature with a per-source Configuration UI and source-type-aware backend routes. Backend - PUT /api/channels/:id is now source-type-aware. For MeshCore sources the channelId is no longer capped at 0-7 (MeshCore allows arbitrary device-dependent indices), the name length cap is widened to 31 bytes, and the write path goes through `meshcoreManager.setChannel(idx, name, secretHex)` after decoding the base64 PSK to its 16-byte secret. A non-16-byte secret is rejected with 400; a device-side failure returns 502. - DELETE /api/channels/:id similarly drops the 0-7 cap for MeshCore, removes the "cannot delete primary channel" gate (MeshCore has no primary), and routes the delete through `meshcoreManager.deleteChannel(idx)`. - Source type is resolved via `databaseService.sources.getSource()` with a Meshtastic-default fallback for the legacy NULL sourceId case. Frontend - New `MeshCoreChannelsConfigSection.tsx` (not a unification of the Meshtastic ChannelsConfigSection — that component is 900+ LOC of drag-reorder + role/uplink/downlink semantics that don't apply here). Provides add / edit / regenerate-secret / delete, hex secret display with show/copy toggle, and a "+ Add channel" that auto-assigns the lowest free idx and seeds a `crypto.getRandomValues` 16-byte secret. - Mounted inside `MeshCoreConfigurationView`, which now receives `baseUrl` and `sourceId` from `MeshCorePage` for the API surface. Tests (+7 frontend) - MeshCoreChannelsConfigSection.test.tsx: list rendering, empty state, permission gating, "Add channel" idx auto-assignment + secret generation, Save sends correct PUT body (base64 PSK + sourceId), Delete sends correct DELETE URL, secret-visibility toggle. Server-route integration tests are intentionally skipped: server.ts handlers aren't factored into a mountable router for supertest, and phase 1's manager-level tests already cover the MeshCore write/delete paths the route delegates to. Closes the 3-phase MeshCore channels feature (docs/meshcore-channels-plan.md). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job PR Review Complete ✅This is a well-implemented completion of the MeshCore channel configuration feature. The code follows project conventions and demonstrates good security practices. Here's my detailed analysis: ✅ Code Quality & Best PracticesBackend Route Changes (
Frontend Components
✅ Security AnalysisPSK/Secret Handling
Authentication & Authorization
✅ Architecture ComplianceMulti-source Architecture
Database Layer
✅ Performance ConsiderationsFrontend Optimizations
Backend Efficiency
✅ Test CoverageNew Tests (+7 frontend tests in
Test Quality
🔍 Minor ObservationsValidation Consistency (
Error Recovery (
UI/UX (
📝 Recommendations
🎯 SummaryThis PR successfully completes the 3-phase MeshCore channels implementation with:
The implementation demonstrates thorough understanding of the codebase patterns and security requirements. The decision to fork the UI rather than extend the existing Meshtastic component was wise given the fundamental differences in channel semantics. Ready for merge ✅ Job run | Branch: feat/meshcore-channels-phase-3 |
System Test ResultsMeshMonitor System Test ResultsTest Run: 2026-05-15 20:43:30 EDT Test Summary
✅ Overall Result: PASSEDAll deployment configurations are working correctly! Test DetailsConfiguration Import:
Quick Start Test:
Security Test:
V1 API Test:
Reverse Proxy Test:
Reverse Proxy + OIDC Test:
Virtual Node CLI Test:
Backup & Restore Test:
Database Migration Test:
DB Backing Consistency Test:
|
Phase 3 of 3 for MeshCore channels support — closes the feature. See
docs/meshcore-channels-plan.md.Summary
Adds a per-source Configuration UI for creating, editing, regenerating-secret, and deleting channels on a MeshCore device, plus source-type-aware backend routes that route writes through
meshcoreManager.setChannel/deleteChannelfor MeshCore sources.What changed
Backend
PUT /api/channels/:idis now source-type-aware:meshcoreManager.setChannel(idx, name, secretHex). Rejects non-16-byte secrets with 400; surfaces device-side failures as 502.setChannelConfigadmin-message path).DELETE /api/channels/:idsimilarly drops the 0..7 cap and the "cannot delete primary" gate for MeshCore (it has no primary concept), routing throughmeshcoreManager.deleteChannel(idx).databaseService.sources.getSource(); legacy NULLsourceIdis treated as Meshtastic.Frontend
MeshCoreChannelsConfigSection.tsxmounted insideMeshCoreConfigurationView. Provides:crypto.getRandomValues16-byte secret).MeshCoreConfigurationViewnow acceptsbaseUrl+sourceIdso the channels sub-section can hit the API.Why a separate config component, not a unified one
The Meshtastic
ChannelsConfigSectionis 937 LOC built around drag-reorder of a fixed 8-slot grid plus role/uplink/downlink/positionPrecision — none of which apply to MeshCore. Forking keeps both readable. The shared backend layer (channels repository, write/delete routes) is already source-type-aware.Test plan
npx vitest run— 4950 PASS / 0 FAIL (+7 over main)npm run build— cleantsc --noEmit— cleanNew tests (+7 frontend)
MeshCoreChannelsConfigSection.test.tsx:/api/channels/all?sourceId=...canWrite=falsePUT /api/channels/<idx>with base64 PSK + sourceId, then re-fetchesDELETE /api/channels/<idx>?sourceId=<src>with confirm + re-fetchtype=passwordby default, toggles totexton ShowWhy no server-route integration tests
server.tsroute handlers aren't factored into a mountable router that supertest can wrap. Phase 1's manager-level tests (mockingnativeBackend.sendCommand) already exercise the MeshCore write/delete paths the route delegates to; the route layer is a thin source-type discriminator + base64↔hex conversion.Plan completion
This PR closes the three-phase MeshCore channels feature:
MeshCoreChannelsView.🤖 Generated with Claude Code