Skip to content

sourceId not scoped in channel list and related queries — MQTT bridge and multi-source installs see incorrect channels #3712

Description

@Yeraze

Summary

sourceId is not consistently scoped across channel queries, admin routes, and notification helpers. The immediate symptom is the MQTT bridge channel list bug (non-virtual channels appearing for MQTT bridge sources), but the root cause affects at least 10 call sites across channelRoutes.ts, server.ts, and channels.ts.

The correct pattern exists in src/db/repositories/channels.tsgetAllChannels(sourceId) and getChannelById(id, sourceId) both accept an optional sourceId and add AND channels.sourceId = ? to the WHERE clause. The bugs below are call sites that have sourceId available in scope but omit it, or functions that never accepted sourceId at all.


Findings

BUG 1 — PUT /api/channels/:id response fetch (Meshtastic path)

  • File: src/server/routes/channelRoutes.ts line 523
  • chanSourceId is available in scope; the MeshCore branch at line 488 correctly passes it, but the Meshtastic branch does not.
  • Returns the wrong source's channel in the PUT response.
  • Fix: getChannelById(channelId, chanSourceId ?? undefined)

BUG 2 — GET /api/channels/:id/export (potential PSK leak)

  • File: src/server/routes/channelRoutes.ts line 231
  • No sourceId query param is accepted or passed. In a multi-source setup could export the PSK from the wrong source.
  • Fix: Accept ?sourceId= query param and pass it through.

BUG 3 — POST /api/channels/:id/import — upsert + response fetch

  • File: src/server/routes/channelRoutes.ts lines 691 and 713
  • importSourceId is extracted and used to resolve the manager but never passed to upsertChannel or getChannelById. Writes and reads from the wrong source row.
  • Fix: Pass importSourceId to both calls.

BUG 4 — snapshotChannelsBeforeChange() / migrateMessagesIfChannelsMoved()CRITICAL

  • File: src/server/routes/channelRoutes.ts lines 307–328
  • Both helpers call getAllChannels() with no sourceId, fetching from ALL sources. Used before/after PUT, import, and URL-config-import routes. Cross-source false-positive channel moves can trigger migrateMessagesForChannelMoves with incorrect slot pairings, causing message-channel assignment corruption.
  • Fix: Add sourceId?: string parameter and thread it through from all callers.

BUG 5 — POST /nodes/refresh channel count response (cosmetic)

  • File: src/server/server.ts line 3340
  • refreshSourceId available in scope but not passed to getChannelCount(). Count reflects all sources, not the source being refreshed.

BUG 6 — POST /admin/get-channel local node path

  • File: src/server/server.ts line 4977
  • gcSourceId available in scope but not passed to getChannelById. Returns first source's channel regardless of which source the admin is inspecting.

BUG 7 — POST /admin/export-config local node path

  • File: src/server/server.ts line 5277
  • aecSourceId available in scope but not passed to getChannelById. Remote-node path is fine (fetches from device directly); local path reads from wrong source.

BUG 8 — POST /api/channels/refresh count response (cosmetic)

  • File: src/server/routes/channelRoutes.ts line 1144
  • chanRefreshSourceId available but not passed to getChannelCount().

BUG 9 — markChannelMessagesAsRead — no sourceId support anywhere — CRITICAL

  • File: src/server/server.ts line 2559 / src/db/repositories/notifications.ts lines 422–531
  • The function has no sourceId parameter at all. Marks messages read across ALL sources for a given channel slot. If MQTT bridge and radio source both have slot 2, marking one read marks both.
  • Fix: Add sourceId to the function signature and WHERE clause throughout the call chain.

BUG 10 — Sync repository methods have no sourceId support

  • File: src/db/repositories/channels.ts lines 320, 336, 350
  • getChannelByIdSync, getAllChannelsSync, and getChannelCountSync never accept or apply sourceId. Any caller using the sync path gets unscoped results.

Priority Summary

Priority Bug File Lines Impact
Critical 4 channelRoutes.ts 308, 313 Cross-source message corruption via false-positive channel moves
Critical 9 server.ts / notifications.ts 2559 / 422 Mark-read bleeds across all sources for same slot
High 2 channelRoutes.ts 231 PSK export from wrong source
High 3 channelRoutes.ts 691, 713 Import writes to / reads from wrong source row
Medium 1 channelRoutes.ts 523 PUT response shows wrong source channel
Medium 6 server.ts 4977 Admin get-channel returns wrong source
Medium 7 server.ts 5277 Admin export-config reads wrong source
Medium 10 channels.ts 320, 336, 350 Sync path entirely unscoped
Low 5, 8 server.ts, channelRoutes.ts 3340, 1144 Cosmetic: count reflects all sources

Authored by NodeZero 0️⃣

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions