fix(vloer): serve the agent host's WebSocket through ws #176

Merged
ryangr0 merged 1 commit from ryangr0/vloer-websocket-ws into development 2026-10-03 12:16:55 +00:00 AGit
Owner

The agent host's hand-written RFC 6455 parser accepted a text frame
with a reserved bit set, invalid UTF-8, a fragmented ping and an orphan
continuation frame without closing, and send() ignored socket.write()
backpressure, so a peer that stopped reading grew server memory.

websocket.ts now completes the upgrade through a ws WebSocketServer in
noServer mode (no compression, no subprotocol, maxPayload 16 MiB,
one-second closeTimeout) and keeps the connection interface the host
uses. Protocol violations close with 1002/1007/1009, and a send to a
peer with more than 16 MiB unread disconnects it. The token check on
the upgrade is unchanged. ws 8.22.0 is pinned as the one runtime
dependency (ADR 0036, amending ADR 0002 and 0012); check.mjs accepts
only ADR-mapped, exact-pinned runtime dependencies, license:check
requires a permitted licence, a NOTICE line and an npm ci --omit=dev
in the Dockerfile, and the image now installs it.

Vloer's first runtime dependency: ws 8.22.0 (MIT, no dependencies), exact-pinned, per the owner's 2026-10-03 decision recorded in Vloer ADR-0036 (amends ADR-0002 and ADR-0012). check.mjs and license-check.mjs now allow only ADR-listed, exact-pinned runtime deps with a licence, NOTICE entry and Dockerfile npm ci line. The image now runs npm ci --omit=dev in its stage; a local build shipped only ws. Running the demo from a fresh checkout now needs npm ci (mise run setup covers it). The 11 new raw-frame tests cover RSV, invalid UTF-8 (1007), fragmented ping, orphan continuation, unmasked frames, 16 MiB limit and slow readers.

Verified with mise run verify on the pinned toolchain (all gates passed).

Ticket: https://vikunja.webgrip.dev/tasks/1723

🤖 Generated with Claude Code

The agent host's hand-written RFC 6455 parser accepted a text frame with a reserved bit set, invalid UTF-8, a fragmented ping and an orphan continuation frame without closing, and send() ignored socket.write() backpressure, so a peer that stopped reading grew server memory. websocket.ts now completes the upgrade through a ws WebSocketServer in noServer mode (no compression, no subprotocol, maxPayload 16 MiB, one-second closeTimeout) and keeps the connection interface the host uses. Protocol violations close with 1002/1007/1009, and a send to a peer with more than 16 MiB unread disconnects it. The token check on the upgrade is unchanged. ws 8.22.0 is pinned as the one runtime dependency (ADR 0036, amending ADR 0002 and 0012); check.mjs accepts only ADR-mapped, exact-pinned runtime dependencies, license:check requires a permitted licence, a NOTICE line and an npm ci --omit=dev in the Dockerfile, and the image now installs it. Vloer's first runtime dependency: ws 8.22.0 (MIT, no dependencies), exact-pinned, per the owner's 2026-10-03 decision recorded in Vloer ADR-0036 (amends ADR-0002 and ADR-0012). check.mjs and license-check.mjs now allow only ADR-listed, exact-pinned runtime deps with a licence, NOTICE entry and Dockerfile npm ci line. The image now runs npm ci --omit=dev in its stage; a local build shipped only ws. Running the demo from a fresh checkout now needs npm ci (mise run setup covers it). The 11 new raw-frame tests cover RSV, invalid UTF-8 (1007), fragmented ping, orphan continuation, unmasked frames, 16 MiB limit and slow readers. Verified with `mise run verify` on the pinned toolchain (all gates passed). Ticket: https://vikunja.webgrip.dev/tasks/1723 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(vloer): serve the agent host's WebSocket through ws
Some checks are pending
[Workflow] On Pull Request / checks (pull_request) Successful in 6m40s
[Workflow] On Pull Request / warnings (pull_request) Waiting to run
[Workflow] On Pull Request / release-policy (pull_request) Successful in 31s
5b20156eae
The agent host's hand-written RFC 6455 parser accepted a text frame
with a reserved bit set, invalid UTF-8, a fragmented ping and an orphan
continuation frame without closing, and send() ignored socket.write()
backpressure, so a peer that stopped reading grew server memory.

websocket.ts now completes the upgrade through a ws WebSocketServer in
noServer mode (no compression, no subprotocol, maxPayload 16 MiB,
one-second closeTimeout) and keeps the connection interface the host
uses. Protocol violations close with 1002/1007/1009, and a send to a
peer with more than 16 MiB unread disconnects it. The token check on
the upgrade is unchanged. ws 8.22.0 is pinned as the one runtime
dependency (ADR 0036, amending ADR 0002 and 0012); check.mjs accepts
only ADR-mapped, exact-pinned runtime dependencies, license:check
requires a permitted licence, a NOTICE line and an npm ci --omit=dev
in the Dockerfile, and the image now installs it.

VIK-1723

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ryangr0 merged commit f55ee16676 into development 2026-10-03 12:16:55 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
webgrip/unfold!176
No description provided.