fix(claude): persist usage cooldowns across invocations
Claude's Retry-After cooldown was process-local, so rerunning tokscale usage immediately sent another request after HTTP 429. Persist bounded cooldown records in Tokscale's cache and consult them before the next Claude usage request.
Records contain only a version and timestamps, with filenames keyed by an access-token hash. Config roots and credentials have separate cooldowns. Updates use a bounded file lock and atomic replacement; the longest valid disk/in-memory deadline wins, while an unwritable cache retains protection in the current process. Expired, malformed, oversized-duration, and clock-skewed records fail open. Claude Code's credentials remain read-only.
Closes #1207.
Validation:
- CLI unit suite: 1,307 passed, 1 ignored.
cargo clippy --locked -p tokscale-cli --all-features -- -D warningsandcargo fmt --all -- --checkpassed.- Regressions cover actual child-process visibility, HTTP suppression, concurrent writers, clock rollback, malformed record replacement, longer disk deadlines, credential/config isolation, and in-memory fallback when persistence fails.
Persistence is best-effort when the cache is inaccessible or its lock remains busy. Rotating the access token starts a new cooldown scope; the integration does not expose a stable account ID to bind across token rotation. HTTP tests use a local fixture server.
Summary by cubic
Persists Claude Retry-After cooldowns across invocations so rerunning tokscale usage after a 429 respects the cooldown instead of making another request.
Implementation notes
- Stores bounded cooldown records in the cache, keyed by access-token hash.
- Keeps the longer of disk and in-memory deadlines; invalid records fail open.
- Re-validates records with lock-time clock samples so delayed older writers can't replace newer cooldowns.
- Uses bounded file locking and atomic replacement; interrupted staging files are reclaimed only under the account's own lock.
- Preserves in-process protection when the cache is unwritable.
- Scopes cooldowns per config root and token; rotating tokens starts a fresh scope.
- Claude Code credentials remain read-only.