Skip to content

feat: use human readable ws device names all places#2013

Open
KEGustafsson wants to merge 4 commits into
SignalK:masterfrom
KEGustafsson:wsDevicesWithNames
Open

feat: use human readable ws device names all places#2013
KEGustafsson wants to merge 4 commits into
SignalK:masterfrom
KEGustafsson:wsDevicesWithNames

Conversation

@KEGustafsson

@KEGustafsson KEGustafsson commented Jun 11, 2025

Copy link
Copy Markdown
Collaborator

New implementation to add authenticated WS devices description as a name to Dashboard.
This fixes issues that #1705 had related for non-admin use cases.

316239363-8801b7d2-3fb5-4aee-bfa6-cf21017d9f08

Question for fine tuning of this PR is, should ws devices data be part of SERVERSTATISTICS or PROVIDERSTATUS feed?
Current implementation is adding it to SERVERSTATISTICS in deltastats.ts. It could be changed to index.ts and part of PROVIDERSTATUS.

This PR adds server-supplied human-readable source names for authenticated WebSocket devices and wires them through the admin UI.

  • Server:

    • Adds src/sourceNames.ts to build a Record<sourceRef, name> from authenticated WebSocket device description values (ws.<clientId>, with . normalized to _) merged with administrator sourceAliases (manual aliases take precedence).
    • Adds a cached GET /sourceNames endpoint in src/serverroutes.ts that returns 403 when security is enabled and the requester is neither authenticated nor allowed read-only.
    • Recomputes the cache via refreshSourceNames() and broadcasts live updates with a serverevent of type SOURCENAMES whenever security configuration/alias-related data changes (including security config saves and sourceAliases persistence).
  • Client (server-admin-ui):

    • Fetches /sourceNames during initial data loading in dataFetching.ts and stores it in Zustand (appSlice.sourceNames), exposed via a useSourceNames() selector.
    • Updates the store when WebSocket SOURCENAMES events arrive in WebSocketService.
    • Uses sourceNames when building display labels in useSourceAliases and buildSourceLabel/buildSourceLabelParts, preferring sourceNames[sourceRef] for WS refs when present (falling back to the raw sourceRef otherwise, while also overriding other derived labels such as N2K manufacturer/model).
    • Updates UI rendering to use the human-readable names:
      • Dashboard uses sourceNames when rendering connection/provider links.
      • Data Browser passes sourceNames into buildSourceLabel for source labels.
      • SourceLabel keeps alias editing read-only for non-admin users (admins keep the existing editing UI).
    • Extends sourceLabels.test.ts coverage for WS label formatting, precedence, and fallback behavior.

@KEGustafsson KEGustafsson changed the title feat: ws devices use description as a name instead of id feat: ws devices use description as a name instead of id on Dashboard Jun 12, 2025
@tkurki tkurki added the feature label Jun 21, 2025

@tkurki tkurki left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This PR works for authenticated devices, right? So reflect that in the title and description.

Like for non-authenticated server you can send data to the server with echo '{"updates":[{"values":[{"path":"navigation.speedOverGround","value":3.15}]}]}' | wscat 'ws://localhost:3000/signalk/v1/stream?subscribe=none'but all you'll see on the list is ws.

@KEGustafsson

KEGustafsson commented Jun 21, 2025

Copy link
Copy Markdown
Collaborator Author

Websocket devices, which are listed in Security/Devices/Devices list are the ones that are impacted. If device has description then that is used, fallback id.
If non-authenticated serves does not populated this list, then there is no change to current situation.

I haven't checked how things look with non-authenticated server, but need to check that too.

Use case is mainly SensESP and similar sensor devices, which are listed there and produce data to server.

I'll update title and description to address this feature in more precisely.

@KEGustafsson KEGustafsson changed the title feat: ws devices use description as a name instead of id on Dashboard feat: use device description as name on Dashboard for authenticated WS devices, if available Jun 23, 2025
@KEGustafsson

