Skip to content

refactor: consolidate device and client servers onto single port#8

Merged
nedpals merged 4 commits into
masterfrom
claude/deviceserver-clientserver-merge-u2sjof
Jul 5, 2026
Merged

refactor: consolidate device and client servers onto single port#8
nedpals merged 4 commits into
masterfrom
claude/deviceserver-clientserver-merge-u2sjof

Conversation

@nedpals

@nedpals nedpals commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Refactors the agent's two-server architecture (device on port 9470, client on port 9471) into a single unified server on one port. Both device and client WebSocket connections are now served from the same listener and routed based on connection type (?mode=device query parameter or X-Device-Mode header for devices; plain /ws for clients).

Key Changes

  • New server/unifiedserver package: Fronts both device and client servers with a single HTTP listener, mDNS advertisement, and shared CORS/health handling. Routes incoming /ws connections to the appropriate handler based on deviceserver.IsDeviceConnection().

  • Refactored deviceserver.Server and clientserver.Server:

    • Removed HTTP listener, mDNS, and TLS management (now owned by unified server)
    • Renamed Start()StartBackground(ctx) to clarify they no longer bind listeners
    • Added ServeWS(w, r) public method for unified server to route connections
    • Removed enableCORS() and startMDNS() methods (moved to unified server)
    • Simplified Config structs to remove Port, CertFile, KeyFile fields
  • Updated Agent:

    • Removed ClientPort field; single DevicePort now serves both roles
    • Added UnifiedServer field to manage the single listener
    • Updated startServers() to instantiate unified server and call StartBackground() on device/client servers
  • Health endpoints: Both /health and /api/v1/health now served on the single port, reporting "type":"agent" instead of separate device/client types.

  • Documentation and CLI:

    • Removed -client-port flag
    • Updated API docs, README, and CHANGELOG to reflect single-port architecture
    • Updated JavaScript client examples to use port 9470 for both devices and clients
  • Tests: Added server/unifiedserver/server_test.go with routing verification and health endpoint tests.

Implementation Details

  • The unified server uses the existing deviceserver.IsDeviceConnection() discriminator to route connections, maintaining backward compatibility with device clients using ?mode=device or the X-Device-Mode header.
  • Device and client servers derive their context from the unified server's parent context, allowing coordinated shutdown.
  • The in-process ServerBridge between device and client handlers remains unchanged.
  • mDNS continues to advertise the device service type on the single port for auto-discovery.

https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK

claude added 4 commits July 5, 2026 03:03
Previously the agent ran two HTTP/WebSocket listeners: a device server on
port 9470 (NFC readers/phones) and a client server on port 9471 (web
clients). They already shared the same /ws path, auth, origin, and CORS
handling and communicated in-process via server.ServerBridge, so the two
ports were a conceptual boundary rather than a technical requirement.

Collapse them onto one listener (default port 9470). A new
server/unifiedserver package fronts the existing device/client handlers
and routes each /ws connection by deviceserver.IsDeviceConnection: device
connections (?mode=device or X-Device-Mode: true) go to the device
handler, everything else to the client handler. Existing clients keep
working unchanged apart from the port.

- deviceserver/clientserver: split the standalone HTTP-listener Start()
  into StartBackground(ctx) for goroutines plus an exported ServeWS; the
  unified server owns the single listener, TLS, mDNS, and CORS. Trim
  Port/CertFile/KeyFile from their Configs (now unused).
- agent.go/main.go: always start the unified server; remove the
  -client-port flag and Agent.ClientPort. The single port is set via
  -device-port (default 9470).
- Both /health and /api/v1/health are served on the one port and report
  "type":"agent".
- Add unifiedserver dispatch + health tests; update docs and test client.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK
golangci-lint's errcheck flagged unchecked error returns in the new
single-port code. Explicitly ignore the writes that cannot meaningfully
fail mid-handler (json.Encode, w.Write, httpServer.Shutdown, the test's
SetReadDeadline) and log the unified server's Start error from its
goroutine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK
govulncheck (the PR's vuln job) flagged GO-2026-5026 in
golang.org/x/net@v0.47.0, reached via the mkcert truststore library's
idna.ToASCII call in tls/manager.go. Bump x/net to v0.55.0 (the fixed
version); go mod tidy pulls the compatible x/crypto/x/sys/x/text updates
and corrects go-qrcode to a direct dependency. govulncheck now reports no
vulnerabilities. Pre-existing issue, unrelated to the server merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK
@nedpals nedpals changed the title Consolidate device and client servers onto single port refactor: consolidate device and client servers onto single port Jul 5, 2026
@nedpals
nedpals merged commit 1e86fab into master Jul 5, 2026
2 of 3 checks passed
nedpals pushed a commit that referenced this pull request Jul 5, 2026
Follow-up to the device/client server merge (#8). No behavior change —
comments, type docs, guide prose, and test-client labels only.

- nfc-client SDK: fix stale example port (18080 -> 9470) and note it
  connects to the shared agent port via plain /ws.
- nfc-device SDK: note it connects via /ws?mode=device on the same shared
  port; reword "Device Server" -> "NFC Agent".
- docs/api.md, docs/javascript-client.md, README.md: rename the
  "Device Server"/"Client Server" role wording to device/client
  endpoints of the single agent; update the section anchors and the links
  that point at them.
- test-client.html: relabel the two URL fields as "Agent URL (client)"
  and "Agent URL (device)".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK
nedpals added a commit that referenced this pull request Jul 5, 2026
Follow-up to the device/client server merge (#8). No behavior change —
comments, type docs, guide prose, and test-client labels only.

- nfc-client SDK: fix stale example port (18080 -> 9470) and note it
  connects to the shared agent port via plain /ws.
- nfc-device SDK: note it connects via /ws?mode=device on the same shared
  port; reword "Device Server" -> "NFC Agent".
- docs/api.md, docs/javascript-client.md, README.md: rename the
  "Device Server"/"Client Server" role wording to device/client
  endpoints of the single agent; update the section anchors and the links
  that point at them.
- test-client.html: relabel the two URL fields as "Agent URL (client)"
  and "Agent URL (device)".


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

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants