From 47d6c82a4943b1e804d062780b8e05f1e42f27b0 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 28 Oct 2026 22:46:47 +0100 Subject: v0.3.1: clean up dependencies, stale tests and document verification --- docs/adr/0001-testable-client-server-cores.md | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 docs/adr/0001-testable-client-server-cores.md (limited to 'docs/adr') diff --git a/docs/adr/0001-testable-client-server-cores.md b/docs/adr/0001-testable-client-server-cores.md new file mode 100644 index 0000000..2e3cd1e --- /dev/null +++ b/docs/adr/0001-testable-client-server-cores.md @@ -0,0 +1,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. -- cgit v1.2.3