Root cause: three critical bugs in the UDP upload flow:
1. Main server never registered sessions on the relay — it stored them
in its own memory but never called POST /session on the relay, so
the relay had no idea about any upload sessions.
2. Relay had no HTTP chunk endpoint — the Chrome extension sends chunks
via HTTP POST to /session/:id/chunk/:index, but the relay only had
a binary UDP listener. Added the HTTP fallback endpoint.
3. Relay had no CORS headers — browser requests from chrome-extension://
origins were blocked. Added CORS middleware.
The flow now works:
Browser → POST /api/udp/session (main server)
Main server → POST /session (relay, with s3Config)
Browser → POST /session/:id/chunk/:n (relay, via public URL)
Relay → S3 multipart upload
Browser → POST /api/udp/session/:id/complete (main server)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>