refactor: consolidate device and client servers onto single port#8
Merged
Merged
Conversation
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
This reverts commit a187de8.
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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=devicequery parameter orX-Device-Modeheader for devices; plain/wsfor clients).Key Changes
New
server/unifiedserverpackage: Fronts both device and client servers with a single HTTP listener, mDNS advertisement, and shared CORS/health handling. Routes incoming/wsconnections to the appropriate handler based ondeviceserver.IsDeviceConnection().Refactored
deviceserver.Serverandclientserver.Server:Start()→StartBackground(ctx)to clarify they no longer bind listenersServeWS(w, r)public method for unified server to route connectionsenableCORS()andstartMDNS()methods (moved to unified server)Configstructs to removePort,CertFile,KeyFilefieldsUpdated
Agent:ClientPortfield; singleDevicePortnow serves both rolesUnifiedServerfield to manage the single listenerstartServers()to instantiate unified server and callStartBackground()on device/client serversHealth endpoints: Both
/healthand/api/v1/healthnow served on the single port, reporting"type":"agent"instead of separate device/client types.Documentation and CLI:
-client-portflagTests: Added
server/unifiedserver/server_test.gowith routing verification and health endpoint tests.Implementation Details
deviceserver.IsDeviceConnection()discriminator to route connections, maintaining backward compatibility with device clients using?mode=deviceor theX-Device-Modeheader.ServerBridgebetween device and client handlers remains unchanged.https://claude.ai/code/session_019UWqA9fEkcZQyEk9qujEqK