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