summaryrefslogtreecommitdiffstats
path: root/AGENTS.md
diff options
context:
space:
mode:
Diffstat (limited to 'AGENTS.md')
-rw-r--r--AGENTS.md56
1 files changed, 56 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..c5139d5
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,56 @@
1# Project Conventions for zagan-bet
2
3## Type Safety
4- SQLite `INTEGER` is `i64`. Never cast to `u64` without a bounds check.
5- Balance, bet, and winnings fields must agree on `i64` or `u64` across the
6 entire codebase — pick one and enforce it.
7- Negative balance is a state the DB can represent; the application must reject
8 plays that would produce one, not silently wrap via `as u64`.
9
10## Game Logic
11- Never compute the same payout/result in two places. `process_action` and
12 `calculate_result` must not both independently derive winnings.
13 The canonical split: `process_action` mutates state and stores raw data
14 (reels, win_type); `calculate_result` reads that data and produces the
15 `GameResult`. One path, one formula.
16- When checking symmetry (e.g. two-of-a-kind), enumerate **all** pairs, not
17 just adjacent indices. `[a, b, a]` is a valid match.
18
19## Session Tracking
20- Every `PLAY_START` must produce a session entry before the balance is
21 touched. The session is the audit trail for the deduction; without it the
22 deduction is orphaned.
23- Clean up sessions on client disconnect. If a game is in progress when the
24 connection drops, the server must roll back the bet.
25
26## Server Handler
27- Never hold a lock, drop it, then re-acquire it in the same function to
28 mutate the same resource. Acquire once, scope the lock to the operation.
29- All balance mutations (`SET balance = balance ± ?`) must happen in a
30 transaction.
31
32## Client TUI
33- `render_lines()` and `render()` must agree. If `render()` uses `\r\n`,
34 count lines against the same string the cursor will erase.
35 Prefer returning a fixed known count for the game's static layout and
36 letting dynamic content fill it, rather than inferring the count.
37
38## Error Paths
39- When a game action fails after a balance deduction, the refund must happen
40 in the same transaction scope as the deduction, not as a separate
41 `execute()` call.
42- Never silently ignore `Err` on balance mutations. If the refund fails,
43 log the username, balance, and operation; surface to the operator.
44
45## Tests
46- Every `calculate_payout` / `calculate_result` edge case gets a unit test
47 in `tests/`. Tests that exercise game logic use a deterministic seed or
48 a test helper that calls the function directly, not the network.
49- A change to game logic that breaks an existing payout pattern must fail
50 a test before it reaches the server.
51
52## TLS / TOFU
53- See `src/tofu.rs` for the trust model. The fingerprint is over the
54 certificate's SPKI, not the whole certificate.
55- `save_host` must not wipe the fingerprint column. Use `ON CONFLICT ...
56 DO UPDATE SET last_used` — never `INSERT OR REPLACE`.