Breeze Core v3.0.2
Breeze Core 3.0.2 — a reliability release, from the postmortem of a real lockout: several users lost access for days and nothing in the log said why.
Fixed
- Authentication failures are now logged. There was previously no auth logging at all — only uvicorn's bare
401 Unauthorizedaccess lines. Every failure now records a reason code, the client IP and an 8-character key-id hint (never a secret), and enrolments/revocations are logged too, so "it logged me out yesterday" is answerable:journalctl -u breeze-core | grep "auth failed" - 401s now say why, so clients can tell transient from fatal. A phone whose clock had drifted past the ±60 s signature window produced a 401 indistinguishable from a revoked credential — so the app concluded its credential was dead and deleted its Ed25519 private key, which with LAN-only enrolment strands anyone away from home. Failures now carry a stable
errorcode and aretryableflag:clock_skew,replay,incomplete_signatureare retryable;unknown_key,expired,bad_signature,no_credential,bad_api_keyare definitive. Aclock_skewrejection also returnsserver_time, so a client can measure its offset and re-sign instead of re-pairing.unknown_keyandexpiredare now distinguished. - The shipped fail2ban configs banned legitimate users. The filter counted
400|401|403|404|405|422|429at 5 hits per 10 minutes, escalating to a five-week ban — but404is a client feature-detecting endpoints,422is input validation, and429is our own rate limiter. The tripwire banned for a week on a single 403. And since clients behind NAT share one address, a ban took everyone on that connection offline at once. Now:401/403only, 20 per 10 min, 1 h capped at a day, tripwire needs 3 hits, andignoreipdocuments that your WAN address belongs there. See HARDENING §3 — including a new §3.1 on reading the auth log.
Added
AC_AUTH_SKEW_SECONDS(default 60) to widen the accepted clock drift for devices with sloppy clocks.
Upgrading is safe from 3.0.1 (the packaging scriptlet fix in that version means dnf/apt upgrade no longer stops the service). 28/28 tests pass.
RISC-V (added after the initial release)
riscv64 now ships as a musl build — breeze-core_3.0.2_riscv64.apk and the matching tarball, also in the Alpine repo on bolero.
It is the first architecture that compiles rather than unpacks: PyPI has no riscv64 wheels, so every dependency is built from source under QEMU emulation — pydantic-core's Rust and PyInstaller's own bootloader included. That build takes hours, needs Alpine edge (rustc >= 1.88, which no stable Alpine ships yet), and is why riscv64 will land last on future releases and may lag the current version.
There is no OpenWrt riscv64 .ipk: that bundle is built on a newer Alpine than OpenWrt 23.05's musl 1.2.4 floor permits. There is no glibc riscv64 build either — see the note on bolero for why.
IT TOOK TWO FUCKING HOURS TO MAKE THAT RISCV BUILD