Problem
liteScope has no app-level auth at all — anyone who can reach the dashboard sees decrypted channel message content. Decryption happens once at ingest time (ingestor calls decoder.DecodePacket and writes the plaintext into transmissions.decoded_json), so the server is just serving stored plaintext to whoever asks. This is a problem for hosts who want to share other stats (map, RF, topology) publicly while keeping actual channel chat private.
Message text currently surfaces in: the live Packets feed and its search filter, the packet detail panel, the Channels page, Spotlight/quick-jump search results, and the manual Decoder page. All of it comes from the same decoded_json.text field, over both REST and the WebSocket push stream.
Proposal
Add an optional, per-channel gate on message content specifically — not the rest of the dashboard (node/observer/RF/topology data stays open). Two unlock methods, both configurable, both off by default:
- Mesh challenge: user clicks "Unlock" on a channel, gets a short random code shown in the UI, and is told to send it as a message on that channel from a device that holds the channel's PSK. When the ingestor sees a decrypted message on that channel whose text matches the pending challenge, the requesting session is granted access. This works because producing plaintext that round-trips through the channel's AES key is only possible for someone who actually is in MeshCore phisical observation network lora signal.
- Shared password: admin sets a password globally in config.json; users unlock by entering it once per session.
Without one, the server strips decoded_json.text (and any other plaintext-carrying fields) from API responses and WS events for that channel before they leave the server - this has to be enforced server-side, not just hidden in the UI, since the DB already holds plaintext.
Out of scope for v1
BLE/USB companion pairing as a third unlock method — meaningfully more work (browser-side WebSerial/WebBluetooth, device protocol handling) and not worth blocking this on. Worth revisiting as a follow-up once challenge/password modes are in.
Problem
liteScope has no app-level auth at all — anyone who can reach the dashboard sees decrypted channel message content. Decryption happens once at ingest time (ingestor calls decoder.DecodePacket and writes the plaintext into transmissions.decoded_json), so the server is just serving stored plaintext to whoever asks. This is a problem for hosts who want to share other stats (map, RF, topology) publicly while keeping actual channel chat private.
Message text currently surfaces in: the live Packets feed and its search filter, the packet detail panel, the Channels page, Spotlight/quick-jump search results, and the manual Decoder page. All of it comes from the same decoded_json.text field, over both REST and the WebSocket push stream.
Proposal
Add an optional, per-channel gate on message content specifically — not the rest of the dashboard (node/observer/RF/topology data stays open). Two unlock methods, both configurable, both off by default:
Without one, the server strips decoded_json.text (and any other plaintext-carrying fields) from API responses and WS events for that channel before they leave the server - this has to be enforced server-side, not just hidden in the UI, since the DB already holds plaintext.
Out of scope for v1
BLE/USB companion pairing as a third unlock method — meaningfully more work (browser-side WebSerial/WebBluetooth, device protocol handling) and not worth blocking this on. Worth revisiting as a follow-up once challenge/password modes are in.