1@README.md 2 3- **Never print, log or format the key.** To check that it arrived, print its 4 length. `Jev` holds it and only ever puts it in an `Authorization` header. 5- This crate is host-only, by design and by documentation, not by accident. A 6 wasm target must not depend on it; add the relay client beside it instead. 7- **`tokio::time::sleep` is in here, so nothing behind a hot-patch point may 8 call into this crate.** A subsecond patch gets its own copy of the process's 9 thread-locals, so patched code that touches a tokio runtime context finds 10 none (jevsnes `apps/native/CLAUDE.md`). Network I/O stays on the worker 11 thread; the decision logic that IS patchable touches none of it. 12- The retry policy is `jev-client`'s, over `jev-protocol::retry`. This crate 13 supplies only the ports (`HttpsTransport`, `TokioRuntime`); never add a 14 retry loop here, which would be a second policy beside that one. 15- **Never add a way to build a `Jev` without a `Ledger`.** `new`/`from_env` 16 are the only constructors and both require one, on purpose - see the 17 crate's own doc comment. A convenience constructor that skips it would be 18 a client that can spend without anything checking the rate guards or 19 seeing the vendor's out-of-credit answer. 20- **There is no lifetime cap, and none should be reintroduced.** Removed 21 2026-09-22 (the user's own ruling on an earlier, self-imposed `$4.00`/ 22 `$4.50`: "not this random $4 number"). The only hard stop on 23 total spend is the vendor's own out-of-credit response 24 (`Refusal::OutOfCredit`); the per-minute and per-hour guards stay, but they 25 are RATE limits, not a budget - see the README's "There is no lifetime cap". 26- **`Ledger::window` re-reads and re-sums the whole file on every call, on 27 purpose.** A cached running total is a second piece of state that has to 28 agree with the log, and a cache that drifts toward "we have spent less 29 than we have" is exactly the failure this exists to prevent - see 30 `ledger.rs`'s own doc comment. Do not add a cache to make this faster 31 without re-reading that reasoning first. 32- **The ledger's own tests use `Ledger::at`, not `Ledger::open`.** `open` 33 reads `$XDG_STATE_HOME`, which every test in the process shares - a test 34 that used it would pollute the real ledger (and, worse, could seed the 35 opening estimate, `OPENING_ESTIMATE_USD`) the first time it ran on a 36 developer's machine. 37- **`ApiErrorKind::OutOfCredit`'s classification is a guess, not a 38 documented fact**, and this crate's out-of-credit flag rests on it. The 39 rule for correcting it is in `../jev-protocol/CLAUDE.md`. 40- **A hold is released only when nothing can have been billed** (`ask`'s 41 `nothing_billed`). After an interrupted or timed-out attempt the cost is 42 unknown, and the hold goes on counting its worst case. 43- **No guard may write a flag a human has to clear, except out-of-credit.** 44 The question bucket and the hour breaker are computed from the ledger's 45 own lines and heal as the window slides (see README, "Why the rate guards 46 heal themselves"). Do not reintroduce a pause file for them; a legacy 47 `paused.json` is not read by anything. `out-of-credit.json` is the one 48 flag, because waiting does not change it. 49- **Admission is check-and-hold under one `flock`** (`Ledger::admit`). A 50 check that reads the ledger and a write that happens later, outside the 51 lock, is the race that let two processes both see "29" and both ask. 52- **Guard logic takes `now` as an argument** (`Window::verdict`, 53 `Ledger::admit`, `Ledger::status`); the tests use a fake clock by passing 54 one. Keep `ledger::now()` calls at the edges (`Jev::ask`, `Jev::status`).