RoundConfig gets a paused flag toggled via new POST /admin/pause and /admin/resume endpoints (audit-logged, surfaced as a "Manutenzione" card in the admin Parametri view). Pausing only stops the *next* round from opening once the current one closes — rounds/service.py:open_new_round_if_needed still lets an in-progress round finish, draw, and pay out its winner normally. GET /rounds/current exposes lottery_paused so the user page shows a maintenance banner (even while logged out) instead of silently going idle. Also replaces the user dashboard's stacked account-bar card + bento-grid menu with a single sticky navbar (identity row + Deposito/Bet/Prelievo tabs), and moves the page content into a dedicated .app-shell container so the navbar itself can span full width.
152 lines
7.8 KiB
Markdown
152 lines
7.8 KiB
Markdown
# 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. La pagina mostra solo un campo token finché non
|
|
accedi: non è protetta da login personale, ma da un **token condiviso**
|
|
(`ADMIN_TOKEN`, definito in `.env`).
|
|
|
|
Incolla il valore di `ADMIN_TOKEN` e premi "Accedi" (o Invio): se il token è
|
|
valido, si apre la dashboard con una navbar in alto e carica automaticamente
|
|
tutte le sezioni — nessun bottone "Carica" separato. Il token resta in
|
|
`sessionStorage` (si perde chiudendo la tab/il browser); "Esci" torna alla
|
|
sola schermata di login.
|
|
|
|
## Sezioni della dashboard
|
|
|
|
- **Parametri** — configurazione operativa (vedi tabella sotto)
|
|
- **Utenti** — elenco utenti, saldo, accesso alla chiave privata
|
|
- **Round** — storico round: stato, vincitore, importi, txid di payout
|
|
- **Transazioni pendenti** — bet/payout/prelievi non ancora confermati, candidati al fee-bump RBF
|
|
- **Audit log** — eventi registrati dal sistema (config cambiata, bet, payout, accessi a chiavi private, ecc.)
|
|
|
|
## Parametri
|
|
|
|
Tutti i parametri operativi/di business sono nella sezione "Parametri",
|
|
salvati nel database — modificabili in qualsiasi momento, effetto immediato,
|
|
**nessun riavvio del server necessario**. Non esiste alcuna variabile
|
|
d'ambiente equivalente: `.env` contiene solo segreti e configurazione di
|
|
infrastruttura (chiave master, JWT, Electrum, token admin), non parametri di
|
|
business — quelli si toccano solo da qui.
|
|
|
|
| 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. |
|
|
| **Durata round (secondi)** | Quanto resta aperto un round prima di chiudersi ed estrarre il vincitore. |
|
|
| **Pausa tra un round e il successivo (secondi)** | Cooldown dopo la chiusura di un round, prima che il successivo si apra — dà tempo ai giocatori di vedere l'esito. |
|
|
| **Durata animazione estrazione (secondi)** | Tempo minimo per cui la dashboard di ogni utente mostra l'animazione "Estrazione in corso" dopo la chiusura del round, prima di rivelare il vincitore. È solo un minimo: l'estrazione reale aspetta un blocco confermato (~2 minuti in media), quindi l'animazione può durare più a lungo di questo valore, mai meno. |
|
|
| **Importo minimo deposito/prelievo (PLM)** | Soglia minima per un prelievo (i depositi non hanno un controllo minimo lato server, solo un floor consigliato). |
|
|
| **Fee rate di rete (sat/vB)** | Fee per byte usata per costruire bet, payout e prelievi. |
|
|
| **Timeout prima del fee-bump RBF (secondi)** | Dopo quanto tempo senza conferma una transazione viene ritrasmessa con fee più alta. |
|
|
|
|
Tutti gli importi in PLM vengono convertiti in sats (1 PLM = 100.000.000 sats)
|
|
solo nella chiamata API — il backend lavora sempre in sats.
|
|
|
|
Su un'istanza nuova (mai avviata), questi campi partono con dei default
|
|
hardcoded nel codice (`RoundConfig` in `app/db/models.py`: bet 10 PLM, round
|
|
10 minuti, cooldown 30s, animazione estrazione 20s, minimo 1 PLM, fee 1
|
|
sat/vB, RBF timeout 900s) — vanno
|
|
comunque rivisti e confermati dal pannello prima del primo utilizzo reale.
|
|
|
|
## Manutenzione (pausa/ripresa lotteria)
|
|
|
|
In cima alla sezione "Parametri" c'è una card "Manutenzione" con un pulsante
|
|
per fermare l'apertura di nuovi round — utile per intervenire sul server
|
|
(aggiornamenti, riavvii) senza lasciare gli utenti a metà di un round o
|
|
sorprenderli con un'interruzione improvvisa.
|
|
|
|
- **"Interrompi dopo questo round"**: il round eventualmente in corso viene
|
|
**completato normalmente** — chiude, estrae il vincitore da un blocco
|
|
confermato, e paga il 70/30 come sempre. Solo l'apertura del **round
|
|
successivo** viene sospesa. Gli utenti vedono un avviso di manutenzione
|
|
sulla loro dashboard (e sulla home, anche da sloggati) finché la lotteria
|
|
resta in pausa.
|
|
- **"Riprendi lotteria"**: annulla la pausa — al prossimo giro dello
|
|
scheduler (ogni 5 secondi) un nuovo round si apre normalmente (rispettando
|
|
comunque il cooldown se il precedente si è appena chiuso).
|
|
|
|
Ogni pausa/ripresa viene registrata nell'audit log (`lottery_paused` /
|
|
`lottery_resumed`), ma — come per il resto del pannello — non registra
|
|
*quale* operatore l'ha premuta (token condiviso, vedi limiti noti in
|
|
[CLAUDE.md](../CLAUDE.md)).
|
|
|
|
**Chi paga il fee-bump RBF?** Quando una bet, un payout o un prelievo resta
|
|
troppo a lungo senza conferma (oltre il "Timeout prima del fee-bump RBF"), il
|
|
sistema lo ritrasmette con una fee più alta. Il costo aggiuntivo lo assorbe
|
|
sempre **chi ha originato la transazione**, non il destinatario: per bet e
|
|
prelievi è l'utente stesso (gli torna un resto più piccolo), per i payout è
|
|
il pool (il resto che torna all'indirizzo pool si riduce) — la quota del
|
|
vincitore e quella delle fee, già fissate, non vengono mai toccate. Se non
|
|
c'è un resto abbastanza grande da assorbire l'aumento, il bump fallisce e
|
|
resta un intervento manuale (vedi "Limiti noti").
|
|
|
|
## Round
|
|
|
|
La sezione "Round" mostra lo storico (`GET /admin/rounds`, ultimi 50 per
|
|
default): id, stato, orario di apertura, vincitore (username), importo del
|
|
pool, importo vinto, importo di fee, txid del payout — tutti in PLM salvo il
|
|
txid.
|
|
|
|
## Transazioni pendenti
|
|
|
|
`GET /admin/pending-transactions` elenca bet, payout e prelievi ancora senza
|
|
conferma: tipo, stato, txid corrente, fee rate usata, numero di tentativi
|
|
(si incrementa a ogni bump RBF) e orario dell'ultima trasmissione. Una riga
|
|
che resta qui a lungo, con `attempt_count` che sale, indica una transazione
|
|
in difficoltà — vedi "Limiti noti" sul fallback RBF.
|
|
|
|
## Audit log
|
|
|
|
`GET /admin/audit-log` elenca gli ultimi 200 eventi registrati dal sistema
|
|
(tipo evento, payload JSON, utente/round coinvolti, timestamp): bet
|
|
piazzate, payout inviati, round chiusi, configurazione modificata, accessi
|
|
alle chiavi private, ecc. È il primo posto da controllare per ricostruire
|
|
cosa è successo dopo un problema.
|
|
|
|
## 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; solo i campi passati vengono cambiati)
|
|
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, "round_duration_seconds": 600}'
|
|
```
|
|
|
|
## Utenti e chiave privata
|
|
|
|
La card "Utenti" elenca id, username, indirizzo e saldo di ogni utente
|
|
registrato. Il bottone "Mostra" su ogni riga rivela la chiave privata (WIF)
|
|
di quell'utente, dietro conferma esplicita — serve per interventi manuali
|
|
(es. restituire fondi bloccati). **Ogni visualizzazione viene registrata
|
|
nell'audit log** (`admin_privkey_accessed`). Questo non introduce una nuova
|
|
falla: il server è già custodial, la chiave master da cui derivano tutte le
|
|
chiavi utente vive sul server — questo pannello espone solo qualcosa che
|
|
l'operatore può già fare via script.
|
|
|
|
## 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`.
|