/api/login locked every client for 30 s after five failures from anyone.
Anyone who could reach the login page could keep the owner locked out by
failing on purpose. If no login succeeded after a lockout, the lock also
returned from 2^31 to 2^32 ms (about 24.9 to 49.7 days) later, because the
deadline was never cleared and was compared as a signed difference.
Count failures per remote address instead. Five failures lock that address
for 30 s, as before. A shared budget caps failures from all addresses
together, so changing address does not add guesses: it holds six failures
and refills one every 6 s, the old global rate, so one failing address can
never empty it on its own. While it is empty every client waits, as before.
Lock times are measured as elapsed time.
The policy is a pure header, WebConfigLoginThrottle.h.
test_webconfig_login_throttle.py runs it directly (isolation, boundaries,
one-hour rate bounds, millis() half-wrap, saturation, eviction) and runs the
real handleLogin with ArduinoJson under ASan/UBSan. Putting every client on
one key, as the old code did, fails the handler test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adapt the optional onboard-radio probe for RAK3401 and RAK4631 cores using the external RAK13302 image. Preserve SPI1 radio ownership, external FEM startup, and ordinary RAK4631 primary-radio operation.
Probe before boot voltage protection, bound missing-chip waits, release temporary pads, and confirm cold sleep without waking the chip. Add sanitizer-backed host regression tests and CI coverage.
Keep rejected power-saving requests from changing radio2's saved RX policy or timings. Exercise actual CLI, scan restoration and calibration sleep guards with semantic negative controls.
Require a real raw-table save for same-value channel SETs. This repairs the false acknowledgement after successful constructor recovery of an older backup followed by a failed candidate write.
Keep resolved alias keys, raw AUTO policy and runtime generation untouched. Preserve GET and unchanged contact behavior, changed-policy validation and indeterminate-publication quarantine.
Cover real stale-backup creation, failure/retry, reboot and exact old-skip controls. Add actual alias/BaseChatMesh and raw app-key regression tests on all four backends. Verified 117 related host tests, 16 final caller rechecks, four firmware qualifications and linked nRF52 crypto checks.
Latch only channel storage on Indeterminate writer outcomes, including failed transaction setup. Preserve ordinary failure retries, confirmed rollback, contacts and the live accepted channel keys.
Exercise actual CLI and binary callers with all four storage backends, reboot behavior and exact missing-latch negative controls. Share TX storage failure diagnostics to retain the strict Wio-E5 Mini flash gate.
Verified 103 related host tests, four platform firmware qualifications and linked nRF52 crypto/stack checks. A separate stale-backup constructor/no-op acknowledgement case remains under audit.