Releases ·

Roastwarden 0.10.0

Safe to share, first steps (phase 1). A fresh install no longer runs open: with no key set it makes its own owner key at first start, keeps it beside the database and logs it once, and wrong keys or tokens are rate limited. Writes that read first wait for the database instead of failing under load, the supplier pages in the tests are synthetic, and the deploy guide now says what secrets a backup holds. The owner's install, which sets its key, works as before.

Security

  • Secure by default (ROADMAP Next 58, Security): a server on a network address with no RUSTROAST_API_KEY no longer runs open. It makes a 48-digit owner key at its first start, keeps it in owner.key beside the database (mode 600) and logs it once; the dashboard's key prompt says where to find it. RUSTROAST_AUTH=off keeps it open on purpose; a loopback address with no key stays open (the local dev stack). An owner key shorter than 16 characters stops the start. An install with a key set (production) is unchanged.
  • Wrong credentials are rate limited: ten refused keys or tokens from one client within a minute get 429 TOO_MANY_FAILURES (with Retry-After) for any credential until the minute ends; reads with no credential carry on. roast exits 5 with a hint to wait.

Changed

  • Supplier test pages are synthetic (Next 61): the saved supplier answers the import's tests read keep each site's shape and the product facts, with invented text in place of the suppliers' own copy.

Fixed

  • DEPLOY.md said backups hold no secret: they hold API token hashes, the Web Push key and the notification tokens; it says so now.
  • Writes that read first wait for the database instead of failing: saving a label design's new version, a print run's state or a printer took a read snapshot first and could fail with "database is locked" when telemetry wrote in between; they now take the write lock at the start (db::begin_write), as a new roast does since 0.9.0. Foreign keys are set on every database connection by the connect options (they already were, by sqlx's default).