M0.2 — five avatars, one world
This sprint’s goal had two halves, and we only got to claim one of them honestly.
The half that’s true
Five avatars now replicate between clients over a real wss:// connection to
a server that’s actually deployed and reachable from off-box, not just
localhost. Every Join is credential-checked — there is no unauthenticated
fallback anywhere in the path, on purpose. An unauthorized join gets refused
with a real Goodbye message and a closed connection, and that refusal is
now verified in production, not just in a test suite.
The half that isn’t, yet
Nobody has actually played this with a friend. Not because the network doesn’t work — it does, and five avatars have been screenshotted standing in the same world, moving. It’s because there’s still nothing to do. Watching your own avatar stand next to four scripted ones isn’t a session; it’s a network diagnostic with legs. That half of the goal is carried forward honestly rather than quietly redefined as met, because there’s no verb to play with until the next sprint builds one.
The bug that only production could find
This is the interesting part, and it’s worth writing down in full because the failure mode is instructive.
The client’s WebSocket layer depends on a TLS library that, as of the version pinned in this project, compiles fine with no cryptography backend selected at all. That backend gets resolved at run time, the first time something actually tries to perform a TLS handshake — not at compile time, and not the moment the connection object is created.
Every test in the suite before this sprint spoke plain ws://. Every one of
them passed, cleanly, because a plaintext connection never reaches the code
path that needs a crypto backend. cargo test was green. cargo check was
clean. Nothing in the local development loop ever exercised the one line of
code that mattered.
Then the client tried to speak wss:// to the real deployed server for the
first time, and the process panicked on the very first handshake attempt —
“no process-level CryptoProvider available.” A perfectly compiling, perfectly
tested binary, dead on first contact with the one environment that actually
uses TLS.
The fix was small: declare a dependency purely to switch a feature flag on, non-wasm-gated so it costs the browser client nothing. The lesson is the bigger deliverable. A TLS code path is not exercised by a test suite that only ever speaks plaintext. If a connection type only gets used against a real deployed endpoint, it needs to be smoke-tested against a real deployed endpoint — no amount of local green checkmarks substitutes for that once.