Copy link
Copy Markdown
Collaborator Author

Title and description updated to highlight that PR target is to show authenticated WS devices from Security / Devices list.

@tedenda

tedenda commented Jul 26, 2025

Copy link
Copy Markdown

This work may close #1146

@KEGustafsson KEGustafsson changed the title feat: use device description as name on Dashboard for authenticated WS devices, if available feat: use human readable ws device names all places Dec 11, 2025
@KEGustafsson

KEGustafsson commented Dec 11, 2025

Copy link
Copy Markdown
Collaborator Author

Latest commit extend usage to Dashboard, Data Browser and Source Priority views, where ws devices with id is shown now with user readable names.

Working without logging, non-admin user and admin user.

@KEGustafsson

Copy link
Copy Markdown
Collaborator Author

New Implementation Approach

Display togglable, human-readable or id, for WebSocket sources in the admin UI, Data Browser and Source Priorities

Changes

Server-side

  • src/security.ts - Added showDeviceLabelNames to SecurityConfig
  • src/deltastats.ts - Include devices array in SERVERSTATISTICS; strip descriptions when toggle OFF

UI Components

  • Settings.js - Toggle "Show Device Names in UI" (default: ON)
  • Dashboard.js - Show device descriptions
  • DataBrowser.js - Resolve WS source IDs to names
  • SourcePriorities.js - Show device names in dropdown

Behavior

Toggle Dashboard Data Browser Source Priorities
ON Device name Device name Device name
OFF Device ID Device ID Device ID

Not included (future work)

  • labelName in deltas source objects
  • labelName in /signalk/v1/api/sources/ REST API

Backwards compatibility

  • Deltas and REST API compatibility need to be maintained
  • Q: How to add alternative source name to deltas and REST API?

Comment thread src/deltastats.ts Outdated
Comment thread packages/server-admin-ui/src/views/ServerConfig/SourcePriorities.js Outdated
@tkurki

tkurki commented Dec 15, 2025

Copy link
Copy Markdown
Member

I want to move towards having just sourceRef in deltas and any additional metadata should be separately retrievable from /sources. Otherwise where do we draw the line what to include in deltas and what not. source object in delta seemed like to a good idea at the time, but I no longer think so.

@KEGustafsson

Copy link
Copy Markdown
Collaborator Author

I want to move towards having just sourceRef in deltas and any additional metadata should be separately retrievable from /sources. Otherwise where do we draw the line what to include in deltas and what not. source object in delta seemed like to a good idea at the time, but I no longer think so.

Should this PR be just viewing/toggling of ws.* between id or description? Or should there be included meta also?
More I played with different option, more puzzled I am with how to share the alternative name.
Viewing part is quite ok as it is now?

@KEGustafsson KEGustafsson force-pushed the wsDevicesWithNames branch 2 times, most recently from 393b0e3 to 38f52c9 Compare January 11, 2026 20:32
@KEGustafsson KEGustafsson reopened this Jan 11, 2026
@KEGustafsson KEGustafsson marked this pull request as draft February 21, 2026 15:37
@KEGustafsson KEGustafsson reopened this Feb 21, 2026
@KEGustafsson KEGustafsson marked this pull request as ready for review February 21, 2026 15:46
* feat(sources): show human-readable names for WebSocket devices

WebSocket device sources appear as cryptic refs like
"ws.3d3e48a1-1185-2fe3-c494-1c1a9ee6f41f" across the Dashboard, Data
Browser and Source Priorities. The device's registration description is already 
in the security config, just never surfaced.

Expose a read-only GET /sourceNames map (ws device descriptions merged
with manual aliases) that every authenticated client can read, so
non-admin users see the names too. The map is cached server-side and
rebuilt only when devices or aliases change, never on the per-delta
path. Source-name editing stays admin-only.

* fix(sources): guard /sourceNames and keep map fresh

Address review feedback on the WebSocket device-names change:

- Require read access for GET /sourceNames (authenticated, anonymous
  read-only enabled, or security disabled) so device descriptions are
  not exposed to anonymous clients.
