Files
archy/core
ssmithxandClaude Sonnet 5 4e410d7c98 fix(ecash): guard Minibits claim polls against races and stop replayed claims retrying forever
The UI polls wallet.ecash-lnaddress-claim every 8s, but a single poll (auth +
/claim + relay fetch + redeem loop) can outlast that interval. Two overlapping
claim_and_redeem runs then loaded the same last_dm_seen_at, fetched/redeemed
the same claims, and last-writer-wins on save — rewinding the watermark and/or
double-redeeming. A double-redeemed or state-loss-replayed claim then failed
forever as "already spent" with no way to leave pending_claims, leaving a
permanent orange retry banner.

- STATE_LOCK (backend) + an in-flight guard (UI) serialize claim polls and
  the lnaddress registration/token-refresh path, so two callers can't race on
  minibits.json.
- pending_claims now tracks per-claim attempts (PendingClaim, migrating
  transparently from the old plain-string shape); a claim that fails
  MAX_CLAIM_ATTEMPTS times is dropped instead of retried forever.
- A redeem failure recognized as mint error 11001 (already redeemed) is
  treated as terminal and dropped immediately — the value was already swept,
  so retrying it is pointless. ClaimOutcome gains dropped_count so the two
  drop reasons (harmless vs. real loss) are visible to the caller.
- save_state now writes via temp-file + rename instead of truncating
  minibits.json in place — the exact disk-full failure mode that corrupted
  this file on archy-x250-pa3, 2026-09-08, could otherwise destroy
  pending_claims tokens that /claim had already consumed server-side
  (unrecoverable, unlike relay DMs).
- minibits_error no longer panics on a multi-byte UTF-8 boundary when
  truncating a server error body (was byte-slicing, not char-safe).
- register_profile's name-collision check now matches the structured
  error.name == ALREADY_EXISTS instead of a raw "already" substring, so an
  unrelated error message doesn't burn a retry attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZnFgeUBKY5UAfyJFsYccS
2026-09-09 03:50:34 +00:00
..