Backend:
- fix(chat): ChatGateway stored the per-socket caller only after the async
token check resolved, so a client that sent chat:join immediately on open
raced ahead and got 4001. The caller is now stored as a promise that the
message handlers await. Verified with a two-client send/receive E2E test
against local Postgres.
Client (client/app/):
- Wahl screen gains a "Ergebnis" tab backed by GET /wahl/guest/results
(PENDING / ASSIGNED with workshop + wish rank / UNASSIGNED).
- Chat channel view loads history over REST, then connects the /chat
WebSocket (chat_socket.dart): live chat:message stream + a compose bar
that sends chat:send. Shows the socket status.
- web_socket_channel dependency added.
flutter analyze/test/build web all green; backend npm test 56.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>