- Broadcast SOURCENAMES on the general serverevent channel instead of
  serverAdminEvent so non-admin clients receive live updates, not just
  the initial fetch.
- Refresh the cached map when /removeSource deletes a source alias.
- Default the /sourceNames fetch response to an empty object so a
  null/empty body cannot break source-label rendering.
@KEGustafsson KEGustafsson reopened this Jun 27, 2026
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 12368786-bd49-449d-acc9-9af8a91fc6ae

📥 Commits

Reviewing files that changed from the base of the PR and between a3a1f3a and 6da2b1e.

📒 Files selected for processing (5)
  • packages/server-admin-ui/src/services/WebSocketService.ts
  • packages/server-admin-ui/src/store/slices/appSlice.ts
  • packages/server-admin-ui/src/utils/sourceLabels.ts
  • packages/server-admin-ui/src/views/DataBrowser/DataBrowser.tsx
  • src/serverroutes.ts

📝 Walkthrough

Walkthrough

The PR adds server-generated source-name maps, exposes them over HTTP and websocket updates, stores them in the admin UI, and uses them in label rendering. Alias editing is restricted for non-admin users.

Changes

Source name propagation

Layer / File(s) Summary
Source-name map builder
src/sourceNames.ts, test/sourceNames.ts, src/serverroutes.ts
wsSourceRef normalizes WebSocket client IDs, buildSourceNames merges device descriptions with aliases, and serverroutes.ts caches, refreshes, and serves the computed map through GET /sourceNames plus SOURCENAMES events.
Store state and selector
packages/server-admin-ui/src/store/slices/appSlice.ts, packages/server-admin-ui/src/store/index.ts, packages/server-admin-ui/src/dataFetching.ts, packages/server-admin-ui/src/services/WebSocketService.ts
The admin UI store adds sourceNames, setSourceNames, and useSourceNames(), then loads and updates that state from the /sourceNames fetch and SOURCENAMES websocket events.
Label helpers and browser labels
packages/server-admin-ui/src/utils/sourceLabels.ts, packages/server-admin-ui/src/utils/sourceLabels.test.ts, packages/server-admin-ui/src/hooks/useSourceAliases.ts, packages/server-admin-ui/src/views/DataBrowser/DataBrowser.tsx
sourceNames flows through the source-label helpers, the alias hook, and DataBrowser label computation.
Dashboard links and alias editing gate
packages/server-admin-ui/src/views/Dashboard/Dashboard.tsx, packages/server-admin-ui/src/views/DataBrowser/SourceLabel.tsx
Dashboard provider links can show mapped names for ws.* IDs, and SourceLabel renders read-only output for non-admin users.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • SignalK/signalk-server#2558: Both PRs update fetchAllData() and related admin UI event handling to bring new server-provided data into the client.

Poem

