fix(mqtt): stamp node.channel on ingest so the map honors VC permissions#3110
Conversation
…erms #3108 routed MQTT message ingest through `channel_database` and stamped `message.channel = CHANNEL_DB_OFFSET + dbId`. The matching change to the node-upsert paths was missed: `NODEINFO_APP` and `POSITION_APP` built `Partial<DbNode>` rows without setting `channel`, so the column stayed NULL. `filterNodesByChannelPermission` in `nodeEnhancer.ts` then evaluated `node.channel ?? 0` for every MQTT-sourced node, falling back to slot 0 and requiring `permissions[channel_0]?.viewOnMap`. But the #3108 UI hides the channel_0..7 toggles for MQTT scopes and directs admins to Virtual Channel Permissions — leaving no way to grant map access. Result: anonymous and non-admin users saw "No nodes visible" on the map for every MQTT source, no matter what they granted. Fix: pass `channel: effectiveChannel` into the upsertNode calls in the NODEINFO_APP and POSITION_APP branches, matching the message-side encoding. Existing rows that already have channel=NULL recover as each node re-broadcasts NODEINFO (typically every few hours under default firmware config); no migration backfill needed for short- term correctness. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job Code Review Complete ✅Reviewing PR #3110: fix(mqtt): stamp node.channel on ingest so the map honors VC permissions Todo List
Code Quality & Best Practices ⭐Excellent implementation! The fix is precise, well-targeted, and maintains consistency with existing patterns:
Bug Analysis 🔍No bugs detected. The implementation is correct:
Performance Considerations 🚀No performance concerns:
Security Review 🔒Security-positive change:
Test Coverage Assessment 🧪Comprehensive and high-quality tests:
Test quality highlights:
Minor Suggestions
Overall AssessmentThis is a high-quality fix that:
Recommendation: Approve and merge 🚢 |
Companion to the node.channel stamping fix in the same PR. With nodes correctly filtered out for users who lack viewOnMap on the channel, two endpoints still leaked enough position data to render lines: 1. GET /api/sources/:id/traceroutes returned every row including the embedded `routePositions` JSON snapshot. The frontend's `useTraceroutePaths` hook prefers that snapshot over the live nodes list, so it drew line segments between coordinates of nodes the user had no permission to see. Apply `maskTraceroutesByChannel` to the response. 2. GET /api/sources/:id/neighbor-info enriched each record with positions pulled from `getNodesByNums` without checking channel access. Build the visible-node set via `filterNodesByChannelPermission` and drop neighbor records whose endpoints aren't in it. User-visible symptom this fixes: anonymous viewers seeing "lines floating in space" on the map for MQTT sources whose nodes had been correctly filtered out of the nodes endpoint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job Code Review Complete ✅Reviewing PR #3110: fix(mqtt): stamp node.channel on ingest so the map honors VC permissions Todo List
Code Quality & Best Practices ⭐Excellent implementation! The fix is precise, well-targeted, and maintains consistency with existing patterns:
Bug Analysis 🔍No bugs detected. The implementation is correct:
Performance Considerations 🚀No performance concerns:
Security Review 🔒Security-positive change:
Test Coverage Assessment 🧪Comprehensive and high-quality tests:
Test quality highlights:
Minor Suggestions
Overall AssessmentThis is a high-quality fix that:
Recommendation: Approve and merge 🚢 |
* chore(release): bump version to 4.6.3 Five user-visible files bumped per the CLAUDE.md version recipe: package.json, package-lock.json (regenerated), helm/meshmonitor/Chart.yaml, desktop/src-tauri/tauri.conf.json, desktop/package.json. CLAUDE.md banner line bumped to match. CHANGELOG entry covers the five PRs since 4.6.2-1: - #3105 unified tapback metadata fix - #3106 docs: drop worktree restriction - #3107 meshcore contact advType persistence - #3108 MQTT channel permissions via channel_database - #3109 hint banner Catppuccin restyle - #3110 node.channel ingest + traceroute/neighbor channel gate Companion blog post (docs/blog/2026-05-20-v4.6.3-permissions.md) walks operators through the new Virtual Channel Permissions flow, the map-visibility behavior change, and the floating-lines fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(release): regenerate desktop/package-lock.json for 4.6.3 The desktop sub-project carries its own lockfile and the bump to 4.6.3 left it pinned to 4.6.1. The Windows Desktop CI job runs `npm install` without `--legacy-peer-deps` and fails on the package.json / package-lock.json version mismatch. Regenerate to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
#3108 routed MQTT message ingest through
channel_databaseand stampedmessage.channel = CHANNEL_DB_OFFSET + dbId. The matching changes on the node and neighbor-info / traceroute endpoints were missed, so non-admin / anonymous viewers either saw nothing on the map or — worse — saw line segments rendered between coordinates of nodes they had no permission to see ("floating lines").What this PR fixes
node.channel.mqttIngestion.tsleft the column NULL, so the map node filter fell back topermissions[channel_0]— a slot grant the feat(mqtt): route MQTT channel permissions through channel_database #3108 UI hides for MQTT scopes. Result: anonymous and non-admin viewers couldn't see any MQTT nodes regardless of what they granted./api/sources/:id/traceroutesreturned rows unfiltered. Each row carries aroutePositionsJSON snapshot of hop coordinates. The frontend'suseTraceroutePathshook prefers that snapshot over the live nodes list, so it drew lines for traceroutes the user had no channel access to — coordinates leaked, lines floated./api/sources/:id/neighbor-infoenriched records with positions fromgetNodesByNumswith no channel check. Same leak shape: lines drawn between coordinates of nodes the user shouldn't see.Fix
mqttIngestion.ts: passchannel: effectiveChannelinto the NODEINFO_APP and POSITION_APPupsertNodecalls. Existing rows withchannel=NULLrecover as each node re-broadcasts NODEINFO.sourceRoutes.ts /traceroutes: applymaskTraceroutesByChannel(already existed innodeEnhancer.ts) to the response.sourceRoutes.ts /neighbor-info: build a visible-node set viafilterNodesByChannelPermissionand drop neighbor records whose endpoints aren't in it.Tests
mqttIngestion.test.tspinning the node.channel stamping (NODEINFO, POSITION, raw-slot fallback).sourceRoutes.neighbor-info.test.tsfor the channel-gate.sourceRoutes.traceroutes.test.tscovering admin-pass, no-grant-drop, and partial-grant scenarios.Test plan
nodes.channel = CHANNEL_DB_OFFSET + dbId(not NULL or 0).viewOnMapon the corresponding Virtual Channel Permissions entry.🤖 Generated with Claude Code