From 784f30ddd740ce6c36b5b10a86b0c949de6e5e01 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Tue, 21 Jul 2026 11:22:03 +0200 Subject: [PATCH] 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 --- docs/guida-admin.md | 60 +++++++++++++++++++++++++++++ docs/guida-utente.md | 68 +++++++++++++++++++++++++++++++++ docs/running-the-server.md | 70 ++++++++++++++++++++++++++++++++++ docs/setup.md | 77 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 docs/guida-admin.md create mode 100644 docs/guida-utente.md create mode 100644 docs/running-the-server.md create mode 100644 docs/setup.md diff --git a/docs/guida-admin.md b/docs/guida-admin.md new file mode 100644 index 0000000..f3ab6ff --- /dev/null +++ b/docs/guida-admin.md @@ -0,0 +1,60 @@ +# Guida admin + +Come gestire la configurazione operativa di PLM Lottery. Presuppone che il +server sia già avviato — vedi [running-the-server.md](running-the-server.md). + +## Accesso + +Il pannello admin è su **`https:///admin`** — **non è collegato** da +nessun link nell'interfaccia utente (né in entrata né in uscita): ci si +arriva solo conoscendo l'URL. Non è protetto da login personale, ma da un +**token condiviso** (`ADMIN_TOKEN`, definito in `.env`). + +Apri la pagina, incolla il valore di `ADMIN_TOKEN` nel campo "Admin token" e +usa i bottoni: + +- **"Carica configurazione attuale"** → mostra `fee_address` e + `bet_amount_sats` (in PLM) correnti +- **"Salva"** → aggiorna i valori nel database, effetto immediato, nessun + riavvio del server necessario + +## Cosa si configura + +| Campo | Significato | +|---|---| +| **Fee address** | L'indirizzo PLM su cui finisce il 30% di ogni round (fee). Obbligatorio: i payout **non partono** se questo campo è vuoto. | +| **Bet amount (PLM)** | Il costo fisso d'ingresso per round, mostrato/impostato in PLM (internamente il backend lavora in sats: 1 PLM = 100.000.000 sats). | + +`ROUND_DURATION_SECONDS` (durata del round) **non** è qui: è una variabile +d'ambiente in `.env`, non modificabile a runtime — per cambiarla serve +riavviare il server con il nuovo valore. + +## Alternative all'interfaccia grafica + +Le stesse operazioni si possono fare da terminale o da Swagger UI +(`https:///docs`, sezione `admin`), sempre passando `ADMIN_TOKEN` +nell'header `X-Admin-Token`: + +```bash +# leggere la configurazione +curl https:///admin/config -H "X-Admin-Token: " + +# aggiornarla (importi in sats: 10 PLM = 1000000000) +curl -X PUT https:///admin/config \ + -H "X-Admin-Token: " \ + -H "Content-Type: application/json" \ + -d '{"fee_address": "plm1q...", "bet_amount_sats": 1000000000}' +``` + +## Limiti noti + +- Il token è unico e condiviso: non c'è identità per singolo admin né audit + di chi ha cambiato cosa (oltre alla tabella `audit_log` generica). +- Nessun rate limiting sugli endpoint admin (né su registrazione/bet/ + prelievo utente). +- Se un payout fallisce (es. Electrum disconnesso, UTXO insufficienti), il + round resta bloccato in `paying_out` senza retry automatico — richiede + intervento manuale. + +Per l'elenco completo dei gap noti vedi la sezione "Known gaps / TODO" in +`CLAUDE.md`. diff --git a/docs/guida-utente.md b/docs/guida-utente.md new file mode 100644 index 0000000..02ecbff --- /dev/null +++ b/docs/guida-utente.md @@ -0,0 +1,68 @@ +# Guida utente + +Come usare PLM Lottery dall'interfaccia web (`https:///` — vedi +[running-the-server.md](running-the-server.md) per come avviare il server). + +## Registrazione e accesso + +Nella schermata iniziale trovi due tab: **Registrati** e **Login**. + +- **Registrati**: scegli username e password. Al termine ti viene assegnato + automaticamente un **indirizzo di deposito personale** (derivato + server-side) — è per sempre tuo, e riceverai anche eventuali vincite su + quello stesso indirizzo. +- **Login**: se hai già un account, accedi con username e password. + +La sessione resta salvata nel browser (fino al logout): non serve rifare +login ogni volta che riapri la pagina. + +## La dashboard + +Dopo l'accesso vedi, in ordine: + +1. **Barra account** — il tuo username e il bottone "Esci" (logout) +2. **Card del round corrente** — sempre visibile, indipendentemente dalla + sezione che stai guardando: + - numero del round e stato (*aperto*, *in chiusura*, *estrazione in + corso*, *pagamento in corso*) + - **timer** che conta alla rovescia il tempo rimanente prima della + chiusura del round + - **giocatori**: quanti hanno già piazzato una bet in questo round + - **jackpot**: il totale in PLM che verrà distribuito (70% al vincitore, + 30% in fee) +3. **Menu di navigazione** con tre sezioni: + +### Deposito + +- Il tuo **saldo interno** (accreditato dopo 1 conferma di rete) con bottone + "Aggiorna" per ricontrollarlo +- Il tuo **indirizzo di deposito**, con bottone per copiarlo negli appunti +- Il **QR code** dello stesso indirizzo, comodo per inviare PLM da un altro + wallet scansionandolo invece di copiare l'indirizzo a mano + +Per depositare, invia PLM (mainnet reale) a quell'indirizzo da un wallet +esterno. Il saldo si aggiorna da solo dopo la prima conferma; premi +"Aggiorna" per vederlo comparire. + +### Bet + +Un bottone unico: piazza l'ingresso a costo fisso (mostrato in PLM) nel round +corrente. Puoi avere **al massimo una bet attiva alla volta**. Il costo viene +scalato dal tuo saldo interno. + +### Prelievo + +Form con due campi: +- **Indirizzo esterno**: dove vuoi ricevere i PLM +- **Importo (PLM)**: quanto prelevare + +Il prelievo viene costruito e trasmesso sulla rete; la fee di rete viene +scalata dall'importo richiesto (non si aggiunge separatamente). + +## Notifiche + +Ogni azione (registrazione, login, bet, prelievo, ecc.) mostra un breve +messaggio (toast) verde in caso di successo o rosso in caso di errore, in +basso nella pagina. Se qualcosa non va e il messaggio non basta a capire il +motivo, il dettaglio tecnico è nei log del server (`logs/app.log` o +`data/logs/app.log` con Docker) — non nell'interfaccia. diff --git a/docs/running-the-server.md b/docs/running-the-server.md new file mode 100644 index 0000000..2a29367 --- /dev/null +++ b/docs/running-the-server.md @@ -0,0 +1,70 @@ +# Avviare il server + +Presuppone che [setup.md](setup.md) sia già stato completato (`.env` pronto, +master key generata, migrazioni applicate). + +## Locale / venv (sviluppo rapido) + +```bash +source .venv/bin/activate +uvicorn app.main:app --reload --port 8123 +``` + +- App su `http://127.0.0.1:8123/` +- Pannello admin su `http://127.0.0.1:8123/admin` +- Log applicativi in `logs/app.log` (rotante, 10MB × 5 backup) +- Nessun TLS, nessun reverse proxy — solo per test locali sulla tua macchina. + +Per fermarlo: `Ctrl+C`, oppure se lanciato in background con `nohup`: +```bash +pkill -f "uvicorn app.main:app" +``` + +## Docker + Caddy (consigliato, anche per i test con dominio/TLS) + +```bash +mkdir -p data/db data/keys data/logs # una tantum, se non già presenti +docker compose up -d --build +``` + +- Caddy fa da reverse proxy davanti all'app e gestisce il TLS automaticamente +- App su `https://localhost/` (o sul dominio configurato, vedi sotto) +- Pannello admin su `https://localhost/admin` +- DB, master key cifrata e log persistono in `./data/` sulla root del repo + (bind mount, non volumi Docker opachi) — sopravvivono a stop/rebuild del + container e sono ispezionabili/backup-abili direttamente + +### Modalità dev, senza dominio (certificato self-signed) + +Non serve fare nulla: lasciando `SITE_ADDRESS` non impostata, Caddy usa +`localhost` di default. Rilevando che non è un hostname pubblico, genera da +solo un certificato dalla sua CA interna — il browser mostrerà un avviso di +sicurezza al primo accesso (normale, accettalo o usa `curl -k`). + +### Modalità produzione, con dominio reale + +```bash +SITE_ADDRESS=lottery.tuodominio.it docker compose up -d +``` + +Il DNS del dominio deve già puntare all'IP del server, con le porte 80 e 443 +raggiungibili da internet. Caddy richiede e rinnova automaticamente un +certificato Let's Encrypt reale — nessuna configurazione aggiuntiva. + +### Comandi utili + +```bash +docker compose logs -f app # segui i log dell'app (anche in ./data/logs/app.log) +docker compose ps # stato dei container +docker compose stop # ferma senza rimuovere i container +docker compose down # ferma e rimuove i container (i dati in ./data/ restano) +``` + +### ⚠️ Attenzione: riavvii automatici a metà round + +`docker-compose.yml` imposta `restart: unless-stopped` sul container dell'app: +se crasha, riparte da solo. Questo però non è ancora sicuro in ogni caso — se +il crash avviene mentre un round è in stato `closing`/`drawing`/`paying_out`, +lo scheduler non lo riprende al riavvio e il round resta bloccato (gap noto, +vedi "Known gaps" in `CLAUDE.md`). Non trattare questo setup come +"non supervisionato" finché quel gap non è risolto. diff --git a/docs/setup.md b/docs/setup.md new file mode 100644 index 0000000..00e233b --- /dev/null +++ b/docs/setup.md @@ -0,0 +1,77 @@ +# Setup + +Passaggi da eseguire una tantum per preparare un'istanza di PLM Lottery, prima di +poterla avviare (in locale o via Docker). Per come avviarla poi ogni volta, vedi +[running-the-server.md](running-the-server.md). + +## 1. Prerequisiti + +- Python 3.12+ (serve solo per il workflow locale/venv — puoi saltarlo se usi solo Docker) +- Docker + Docker Compose (serve solo per il workflow a container) +- Un server Electrum raggiungibile per la rete PLM. Il server di bootstrap per lo + sviluppo è `santantonio.sytes.net:50002` (SSL) — va bene per i test, ma in + produzione conviene usarne uno di cui ci si fida o gestirne uno proprio. + +## 2. Creare il file `.env` + +Copia `.env.example` in `.env` e compila i segreti. Ogni valore sotto viene +generato una volta e non cambia più (ruotarlo invalida sessioni/dati cifrati +esistenti): + +```bash +cp .env.example .env +``` + +| Variabile | Scopo | Come generarla | +|---|---|---| +| `XPRV_ENCRYPTION_KEY` | Chiave simmetrica che cifra a riposo la master xprv del server. **Perdere questa chiave significa perdere per sempre l'accesso ai fondi di tutti gli utenti.** | `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"` | +| `JWT_SECRET` | Firma i token di sessione degli utenti. | `python -c "import secrets; print(secrets.token_urlsafe(32))"` | +| `ADMIN_TOKEN` | Token bearer richiesto sugli endpoint admin (header `X-Admin-Token`). | `python -c "import secrets; print(secrets.token_urlsafe(32))"` | + +Le altre chiavi di `.env` (`DATABASE_URL`, `ELECTRUM_HOST`/`PORT`/`USE_SSL`, +`MASTER_KEY_PATH`, `ROUND_DURATION_SECONDS`) hanno default sensati in +`.env.example` — modificali se serve (es. round più corti per i test). + +**Non committare mai `.env`.** È già escluso da `.gitignore`. + +## 3. Generare la master key + +Il server deriva l'indirizzo di deposito di ogni utente (e l'indirizzo pool) da +un'unica master xprv, generata una volta e cifrata a riposo con +`XPRV_ENCRYPTION_KEY`. Questo passaggio va eseguito esattamente una volta per +ogni deployment, dopo aver impostato `XPRV_ENCRYPTION_KEY` in `.env`: + +- **Locale/venv**: `PYTHONPATH=. python scripts/generate_master_key.py` +- **Docker**: `docker compose run --rm app python scripts/generate_master_key.py` + +Questo scrive un file cifrato (`MASTER_KEY_PATH`, default `./master.xprv.enc` in +locale o `./data/keys/master.xprv.enc` con Docker). **Fai il backup di questo +file insieme a `XPRV_ENCRYPTION_KEY`** — uno dei due da solo è inutile, ma +perderli entrambi insieme significa perdere i fondi di tutti gli utenti senza +possibilità di recupero. + +## 4. Installare le dipendenze (solo workflow locale/venv) + +Salta questo passaggio se usi solo Docker — l'immagine installa le proprie +dipendenze durante la build. + +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install -e ".[dev]" +``` + +## 5. Applicare le migrazioni del database + +- **Locale/venv**: `alembic upgrade head` +- **Docker**: le migrazioni vengono eseguite automaticamente all'avvio del + container (vedi il `CMD` del `Dockerfile`) — nessun passaggio manuale. + +## 6. Impostare l'indirizzo delle fee + +Prima che il primo round possa pagare, un admin deve impostare `fee_address` +tramite il pannello admin o l'API — vedi [admin-guide.md](admin-guide.md). I +payout si rifiutano di partire finché non è impostato. + +A questo punto l'istanza è pronta per essere avviata — continua con +[running-the-server.md](running-the-server.md).