A rabbit found a name-map bright,
and hopped through labels late at night.
ws. refs gained a clearer glow,
while aliases and role gates now know.
My whiskers twitch—what a tidy sight! 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning It describes the feature, but it does not follow the template: both required section headings and a testing summary are missing. Add the required 'What problem does this solve?' and 'How was this tested?' sections, and summarize the user-facing issue and verification steps.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the feature: using human-readable WebSocket device names throughout the UI.
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 unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/serverroutes.ts`:
- Around line 582-614: The cached source-name map is not being refreshed on the
full security-config save path, so updates made through the PUT security/config
route can leave GET /sourceNames and SOURCENAMES subscribers stale. Update the
security config save flow to invoke refreshSourceNames after saveSecurityConfig
succeeds, using the existing refreshSourceNames and computeSourceNames helpers,
and keep the current invalidation behavior in getConfigSavingCallback and the
sourceAliases handler consistent with this route.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87c1ddd8-e8b7-4fe1-ba15-408101af1c78

📥 Commits

Reviewing files that changed from the base of the PR and between 74beff5 and 11edce6.

📒 Files selected for processing (13)
  • packages/server-admin-ui/src/dataFetching.ts
  • packages/server-admin-ui/src/hooks/useSourceAliases.ts
  • packages/server-admin-ui/src/services/WebSocketService.ts
  • packages/server-admin-ui/src/store/index.ts
  • packages/server-admin-ui/src/store/slices/appSlice.ts
  • packages/server-admin-ui/src/utils/sourceLabels.test.ts
  • packages/server-admin-ui/src/utils/sourceLabels.ts
  • packages/server-admin-ui/src/views/Dashboard/Dashboard.tsx
  • packages/server-admin-ui/src/views/DataBrowser/DataBrowser.tsx
  • packages/server-admin-ui/src/views/DataBrowser/SourceLabel.tsx
  • src/serverroutes.ts
  • src/sourceNames.ts
  • test/sourceNames.ts

Comment thread src/serverroutes.ts
…89)

The PUT security/config route saves the complete security config,
which can change device descriptions, but did not refresh the cached
source-name map. This left GET /sourceNames and SOURCENAMES subscribers
stale until another device or alias change occurred. Invoke
refreshSourceNames after a successful save, matching the device routes
and the sourceAliases handler.


Claude-Session: https://claude.ai/code/session_018SBdX6xr1Hxn8Dam7N4AKu

Co-authored-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/serverroutes.ts (1)

608-615: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Refresh source names when priority reset clears aliases.

buildSourceNames() includes sourceAliases, and DELETE /priorities emits SOURCEALIASES as {} after reset, but this cache is not refreshed there. Clients can keep stale alias-derived names until another alias/device change occurs.

Suggested fix
         app.emit('serverAdminEvent', {
           type: 'SOURCEALIASES',
           data: {}
         })
+        refreshSourceNames()
         app.emit('serverAdminEvent', {
           type: 'PRIORITYGROUPS',
           data: []
🤖 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/serverroutes.ts` around lines 608 - 615, The source-name cache in
refreshSourceNames() is not updated when DELETE /priorities clears aliases, so
clients can keep stale alias-derived names. Update the priorities reset flow in
the DELETE /priorities handler to call refreshSourceNames() after emitting
SOURCEALIASES, ensuring cachedSourceNames is rebuilt from buildSourceNames() and
the serverevent S0URCENAMES update is sent immediately.
🤖 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.

Outside diff comments:
In `@src/serverroutes.ts`:
- Around line 608-615: The source-name cache in refreshSourceNames() is not
updated when DELETE /priorities clears aliases, so clients can keep stale
alias-derived names. Update the priorities reset flow in the DELETE /priorities
handler to call refreshSourceNames() after emitting SOURCEALIASES, ensuring
cachedSourceNames is rebuilt from buildSourceNames() and the serverevent
S0URCENAMES update is sent immediately.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ef4bf8f0-ec36-4cc5-9322-566a031d1b7d

📥 Commits

Reviewing files that changed from the base of the PR and between 11edce6 and c29eb09.

📒 Files selected for processing (1)
  • src/serverroutes.ts

DELETE /priorities clears sourceAliases but the cached source-name
map was not rebuilt, so clients kept stale alias-derived names.
Call refreshSourceNames() after emitting the empty SOURCEALIASES,
matching the other alias-mutating handlers.


Claude-Session: https://claude.ai/code/session_015idCKNy7E5qHFVYu5DzLXE

Co-authored-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/serverroutes.ts (1)

592-598: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Honor showDeviceLabelNames when building read-only names.

computeSourceNames() always passes security devices to buildSourceNames, so device descriptions can still appear in /sourceNames and SOURCENAMES even when the label-name toggle is off. Strip/omit device descriptions before building this read-only map; keep manual aliases if those should remain explicit.

