6 Commits
Author SHA1 Message Date
davideandClaude Sonnet 5 22e3cfb2be Disable Swagger/ReDoc/OpenAPI JSON by default (B-42)
They enumerate the entire API surface, admin endpoints included, to
anyone who requests them. Gate them behind a new ENABLE_API_DOCS
setting (off by default) and update README/docs and BUGS.md/CLAUDE.md
open-bug counts accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 15:34:49 +02:00
davideandClaude Opus 5 7c4e9983ea Survive a dropped Electrum connection, and fall back to other servers
A dropped connection used to hang the whole platform permanently, and three
defects composed to do it (BUGS.md B-01):

The read loop's death was invisible. When the socket closed, _read_loop broke out
and finished, but _run_once was blocked on gather() over two notification
consumers waiting on queues nobody would ever fill again — it never returned and
never raised, so the reconnect-with-backoff logic was unreachable.
client.wait_closed() now resolves when the loop ends for any reason, and
_run_once races it against the consumers and a keepalive with
asyncio.wait(FIRST_COMPLETED).

Nothing had a timeout. request() registered a future, wrote to a half-closed
socket (drain() often doesn't raise) and awaited a reply that would never come.
That hung a POST /bets *while holding the per-user lock*, and could stop the
confirmation poller for good. Every request is now bounded at 15s, and a timeout
tears the connection down rather than leaving a server that owes us a reply in
rotation.

There was no keepalive, so on a quiet instance the normal way this connection
dies is an idle-timeout drop by the server (~10 minutes for many). A server.ping
every 60s makes that observable within a minute.

listener.client is also cleared before reconnecting, so callers stop treating a
dead connection as live.

On top of the finding, the listener now rotates over a list of servers:
ELECTRUM_FALLBACK_SERVERS holds comma-separated host:port[:notls] extras, tried
after the primary. Everything the platform does goes through this one connection
— deposit credits, broadcasts, confirmations, the chain tip the draw waits on —
which made a single hardcoded server its biggest point of failure. A failed or
dropped session moves to the next server immediately and only sleeps on the
backoff once every server has had a turn, so one dead server costs one attempt
instead of an outage, while a genuinely offline network still backs off. A
malformed entry fails at startup, not during the outage when the fallback is what
you need.

Also fixes B-19: header handling refuses a height below the current tip and
applies height and hex together, since _wait_for_next_block waits for
tip_height > tip_at_close (a regression silently added a block to the draw's
wait) and that hex is the draw's entropy source, so a mismatched pair would be
worse than a stale one.

Verified in the live deployment: the log shows the endpoint list, then "Electrum
connected to santantonio.sytes.net:50002", and the connection holds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 00:34:59 +02:00
davideandClaude Sonnet 5 aae0961c94 Bring docs in sync with recent features (pending balance, SSE, per-player reveal)
CLAUDE.md: bumped the stale test count (54 -> 76), added "Balance display"
and "Real-time updates (SSE)" sections, and rewrote the DRAW section's
frontend-reveal paragraph to describe the actual current behavior (dual
status/result boxes gated by user_played, closes_at-anchored reveal delay,
localStorage persistence, the last-round-result backstop) instead of the
older single-box design. Refined the "no history endpoints" known gap now
that GET /users/me/last-round-result exists (still not general history).

README.md: same test count fix, expanded coverage list.

docs/: fixed a pre-existing broken link in setup.md (admin-guide.md ->
guida-admin.md), added a note in running-the-server.md that editing the
bind-mounted Caddyfile needs an explicit `docker compose restart caddy`
(discovered while adding the SSE Caddy config in a prior change), and
rewrote guida-utente.md's draw/reveal section plus the balance/withdrawal
sections to match what the UI actually does now. guida-admin.md was
reviewed but needed no changes.

app/static/style.css: dropped `.toast.info`, dead since the toast-based
loss notification it styled was replaced by the persistent result box.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:05:27 +02:00
davideandClaude Sonnet 5 1941f30b10 Add ops scripts to decrypt/re-encrypt the master xprv, and document them
decrypt_master_key.py: prints the existing master xprv after an explicit
confirmation prompt, for disaster-recovery backups. Falls back to
./data/keys/master.xprv.enc (the docker-compose.yml bind-mount path) when
.env's configured MASTER_KEY_PATH doesn't exist locally.

encrypt_master_key.py: the reverse direction — takes an externally-generated
xprv (e.g. created offline/air-gapped) via a hidden getpass prompt, validates
it parses as a private extended key, and encrypts it with the same Fernet
scheme generate_master_key.py uses. Refuses to overwrite an existing key file
unless --overwrite is passed.

Neither script is reachable via any API endpoint or the admin panel, by
design — this is the one secret the entire custodial wallet derives from.
Documented in docs/setup.md (new "Recuperare o portare una xprv esistente"
section) and CLAUDE.md's Commands block.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 16:20:03 +02:00
davideandClaude Sonnet 5 0e56f63e63 Document the DB-only config model and the new dashboard sections
CLAUDE.md and docs/guida-admin.md now describe RoundConfig as the sole
source of truth for business parameters, with no env var counterpart —
defaults live as hardcoded model column defaults, not app/config.py.
guida-admin.md documents the four new dashboard sections (Round,
Transazioni pendenti, Audit log alongside Parametri/Utenti). setup.md
points readers to the admin panel instead of .env for those values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 15:06:51 +02:00
davideandClaude Sonnet 5 784f30ddd7 Add docs/ with separate setup, run, user and admin guides
Four standalone Markdown docs instead of growing CLAUDE.md further:
setup.md (one-time secrets/master-key/migrations), running-the-server.md
(local venv vs Docker+Caddy, dev self-signed vs production domain),
guida-utente.md (dashboard: deposit+QR, bet, withdrawal, round timer/
jackpot) and guida-admin.md (the /admin panel and its API equivalent).
Written in Italian per explicit request, unlike the rest of the
repository's English-only docs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 11:22:03 +02:00