mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-10-06 04:38:22 +00:00
Routstr-to-Routstr auto top-up had no spend bound. Admin settings were accepted without range or type validation, and every low-balance cycle independently minted a Cashu token and handed it to the configured peer. A malicious, buggy, or persistently non-crediting peer therefore received a fresh bearer token every sixty seconds; nothing in the worker noticed that the previous one had never been credited, and nothing survived a restart, so the bleed was limited only by the owner's mint balance. Auto top-up now mirrors the PPQ claim machinery that already guards the Lightning path. Each provider gets one durable claim row keyed by its id, so a second worker (or the same worker after a restart) loses the insert or the ownership-fenced update instead of paying twice. The claim moves to "sent" before the network call, and only a peer balance that reaches the pre-topup balance plus the top-up amount clears it: an uncredited token holds the slot rather than being retried. Repeated non-credit walks the claim through exponential backoff to a halt that needs an admin release, and a rolling 24h cap bounds the total even when every attempt looks successful. Settings validation now rejects non-positive, non-finite, boolean, huge, and non-integer amounts, amounts outside the per-transaction range, and a missing mint URL, at the admin API as well as in the worker. The claim row is a CashuTransaction like the PPQ one, so no migration is needed; provider delete and type change refuse to orphan it.