Codemojex · C1.3
The privacy boundary.
The privacy boundary is structural, not a filter at the edge. The secret exists in exactly one
place a player can never read — the games row and its immutable cache copy — and no
player-facing view selects it. A player sees their own attempt history and no one else's; the live events and the
leaderboard carry a name and a score, never the code or the guess. Privacy is a property of the shape of
the reads, enforced in Codemojex.View.
Pick a read below. Each returns only public fields — and the teal chip is the thing it structurally omits.
Codemojex.View.game_view/1 builds the public map — the emojiset snapshot, the prize, timer, and status, and (post-reveal) the totals. It never puts :secret. Story: there is no :secret key anywhere in the view — only the keyboard snapshot.
Shaped reads, not edge filters
Codemojex.ViewCodemojex.View's moduledoc states the invariant plainly: "nothing here returns the
secret, and nothing returns another player's guesses." The three reads carry it in their shape, not as a
redaction pass. game_view/1 assembles a public map and never puts :secret;
my_history/3 calls Store.guesses_for(player, n) — scoped to the caller —
and takes [:emojis, :points, :at_ms]; leaderboard/2 returns {player, max_score}
rows through Board.top, never the emojis. There is no edge that could forget to redact, because the
reads do not select what a player must not see.
test/stories/privacy_story_test.exsstories# Scenario: the game view never carries the secret Given an open game whose secret was minted server-side When the client fetches the game view Then there is no :secret key anywhere in the view — only the keyboard snapshot # Scenario: a player's history shows only their own attempts Given both players have submitted a guess When Alice reads her history Then she sees her own guess and nothing of Bob's # Scenario: the leaderboard exposes scores, never guess content Given a scored attempt on the board When the leaderboard is read Then every row is a {player, score} pair with no emojis attached
The golden gate widens
revealed?/1For a golden (blind) game the gate widens, and the rule is one function:
revealed?(r) is feedback != "none" or revealed_ms not nil. Toggle the mode — the
chips that cross the wire light up; the dashed chips are withheld.
revealed_ms is set. Source: Codemojex.View · revealed?/1 · design §Privacy.Classic — a guess is scored and shown live; the totals and leaderboard cross the wire. There is no commitment, and the secret never leaves the server. revealed?(r) is true because feedback != "none".
The secret's one place
schemas/game.exCodemojex.Schemas.Game's moduledoc is explicit: "the secret (and, for a golden game,
the nonce) is a server-side column and is never serialized to players." The secret and
nonce fields are written server-side and never sent; the commitment is published from
open — public by design, because it binds the server to the secret it fixed — and revealed_ms
is the gate that opens the score. The boundary is drawn in the shape of the data: the secret has exactly one home,
a player has no read that selects it, and a golden game exposes the secret and the nonce only at the sealed
reveal, so a player can recompute SHA-256(secret ‖ nonce) and verify the commitment for
themselves. That verifiability is the subject of the next chapter.
References
sources · relatedSources
- Helland — Life Beyond Distributed Transactions (CIDR 2007)the privacy seam: entities behind boundaries expose names, not internals.
- Commitment scheme — Wikipediathe hiding and binding properties the golden commitment needs.
Related
- C1 — The Game as Branded Systemsthe chapter hub.
- C1.2 — The four layersthe tier the secret rests on.
- C2 — Rooms, Modes, and the Secretthe secret and its commitment, next.