Cross-backend parity suite for the per-connection outbound bound over a
real upgrade.
Both spines hold what waits to be written to one WebSocket to a byte budget
(BackendWebsocketTransport's outbound_queue_bytes on the TS side, the
Rust fuz_realtime outbound queue on the other; both default to 4 MiB, each
waiting frame charged its UTF-8 length plus 64 bytes). A frame that does not
fit closes the socket with WS_CLOSE_OUTBOUND_OVERFLOW and the reason
outbound queue overflow; the credential stays good, so a client reconnects
under its ordinary backoff. The code and the reason are therefore wire
contract, and this suite is the pin that runs on both.
It drives the backend's _testing_flood_notifications action, which queues
a burst of notifications onto the caller's own connection in one synchronous
run — so the burst waits at once whether or not the client is reading, and
the overflow is deterministic. The cases:
- within the budget — a small burst arrives whole and in order, ahead of
its response, and the socket stays open.
- large, within the budget — a burst of a few mebibytes, most of the
default budget, arrives the same way: every frame whole, in order, the
response last. Megabyte frames can outrun a socket's buffer, and where
they do — the Deno TS spine, as observed; Node and Bun write the burst
through — the frames behind the first wait on the backend's write pump.
- overflow — a burst far past the budget closes the socket with the code
and the exact reason; the response of the flooding request never arrives;
any flood frames that did arrive form a contiguous prefix of the burst.
A second connection on the same account keeps dispatching throughout.
- refusal — a burst past the action's own size limit is refused with
invalid_params, and the socket stays open. - no connection — over HTTP RPC the action refuses with
invalid_params
and reason no_connection, rather than answering as though it flooded. - the action's limits — over HTTP RPC a call at each of the action's
limits (
count, size, count × size) is refused for having no
connection, and a call one past each is refused invalid_params with no
reason. Both spines check the limits before they look for the connection
and before they build a payload, so the boundaries are read off the
refusal and no burst is ever allocated — which pins the two spines'
limits equal.
What the suite does not assert, because it is each implementation's own:
how many frames accepted before the overflow reach the client (the Rust
spine discards them all; the TS spine may deliver the first), and the exact
boundary a burst of tiny frames overflows at.
The wire literals are deliberate independent copies of the producers'
constants — parity by test, so a value changed on one side fails here
instead of moving both at once.
The flood action is gated on the daemon token, so the flooding socket
upgrades with it and no Origin (both spines discard a daemon token
presented in a browser context). Gated on capabilities.ws; cross-process
only (create_ws_transport needs a real bound socket), and only for a
backend that mounts _testing_flood_notifications on its WS endpoint.