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>
This commit is contained in:
@@ -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://<host>/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://<host>/docs`, sezione `admin`), sempre passando `ADMIN_TOKEN`
|
||||||
|
nell'header `X-Admin-Token`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# leggere la configurazione
|
||||||
|
curl https://<host>/admin/config -H "X-Admin-Token: <ADMIN_TOKEN>"
|
||||||
|
|
||||||
|
# aggiornarla (importi in sats: 10 PLM = 1000000000)
|
||||||
|
curl -X PUT https://<host>/admin/config \
|
||||||
|
-H "X-Admin-Token: <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`.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Guida utente
|
||||||
|
|
||||||
|
Come usare PLM Lottery dall'interfaccia web (`https://<host>/` — 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.
|
||||||
@@ -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.
|
||||||
@@ -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).
|
||||||
Reference in New Issue
Block a user