• 26.13-alpha 8c1fd1da2b

    26.13-alpha
    All checks were successful
    Build ISO / build-iso (push) Successful in 17m28s
    CI / lint (push) Successful in 27s
    CI / test (push) Successful in 59s
    CI / validate-json (push) Successful in 23s
    CI / markdown-links (push) Successful in 15s
    Release / release (push) Successful in 11m38s
    Pre-release

    daniel released this 2026-04-21 17:03:28 +02:00 | 7 commits to main since this release

    Fixed

    • Upgrade path from pre-auth releases actually works. 26.11-alpha
      introduced from werkzeug.security import ... in furtka/auth.py,
      but werkzeug isn't installed on the target system — core runs as
      system Python with stdlib only, and flask>=3.0 in pyproject.toml
      is never pip-installed on the box. Fresh boxes from the 26.11/26.12
      ISO without a manually-installed werkzeug crashed on import; boxes
      upgrading from pre-26.11 got double-broken by that plus the health
      check below. Replaced the werkzeug dependency with a stdlib-only
      furtka/passwd.py that uses hashlib.pbkdf2_hmac for new hashes
      and parses werkzeug's scrypt:N:r:p$salt$hex format for backward
      compatibility — existing users.json files created on the rare
      boxes that did have werkzeug keep working after this upgrade, no
      re-setup needed. from werkzeug.security import ... is gone from
      the import chain entirely; pyproject.toml's flask dep stays only
      for the live-ISO webinstaller.
    • Self-update no longer auto-rolls-back when crossing the auth
      boundary.
      updater._health_check pinged /api/apps and demanded
      a 200, which meant every 26.10 → 26.11+ upgrade hit the post-restart
      check, got a 401 (auth guard), and treated that as "server dead"
      → rollback. Now any 2xx–4xx response counts as "server alive"; only
      connection-level failures or 5xx fail the check. 5xx still fails
      rollback because that means the new process is up but broken.
    • Install lock closes its race window. POST /api/apps/install
      used to release the fcntl lock immediately after the sync
      pre-validation so the systemd-run child could re-acquire it —
      leaving a tiny gap where a second POST could slip in, pass the lock
      check, and return 202. Both child processes would start, one would
      win the in-child lock, the other would die silently. Now the API
      also reads install-state.json and refuses with 409 if the stage
      is non-terminal (pulling_image, creating_volumes,
      starting_container). The fcntl lock stays as belt-and-suspenders.
    Downloads