Suggested fix
   const computeSourceNames = (): Record<string, string> => {
     const config = getSecurityConfig(app)
+    const includeDeviceLabelNames = config.showDeviceLabelNames !== false
     const devices =
-      typeof app.securityStrategy.getDevices === 'function'
+      includeDeviceLabelNames &&
+      typeof app.securityStrategy.getDevices === 'function'
         ? app.securityStrategy.getDevices(config)
         : []
     return buildSourceNames(devices, app.config.settings.sourceAliases || {})
   }
🤖 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/serverroutes.ts` around lines 592 - 598, `computeSourceNames()` is always
forwarding security devices into `buildSourceNames`, so device descriptions can
leak into the read-only source-name output even when `showDeviceLabelNames` is
disabled. Update `computeSourceNames()` in `serverroutes.ts` to respect the
toggle by stripping or omitting device descriptions before calling
`buildSourceNames`, while still preserving any explicit manual aliases from
`app.config.settings.sourceAliases`.
🤖 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.

Outside diff comments:
In `@src/serverroutes.ts`:
- Around line 592-598: `computeSourceNames()` is always forwarding security
devices into `buildSourceNames`, so device descriptions can leak into the
read-only source-name output even when `showDeviceLabelNames` is disabled.
Update `computeSourceNames()` in `serverroutes.ts` to respect the toggle by
stripping or omitting device descriptions before calling `buildSourceNames`,
while still preserving any explicit manual aliases from
`app.config.settings.sourceAliases`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0a3fc4fc-7ec4-4a29-a9f1-e572225f9975

📥 Commits

Reviewing files that changed from the base of the PR and between c29eb09 and a3a1f3a.

📒 Files selected for processing (1)
  • src/serverroutes.ts

@KEGustafsson

Copy link
Copy Markdown
Collaborator Author

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)

🤖 Prompt for all review comments with AI agents

ℹ️ Review info

@coderabbitai
This finding isn't actionable — the showDeviceLabelNames toggle it references doesn't exist anywhere in the codebase (no settings key, no schema, no UI). With no toggle, there's nothing to gate against.
The exposure is also intended behavior from #88, not a leak: /sourceNames (serverroutes.ts:1770-1791) is only served when security is off, the request is authenticated, or anonymous read-only access is enabled — otherwise 403. Descriptions are never exposed to anonymous clients.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@KEGustafsson: The PR description image shows a small UI panel titled “Connections activity” with three connection rows separated by thin horizontal dividers. Each row has small connection/document-style icons and blue link text. The visible entries are “defaults”, “udp7000”, and “SensoSP device: sensesp-engines-test”. The key visual change is that the third entry is displayed with a human-readable device description instead of only a raw id.

The Comment image shows the same style of “Connections activity” list, again with defaults, udp7000, and SensoSP device: sensesp-engines-test rendered as clickable blue labels, reinforcing the intended UX of showing readable source/device names in the UI.

You’re right — thanks for the clarification. That finding was based on an incorrect assumption about a showDeviceLabelNames toggle that does not exist in this PR/codebase, so it isn’t actionable. And given the /sourceNames access checks you outlined in src/serverroutes.ts, this is intended behavior rather than an unintended disclosure.

I’m withdrawing that comment.


✏️ Learnings added
Learnt from: KEGustafsson
URL: https://github.com/SignalK/signalk-server/pull/2013

Timestamp: 2026-06-27T14:59:03.575Z
Learning: In the SignalK signalk-server codebase, the `/sourceNames` route in `src/serverroutes.ts` is intentionally gated: it is served only when security is off, the request is authenticated, or anonymous read-only access is allowed; otherwise it returns `403`. Review feedback should not treat human-readable device descriptions from `/sourceNames` as an anonymous data leak.

Learnt from: KEGustafsson
URL: https://github.com/SignalK/signalk-server/pull/2013

Timestamp: 2026-06-27T14:59:03.575Z
Learning: In SignalK signalk-server PR `#2013`, review comments should not reference a `showDeviceLabelNames` toggle unless it is actually present in the code, schema, or UI; KEGustafsson clarified that no such toggle exists in the current implementation under review.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants