Codemojex · C9.1
The crossing.
One scored attempt leaves the React island, crosses to the Elixir engine, and returns as fresh state. Along the way the branded id travels the whole distance — a JOB minted on submit, a GES written by the scorer, the PLR lane it rode, the GAM it belongs to. The secret and other players’ guesses never cross.
Grounding — liveview_boot/effector-pipeline.md · interactions.md §2 · game.ex (Codemojex.Guesses.submit/3 · ScoreWorker) · channel/model.ts.
GameEdge calls bridge.pushEvent("submit_guess", { emojis }) and clears its picks — the only client-owned state. The boot forwards it to the LiveView socket.The submit path
game.ex · effector-pipelineOn the server, Codemojex.submit/3 validates the guess (open, not expired, codes valid for the set), overlays the player’s locks, charges the wallet, then enqueues a branded JOB on the player’s PLR lane. The host never scores — the enqueue is the whole write; the reply is {:noreply}.
# validate · Locks.merge · Wallet.charge_guess, then: job = EchoData.BrandedId.generate!("JOB") payload = :erlang.term_to_binary({:guess, game, player, guess}) Lanes.enqueue(Bus.conn(), @queue, player, job, payload) # @queue "cm", lane = PLR
The ScoreWorker consumer claims the job, scores against the cached immutable secret, writes a GES guess and records the board, then fans the result out twice — onto EchoMQ’s retained log (durable, replayable) and a Phoenix.PubSub broadcast on "game:" <> gam (ephemeral, live). A blind golden game skips both: its first public signal is the one fat revealed frame at close.
# GameLive re-reads the privacy-safe view and pushes full state: push_event(socket, "game:update", game_props) # boot GameIsland hook → handle.update(props) → model.propsReceived(props) # $props updates; $view + $leaderboard recompute
The identity travels, the payload doesn’t
view.ex · the gateThe crossing carries identities and messages about identities — never object graphs, never the secret. Codemojex.View.game_view/1 is the privacy gate: it builds a player-facing view that never selects the secret and, for a blind golden game, withholds the per-guess scores and the leaderboard until close. Select each side.
game:update props cross the gate to seed the island’s $props. The id is the key on every frame — time-ordered, coordination-free, unchanged across the boundary.This is the BCS law on the wire: the only values that cross a boundary are identities, and messages about identities. A dropped frame is corrected by the next full game:update; a reconnect re-reads from scratch — the client can never drift from the server’s view.
References
sources · relatedSources
- Kreps — The Logthe retained bus log the scorer appends beside the live broadcast
- Phoenix.PubSubthe ephemeral fan-out on
game:<id>that feeds live subscribers - Effector — samplehow join replies and update frames land in
$props
Related
- C3 — Guesses on Fair Lanesthe lane the
JOBrides - C1 — The Game as Branded Systemsthe structural privacy boundary
- C9 — The Road to GameIslandthe chapter hub