API tokens passed via ?token= query parameter were accepted on all HTTP
requests. This is a security concern because tokens in URLs can leak via
server logs, browser history, referrer headers, and proxy logs.
The query-string token path exists solely for WebSocket connections which
cannot set custom headers during the upgrade handshake. This change adds
an isWebSocketUpgrade check to all three query-string extraction sites
in CheckAuth and extractAndStoreAuthContext, rejecting ?token= on regular
HTTP requests while preserving WebSocket functionality.
No frontend impact — the kiosk flow stores the token in sessionStorage
then uses X-API-Token headers for all API calls.