- GET /health/ready (Electrum connected, header < 1800s, scheduler heartbeat < 30s) is the container healthcheck; the scheduler beats on every tick and draw-wait iteration - GET /admin/electrum and an Electrum indicator in /admin (server, header age, last rotation) - GET /admin/audit-log: before_id, event_type, round_id, user_id, from, to; the panel gets filters - registration writes user_registered in its transaction - the app's own logs also go to stdout; uvicorn trusts X-Forwarded-For from Caddy's fixed address only, so the access log shows the client's IP Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
27 KiB
Limiti noti
Questo documento raccoglie i limiti noti (LIM): difetti di copertura o
di robustezza accettati consapevolmente, con l'impatto, ciò che oggi li
attenua e cosa servirebbe per chiuderli. Le decisioni di progetto non sono
più qui: ognuna è un ADR in adr/.
Un limite noto non è un bug: un bug è un comportamento che contraddice la
specifica e prende un numero B-nn (storico-bug.md). Se si
decide di chiudere un limite, si aggiorna prima la voce LIM qui (o la si
barra come rimossa) e poi il requisito del documento di dominio, secondo
processo-di-modifica.md.
Un limite che il piano delle correzioni chiuderà porta
*Stato:* da chiudere con B-nn, e Per chiuderlo descrive il comportamento
atteso; quando la correzione entra nel codice, il limite si barra come
~~[LIM-nn]~~ Rimosso: chiuso da B-nn.
Formato di ogni voce: descrizione, Impatto, Mitigazione attuale, Per chiuderlo, e il codice coinvolto.
Quali limiti bloccano il funzionamento non presidiato
La revisione del 2026-09-28 ha mostrato che la tabella precedente era
incompleta: oltre a drawing e all'RBF, bloccavano il funzionamento non
presidiato le falle critiche B-73 … B-82 (estrazione manipolabile, risposte
oltre 64 KiB, abbandoni su un solo server, pagamento senza riserva, deposito
spendibile due volte). La colonna Dopo il piano dice cosa resta una volta
implementato il piano delle correzioni.
| Limite | Blocca il non presidiato oggi? | Dopo il piano |
|---|---|---|
drawing non riprende dopo un errore o un riavvio |
Non più (chiuso da B-81) | — |
| [LIM-02] RBF di una sola forma | Non più il pagamento senza resto (B-79) né il resto sotto soglia (B-87); resta una transazione che esaurisce resto o riserva | Visibile in rbf_bump_failed; resta in attesa senza abbandono |
[LIM-03] Attesa in closing senza limite di tempo |
Sì, in caso di congestione | Resta senza limite di tempo per scelta (ADR-51); con B-78 e B-87 finisce quando la rete decide |
| [LIM-04] Prelievo e RBF mai provati in rete reale | Sì, come verifica | Da chiudere con la prova su rete reale (operativita.md) prima di aprire al pubblico |
| Non più (chiuso da B-82 e B-85) | Resta [LIM-24] | |
| [LIM-11], |
Non più (chiusi da B-82, B-83 e B-84) | Resta la scelta dell'operatore di server indipendenti ([LIM-11]) |
| [LIM-13] Estrazione manipolabile | Sì — per un giocatore che mina | Chiuso da B-73; resta [LIM-25] |
| [LIM-14] Header senza difficoltà minima | Sì — un header falso congela ogni estrazione | Chiuso da B-74 per il blocco; resta il costo basso di un header a difficoltà minima |
| [LIM-06] Token admin unico | No per il funzionamento, ma è il rischio di sicurezza più ampio | Invariato |
| tutti gli altri | No | — |
Robustezza del ciclo di vita
-
[LIM-01]Rimosso: chiuso da B-81. Un round indrawingriprende da solo dopo un errore o un riavvio, con lo stesso blocco, gli stessi partecipanti e lo stesso vincitore (RND-36). -
[LIM-02] L'RBF gestisce una sola forma di transazione: un'unica uscita riducibile — il resto verso il mittente per scommesse e prelievi, l'uscita di riserva per il pagamento (RND-38, B-79). Non c'è il ripiego «aggiungi un'altra moneta» né il CPFP. Ogni aumento costa almeno 1 sat/vB sull'intera dimensione della transazione (141 sat per una transazione con un ingresso e due uscite) e si toglie da quell'uscita; se quanto resta sarebbe sotto la soglia di polvere l'uscita viene eliminata e il suo valore va in commissione, e quella sostituzione è l'ultima (B-87, ADR-19); se nemmeno l'intera uscita raggiunge l'aumento minimo, o non esiste,
bump_feesollevaRbfError.- Impatto: con la rete congestionata una transazione a 1 sat/vB che ha
esaurito resto o riserva può restare in mempool indefinitamente. Poiché il
riconciliatore abbandona solo ciò che il server non conosce, una
transazione ferma ma presente in mempool non viene mai abbandonata: una
scommessa così blocca il round in
closing, un pagamento così lo blocca inpaying_out. - Mitigazione attuale: la riserva del pagamento è dimensionata per circa
10 sat/vB; resto minimo garantito sulle transazioni utente; tetto al fee
rate (
MAX_FEE_RATE_SAT_VB); ogni accelerazione impossibile o rifiutata scriverbf_bump_failed(una volta per transazione e motivo); abbandono dopo 6 ore per ciò che sparisce dalla rete; ritentativo automatico del pagamento dopo un abbandono. - Stato: accettato dopo B-79 e B-87: una transazione che ha esaurito resto o riserva e non conferma nemmeno al tetto del fee rate resta in attesa, visibile, e non viene abbandonata (ADR-51).
Codice:
app/tx/broadcast.py:bump_fee·app/wallet/psbt_builder.py:build_payout_transaction·app/tx/reconcile.py:reconcile_once - Impatto: con la rete congestionata una transazione a 1 sat/vB che ha
esaurito resto o riserva può restare in mempool indefinitamente. Poiché il
riconciliatore abbandona solo ciò che il server non conosce, una
transazione ferma ma presente in mempool non viene mai abbandonata: una
scommessa così blocca il round in
-
[LIM-03] L'attesa in
closingnon ha un limite proprio. Il round aspetta ogni scommessabuilding/broadcast. A porre fine all'attesa di una scommessa che non conferma è la sua conferma (una qualsiasi delle sue versioni) oppure il riconciliatore, ma solo con la prova che non è partita (ADR-51); una scommessa ferma ma presente in mempool trattiene il round senza limite ([LIM-02]).- Impatto: un round può restare chiuso ma non estratto per ore; nessun nuovo round si apre nel frattempo.
- Mitigazione attuale: lo stato è visibile (
closing) e il pannello «Transazioni pendenti» mostra la scommessa che trattiene il round. - Stato: B-78, B-77 e B-87 chiusi; resta per scelta l'assenza di un limite di tempo.
- Per chiuderlo: con B-78 l'attesa finisce quando la scommessa conferma (una qualsiasi delle sue versioni, B-77) o quando c'è la prova che non confermerà mai (ADR-51), non dopo un tempo fisso; con B-87 la scommessa resta accelerabile fino all'eliminazione del resto. Un limite di tempo resta escluso per scelta: escludere e rimborsare una scommessa lenta libererebbe fondi senza prova, che è ciò che ADR-51 vieta. Resta quindi accettato che una scommessa ferma al tetto del fee rate trattenga il round.
Codice:
app/rounds/scheduler.py:RoundScheduler._tick·app/tx/reconcile.py:_is_due -
[LIM-04] Prelievo e accelerazione RBF non sono mai stati inviati in una rete reale. Sono coperti da test unitari, rami di errore e annullamento compresi; il resto del flusso (registrazione, deposito, scommessa, un ciclo completo di round con pagamento) è stato verificato in mainnet.
- Impatto: un errore di costruzione o di firma specifico della rete reale emergerebbe al primo prelievo di un utente vero.
- Stato: da chiudere con la fase 7 del piano.
- Per chiuderlo: un prelievo e un RBF reali in mainnet, con verifica dell'aritmetica sulla transazione inviata, dentro la prova con importi piccoli e guasti provocati di operativita.md.
Codice:
app/withdrawals/service.py:request_withdrawal·app/tx/broadcast.py:bump_fee -
[LIM-05] Nessun test di integrazione con una connessione Electrum vera.
tests/integration/è vuota; la verifica dal vivo è stata tutta manuale (scripts/electrum_smoke_test.py, script ad hoc, transazioni reali).- Impatto: le differenze di comportamento fra implementazioni di server Electrum (formati di risposta, errori) emergono solo in produzione.
- Per chiuderlo: lo strato di test di guasto e di integrazione previsto in architettura.md (server Electrum simulati che rispondono in ritardo, tagliano la connessione, mandano risposte enormi o catene divergenti), più la prova su rete reale di operativita.md. Nessuna delle falle critiche del 2026-09-28 sarebbe stata trovata dai test attuali.
Codice:
tests/integration/__init__.py·scripts/electrum_smoke_test.py
Sicurezza e amministrazione
-
[LIM-06] Un unico token admin condiviso, senza identità per operatore. Il registro di audit dice cosa è cambiato (per esempio
config_updatedcon prima/dopo) ma non chi. Il token dà accesso a elenco utenti, esportazione delle chiavi private, reset delle password e storico. Non c'è limite ai tentativi sul token.- Impatto: una fuga del token ha il raggio d'azione più ampio del sistema, ed è impossibile attribuire un'azione a una persona.
- Mitigazione attuale: confronto a tempo costante, pannello chiuso se il
token è vuoto, ogni azione sensibile in audit,
/adminnon collegato dalla pagina pubblica. Dettagli in sicurezza.md. - Per chiuderlo: account amministrativi individuali (con l'identità scritta in ogni voce di audit) e limitazione dei tentativi sul token.
Codice:
app/api/routes/admin.py:require_admin·app/audit/log.py:write_audit_log -
[LIM-07] Nessuna limitazione di frequenza su scommesse, prelievi, endpoint admin, cambio password e segnalazioni di bug. Solo login e registrazione sono limitati (ADR-41); il canale SSE ha tetti di concorrenza (500 globali, 5 per IP), non di frequenza.
- Impatto: un utente autenticato può martellare scommesse e prelievi (il blocco per-utente li serializza, non li limita); il cambio password permette di provare password attuali senza ritardi a chi possiede già un token valido; le segnalazioni anonime possono riempire il database.
- Stato: chiuso in parte da B-94 (cambio password limitato e registrato, segnalazioni di bug limitate per IP, lunghezza massima di 256 caratteri sui campi delle credenziali). Scommesse, prelievi ed endpoint admin restano senza limite di frequenza.
- Per chiuderlo: un limitatore per utente e per IP sugli endpoint
interessati, sullo stesso modello di
RateLimiter/RollingQuota.
Codice:
app/api/routes/bets.py:create_bet·app/api/routes/withdrawals.py:create_withdrawal·app/api/routes/users.py:change_password·app/api/routes/bug_reports.py:create_bug_report -
[LIM-08] Nessun registro di sicurezza lato utente. Registrazione, login, login falliti e cambio password dell'utente non scrivono voci di audit (le scrive solo il reset da parte dell'admin).
- Impatto: dopo una compromissione non c'è traccia di quando e da dove sia avvenuto l'accesso.
- Stato: chiuso in parte da B-92 (
user_registered, con indice di derivazione e indirizzo) e da B-94 (password_changed). Login riusciti e falliti restano senza voce di audit. - Per chiuderlo: eventi di audit per questi casi (vedi audit-log.md).
Codice:
app/auth/routes.py:login·app/api/routes/users.py:change_password -
[LIM-09] Il JWT sta in
localStoragee la CSP ammette script inline. Una falla XSS permetterebbe di leggere il token.- Mitigazione attuale: CSP
default-src 'self',frame-ancestors 'none', escape dei valori controllati dall'utente nelle pagine; sessioni revocabili (ADR-36). - Per chiuderlo: togliere gestori e stili inline dalle SPA per poter
eliminare
'unsafe-inline', oppure spostare la sessione in un cookieHttpOnly.
Codice:
Caddyfile·app/static/app.js - Mitigazione attuale: CSP
-
[LIM-26] La piattaforma è custodiale: gli utenti devono fidarsi dell'operatore. Tutte le chiavi stanno sul server (ADR-01): l'operatore (o chi compromette il server) può spendere ogni fondo, leggere
server_seedprima della rivelazione e scegliere il vincitore con un minatore ([LIM-25]). Nessuna misura del piano lo cambia.- Impatto: il rischio di perdita totale dei fondi depositati dipende dalla sicurezza del server e dall'onestà dell'operatore.
- Mitigazione dopo il piano: chiave cifrata a riposo con la chiave di cifratura in un file separato (B-91), container non root, verifica della chiave all'avvio (B-89), prova pubblica di ogni estrazione (ADR-24), audit di ogni azione sensibile. Modello di minaccia in sicurezza.md.
- Per chiuderlo: un disegno non custodiale, scartato in ADR-01.
Codice:
app/wallet/hd.py:_load_account_key·app/wallet/keystore.py:decrypt_xprv
Fiducia nella rete
-
[LIM-10]Rimosso: chiuso da B-82 e B-85. I depositi si accreditano adeposit_confirmationsconferme (le coinbase a 120), le riorganizzazioni sono seguite, registrate e, da profondità 2, mettono in pausa; le monete del round si verificano con il quorum prima del pagamento e i partecipanti spariti restano fuori (ADR-52). Resta accettato il 51% ([LIM-24]). -
[LIM-11] I server del quorum li sceglie l'operatore. Il server rifiuta di partire con meno di 2 server di riserva e ogni corroborazione richiede almeno 2 risposte (ADR-07, B-84), ma più server controllati dalla stessa parte contano come voci indipendenti. I certificati TLS non sono verificati contro un'autorità; si possono fissare per endpoint (
host:porta:pin=<sha256>,ELECTRUM_CERT_PIN).- Impatto: chi controlla la maggioranza dei server configurati (o raggiungibili) può scegliere il vincitore o alterare i saldi mostrati.
- Mitigazione attuale: quorum minimo obbligatorio; meno di 2 risposte → la corroborazione fallisce (una rete irraggiungibile non prova nulla); pin facoltativo del certificato. Il vecchio caso «senza riserve tutto passa» e «una sola risposta decide» è chiuso da B-84.
- Per chiuderlo: non si chiude: resta una scelta dell'operatore usare server indipendenti fra loro.
Codice:
app/electrum/listener.py:ElectrumListener._corroborate_majority -
[LIM-12]Rimosso: chiuso da B-83 e B-82. Conferme (prova merkle), reintegri, abbandoni e le monete del montepremi usate per il pagamento sono tutti decisi dal quorum degli altri server, mai dal solo server attivo. -
[LIM-13] L'estrazione attuale è manipolabile da chi produce o trasmette i blocchi.
- Minatore: il seme è il solo hash del blocco, quindi un minatore con biglietti in gioco può trattenere i blocchi finché uno lo fa vincere. Non è un'ipotesi remota: la potenza di calcolo di PLM (~22 TH/s) si può affittare, e scartare qualche blocco costa solo le ricompense perse.
- Server attivo: può scegliere quale blocco reale usare semplicemente non annunciandone uno; la corroborazione verifica che il blocco esista, non che sia il primo dopo la chiusura, e dopo una corroborazione fallita si passa comunque al blocco successivo.
- Verificabilità: l'ordine dei partecipanti è l'orario di invio registrato
dal server, un dato non pubblico; un giocatore non può ricalcolare da solo
l'esito (il commento di
draw_winnerdice il contrario). - Pareggi: due scommesse con lo stesso
broadcast_atnon hanno un criterio secondario di ordinamento, quindi l'estrazione non è riproducibile. - Distorsione del modulo: un seme da 256 bit modulo al più 400 partecipanti introduce una distorsione inferiore a 400/2²⁵⁶, accettata anche dopo il piano.
- Stato: chiuso da B-73.
- Come è chiuso: il commit-reveal di ADR-24 con l'altezza fissa e le conferme di ADR-25: seme che dipende da un segreto impegnato all'apertura, partecipanti ordinati per txid e fissati da un'impronta, prova pubblica. Resta accettata la collusione fra operatore e minatore ([LIM-25]).
Codice:
app/rounds/draw.py:draw_winner·app/rounds/scheduler.py:RoundScheduler._close_and_draw -
[LIM-14] La validazione degli header non ricostruisce la difficoltà reale. Il bersaglio dichiarato non può essere più facile del limite di rete (B-74, ELC-11) e ogni salto di più blocchi è verificato come catena, quindi un header falso a un'altezza enorme non blocca più
tip_height.- Mitigazione attuale: la corroborazione del blocco usato per l'estrazione
(ADR-07, ADR-25); non proteggeva dal blocco di
tip_height, ora chiuso da B-74. - Stato: chiuso da B-74.
- Come è chiuso: bersaglio non più facile di
powLimite catena verificata su ogni salto (ADR-26). Resta accettato dopo il piano: senza il ricalcolo della difficoltà, un header a difficoltà minima (powLimit, in media 2³² hash) costa una frazione di secondo a un miner ASIC e pochi secondi a una GPU, quindi un server ostile può ancora produrre una breve catena falsa concatenata alla nostra. A neutralizzarla sono il quorum sull'header di estrazione (ADR-25), il segreto del commit-reveal (ADR-24) e il rilevamento delle riorganizzazioni (ADR-52); una validazione completa con le regole di ricalcolo della difficoltà di PLM resta fuori scopo.
Codice:
app/rounds/draw.py:header_meets_its_own_target·app/electrum/listener.py:ElectrumListener._apply_header - Mitigazione attuale: la corroborazione del blocco usato per l'estrazione
(ADR-07, ADR-25); non proteggeva dal blocco di
-
[LIM-15] La sottoscrizione di un nuovo indirizzo è a sforzo singolo. Se fallisce subito dopo la registrazione, l'indirizzo resta non osservato fino alla riconnessione successiva o al giro di
DepositReconciler(300s, che attende prima di partire).- Impatto: un deposito fatto subito dopo la registrazione può tardare fino a cinque minuti.
Codice:
app/electrum/listener.py:ElectrumListener.address_for_new_user·app/deposits/reconcile.py:DepositReconciler -
[LIM-24] Un attacco al 51% su PLM resta possibile: è contenuto, non impedito. Chi controlla la maggioranza della potenza di calcolo (che per PLM, ~22 TH/s, si può affittare) può riscrivere più di 6 blocchi e annullare depositi già accreditati o scommesse già confermate. Riguarda chiunque usi PLM, non solo la lotteria.
- Impatto: un deposito accreditato e poi annullato da una riorganizzazione
più profonda di
deposit_confirmationsè denaro che la piattaforma ha già contato; può essere stato scommesso o prelevato. - Mitigazione dopo il piano: 6 conferme sui depositi (ADR-06) rendono l'attacco costoso quanto sei blocchi dell'intera rete; il rilevamento e la pausa sulle riorganizzazioni profonde (ADR-52) lo rendono visibile e fermano nuovi round; la verifica delle monete prima del pagamento fa sì che un round colpito paghi ciò che resta invece di bloccarsi. Il denaro sottratto dall'attaccante è perso per la piattaforma.
- Aperto: nessuna di queste misure lega il costo dell'attacco alla
dimensione del montepremi. Il tetto opzionale
max_round_pool_sats(ADR-21) è disattivato per default (0) e, anche impostato, il suo valore non discende da alcun calcolo del costo di noleggiare potenza sufficiente a riscriveredeposit_confirmationsblocchi: resta a discrezione dell'operatore. Per un montepremi abbastanza grande, quindi, l'attacco può convenire nonostante le mitigazioni sopra. Decisione rimandata: se e come legaremax_round_pool_satsa una stima di quel costo (o attivarlo per default) non è stato ancora deciso. - Per chiuderlo: non è chiudibile dal software della lotteria.
Codice:
app/deposits/service.py:find_new_credit_candidates·app/electrum/listener.py:ElectrumListener._apply_header·app/rounds/scheduler.py:RoundScheduler._trigger_payout - Impatto: un deposito accreditato e poi annullato da una riorganizzazione
più profonda di
-
[LIM-25] Operatore e minatore insieme possono scegliere il vincitore. Con il commit-reveal (ADR-24) l'operatore conosce
server_seede può calcolare l'esito di ogni blocco candidato; un minatore d'accordo con lui può scartare i blocchi sfavorevoli. Lo stesso vale per chi ottiene sia il database sia la chiave di cifratura: il segreto è cifrato a riposo (sicurezza.md SEC-56), quindi il solo database, o un suo backup, non basta.- Impatto: un round può essere vinto da un complice.
- Perché è accettato: l'operatore è già fidato come custode di tutti i fondi ([LIM-26]); chi può leggere il database può già fare di peggio. Il commit-reveal impedisce a chi produce o trasmette i blocchi da solo di scegliere il vincitore, che era il rischio da chiudere.
- Per chiuderlo: un contributo di casualità che l'operatore non conosce (segreti dei giocatori, beacon esterno), scartato in ADR-24.
Codice:
app/rounds/draw.py:draw_winner·app/rounds/service.py:open_new_round_if_needed -
[LIM-27] Le soglie di conferma differiscono da quelle del portafoglio di riferimento.
PalladiumWalletconsidera spendibile un'uscita normale dopoMinConfirmations = 6conferme e una coinbase dopo 121 (maturità 120 più un blocco di margine). La piattaforma adotta 6 solo per i depositi (ADR-06) e 120 per le coinbase; un prelievo o una vincita, confermati qui a 1 conferma, compaiono nel portafoglio di riferimento dell'utente come non ancora spendibili per altri 5 blocchi.- Impatto: un utente che preleva verso
PalladiumWalletvede i fondi arrivati ma bloccati per altri 5 blocchi (10 minuti in media) rispetto a quanto dice la piattaforma; nessun rischio per i fondi. - Per chiuderlo: non serve: è una politica del portafoglio del destinatario, non una regola di consenso. Le guide (guida-utente.md) possono dirlo.
Codice:
app/tx/confirmation.py:poll_once·app/deposits/service.py:find_new_credit_candidates - Impatto: un utente che preleva verso
Configurazione ed economia
-
[LIM-16]Rimosso: chiuso da B-95. Costo della scommessa,fee_addresse tetto al montepremi sono fotografati sulla riga del round all'apertura, come durata e pausa (ADR-10); il fee rate resta letto dal vivo per scelta e il prelievo minimo segue il costo corrente della configurazione (ADR-20). -
[LIM-17] Nessun consolidamento automatico del montepremi. Monete avanzate e resti si accumulano sugli indirizzi del montepremi (fino a B-80 su uno solo, per tutti i round); il margine fra 400 partecipanti e 500 ingressi (ADR-21) si consumava nel tempo.
- Impatto: raggiunto il limite, il pagamento fallisce con
too_many_inputse il round resta inpaying_out, con unpayout_failedogni 60s. - Stato: la parte del margine che si consumava è chiusa da B-80: con un indirizzo per round (ADR-03) il pagamento spende solo le monete del proprio round, e il margine non si consuma più (resta lo stato descritto sopra per i round aperti prima di B-80, che condividono l'indirizzo di riserva).
- Resta accettato: le riserve per l'RBF (ADR-17) e le monete estranee inviate agli indirizzi di round chiusi si accumulano senza consolidamento automatico; recuperarle è un'operazione manuale (operativita.md).
Codice:
app/rounds/scheduler.py:RoundScheduler._trigger_payout·app/wallet/psbt_builder.py:build_payout_transaction - Impatto: raggiunto il limite, il pagamento fallisce con
Prodotto e interfacce
-
[LIM-18] Il sistema presuppone un solo processo. Canale SSE, blocchi per-utente, limitatori di tentativi, cache dei QR e della chiave dell'account sono in memoria.
- Impatto: con più worker, due costruzioni dello stesso utente potrebbero scegliere le stesse monete, i limiti per IP si dividerebbero per worker e gli eventi SSE arriverebbero solo ai client dello stesso worker.
- Per chiuderlo: canale condiviso (Redis pub/sub) e lock su database o Redis. L'invariante del round attivo è già un indice e non rientra qui. Il piano del 2026-09-28 non lo chiude: un solo processo e un solo file SQLite restano la scelta di ADR-13, adeguata alla scala prevista; il piano rende solo più affidabile quel processo (B-88, B-93).
Codice:
app/tx/locks.py:UserLocks·app/rounds/events.py:RoundEventBroadcaster·app/auth/rate_limit.py:AuthRateLimiters -
[LIM-19] Nessuna cronologia per l'utente. L'utente non vede lo storico dei round, delle scommesse, dei depositi o dei prelievi: un prelievo fallito lascia una riga
failedche l'utente non può mai vedere. Esistono soloGET /users/me/last-round-result(l'ultimo round giocato) eGET /bug-reports/mine. L'operatore ha invece/admin/rounds,/admin/pending-transactions,/admin/audit-log.- Per chiuderlo: endpoint e sezione di cronologia personale.
Codice:
app/api/routes/users.py:last_round_result·app/withdrawals/service.py:request_withdrawal -
[LIM-20]
/guidaè un segnaposto. Il collegamento funziona ma la pagina dice che la guida arriverà. (/report-buginvece è completa e tradotta.)Codice:
app/main.py:user_guide·app/static/guida.html -
[LIM-21] La parità delle chiavi di traduzione non è verificata da un test. Oggi le 7 lingue hanno le stesse 151 chiavi, ma nulla lo impone: una chiave mancante ricade sull'inglese e, se manca anche lì, viene mostrata la chiave grezza.
- Stato: da chiudere con il test di parità di ARC-63 (nessun B-nn: non è un difetto del codice).
- Per chiuderlo: un test che confronti gli insiemi di chiavi di
TRANSLATIONS.
Codice:
app/static/i18n.js:t -
[LIM-22]Rimosso: chiuso da B-94. Gli endpoint/admin/*, il503del canale SSE e gli errori del framework (401,404,405,422) rispondono con il formato strutturato{code, message, params}(API-16, ADR-47). -
[LIM-23]Rimosso: chiuso da B-94.GET /admin/usersè paginato (API-33).