Per-username lockout (5 failed TOTP attempts / 5 min) stops account-targeted
brute force regardless of source IP. Player.totp_secret is now Fernet-
encrypted (ENCRYPTION_KEY env, db/crypto.py) instead of stored in plaintext,
and auth_token is stored as a SHA-256 hash rather than the raw session token.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Remove config.py, an unused Flask SECRET_KEY leftover from before the
legacy HTTP backend was replaced by the Socket.IO/ASGI server.
- Move tests.py / tests_history.py / test_socket.py into a tests/
package as test_engine.py / test_history.py / test_socket.py, and
update CLAUDE.md's documented commands to match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>