1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
# 0001: Testable client and server cores
Status: Accepted (2026-10-28)
## Context
The client and server started as binaries with their game logic and I/O mixed
together. That made the TUI hard to reason about: a spin appended results below
the board, a later bet change redrew at the wrong line, and none of it could be
tested without a terminal. The server handler had the same problem: it owned
static database and session state, so its security-sensitive paths could not be
exercised from `tests/`.
## Decision
- The library (`src/lib.rs`) owns shared logic. `src/bin/client` and
`src/bin/server` are thin adapters for crossterm, TLS, environment variables,
and interactive prompts.
- `client::core::ClientCore` owns input, history, commands, game state, and
pending replies. It returns `Effect`s (`Print`, `ReplaceRegion`, `ClearRegion`,
`SetPrompt`, `SendLine`, `Interactive`, ...). The binary applies them; the
tests apply them to a headless screen.
- `server::core::ServerCore` owns message handling and receives an injected
`Connection`, `GameRegistry`, and bcrypt cost. The binary only owns the TLS
listener and per-connection thread.
- Tests live in `tests/` and exercise the library. Pure UI math is tested
directly; terminal ANSI output is checked manually with `docs/TESTING.md`.
There are no PTY tests because they cannot cover Windows and `RULES.md`
requires identical behaviour on all platforms.
- The client keeps sending its SHA-256 credential. The server stores
`bcrypt(credential)` and upgrades legacy SHA-256 rows on the first successful
login. This protects a stolen server database without changing the wire
protocol, but the client-side credential remains replayable if `client.db`
leaks.
- Each settled spin writes a durable `plays` row in the same transaction as the
balance updates. The in-memory session is a transient guard and is removed
as soon as the spin settles or fails.
## Consequences
- Client flows and server security rules are testable without a terminal or a
network. A visual bug becomes an assertion about the headless screen.
- The binaries have an extra translation layer (`Effect` application), and the
server opens a SQLite connection per client.
- Terminal rendering still needs a manual Linux/Windows pass; the checklist is
in `docs/TESTING.md`.
- Password storage is stronger, but not a full PAKE. A future MAJOR protocol
change can replace the replayable credential.
|