Close the smaller state inconsistencies (B-96, BET-02, BET-07, WDR-01, WDR-15, TX-16, TX-18, TX-27, TX-29, DEP-15, DEP-16, AUD-30, AUD-46, DAT-22)

- bet/withdrawal routes read listener.client after taking the user lock
- a reduced full-balance withdrawal is checked against the minimum again
- a bet covered only by pending balance answers balance_pending_confirmation
- a recovered bet/withdrawal/payout writes bet_placed/withdrawal_sent/payout_sent
- an abandoned payout clears winner/fee/reserve amounts with payout_txid
- the reconciler pings SSE only for rows it changed
- closing_stalled every 30 minutes past the deadline; closing_waiting_since on /rounds/current
- one refresh per user at a time; a failed refresh no longer ends the Electrum session

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-18 01:08:14 +02:00
1 parent 24e5fc3d8b
commit 9520c80dcf
23 files changed
+445 -151

No files matched your search

+4 -17
View File
@@ -44,9 +44,6 @@ ogni tipo di evento. Le colonne della tabella `audit_log` sono descritte in
`app/tx/broadcast.py:RbfBumper._tick`, `app/main.py:lifespan`,
`app/rounds/scheduler.py:RoundScheduler._tick`,
`app/electrum/listener.py:ElectrumListener._record_reorg`
*Stato:* da implementare (B-96), per uno degli eventi
nuovi · *Oggi:* gli eventi osservativi sono i primi quattro,
`chain_reorg_detected` e `rbf_bump_failed`.
- **[AUD-04]** Il `payload` è un dizionario serializzato in JSON nella colonna
`payload_json`. `created_at` è impostato dall'applicazione, non dal
@@ -114,10 +111,7 @@ ogni tipo di evento. Le colonne della tabella `audit_log` sono descritte in
`app/tx/broadcast.py:RbfBumper._tick`,
`app/rounds/scheduler.py:RoundScheduler._tick`,
`app/rounds/scheduler.py:RoundScheduler._close_and_draw` ·
*Test:* `tests/unit/test_scheduler.py` (solo `payout_failed`)
*Stato:* da implementare (B-96), per l'ultima lettura ·
*Oggi:* le letture sono quelle di `payout_failed`, di
`draw_baseline_tip_unknown` e di `rbf_bump_failed`.
*Test:* `tests/unit/test_scheduler.py`, `tests/unit/test_state_consistency.py`
## Catalogo degli eventi
@@ -275,7 +269,6 @@ flowchart LR
sbagliata, nuova troppo corta) non scrive nulla. Nessuna logica rilegge la
riga.
*Codice:* `app/api/routes/users.py:change_password` · *Test:* —
alcun evento.
- **[AUD-43]** `restore_gap_detected` — il controllo all'avvio ha trovato
cronologia sulla catena per almeno uno dei 20 indici di derivazione
@@ -386,9 +379,7 @@ flowchart LR
correnti, secondi trascorsi dalla scadenza. `user_id` no, `round_id` sì.
Transazione propria ([AUD-03]). La riga più recente del round è l'orologio
della ripetizione successiva, 1800 s dopo ([AUD-09]).
*Codice:* `app/rounds/scheduler.py:RoundScheduler._tick` · *Test:* —
*Stato:* da implementare (B-96) · *Oggi:* l'attesa in `closing` non scrive
alcun evento.
*Codice:* `app/rounds/scheduler.py:RoundScheduler._tick` · *Test:* `tests/unit/test_state_consistency.py`
- **[AUD-37]** `draw_committed` — il round è entrato in `drawing`: elenco dei
partecipanti e altezza del blocco di estrazione sono fissati
@@ -536,9 +527,7 @@ flowchart LR
([AUD-21]) o `payout_sent` ([AUD-29]) — con lo stesso payload
([TX-16](transazioni-e-riconciliazione.md#riconciliazione)).
*Codice:* `app/tx/reconcile.py:_promote` ·
*Test:* nessun test verifica la riga di audit.
*Stato:* da implementare (B-96), per il secondo evento · *Oggi:* si scrive
solo `pending_tx_recovered`.
*Test:* `tests/unit/test_state_consistency.py`
- **[AUD-31]** `pending_tx_abandoned` — una transazione `building` o `pending`
è stata dichiarata persa **con una prova**
@@ -626,9 +615,7 @@ flowchart LR
`app/rounds/scheduler.py:RoundScheduler._tick`,
`app/rounds/confirmation.py:_on_payout_confirmed`,
`app/tx/confirmation.py:poll_once`, `app/tx/broadcast.py:bump_fee`
*Stato:* da implementare (B-92), per user_registered
dall'elenco · *Oggi:* la registrazione e il cambio password riuscito non
producono alcuna riga.
*Stato:* da implementare (B-92), per `user_registered`
## Log applicativo