# Changelog All notable changes to Furtka will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, release 0, alpha stage). ## [Unreleased] ## [26.12-alpha] - 2026-04-21 ### Changed - **App-Install geht async mit Live-Progress.** `POST /api/apps/install` returnt jetzt `202 Accepted` nach der synchronen Pre-Validation (Source auflösen, Files kopieren, `.env` schreiben, Placeholder- und Path-Checks). Den eigentlichen Docker-Teil (`compose pull` → volumes → `compose up`) dispatched der Handler als `systemd-run --unit=furtka-install-` Hintergrund-Job, der seine Phase in `/var/lib/furtka/install-state.json` schreibt. Neues `GET /api/apps/install/status` für UI-Polling. Das Install-Modal zeigt jetzt live "Image wird heruntergeladen…" → "Speicherbereiche werden erstellt…" → "Container wird gestartet…" statt ~30 Sekunden totem "Installing…". Muster 1:1 parallel zu `/api/catalog/sync/apply` und `/api/furtka/update/apply`. Neue CLI- Subcommand `furtka app install-bg ` (intern, von der API aufgerufen); `furtka app install` für Terminal-User bleibt synchron. Die Reinstall-Taste in der App-Liste pollt ebenfalls den Install-Status und spiegelt die Phase im Button-Text. ## [26.11-alpha] - 2026-04-21 ### Added - **Login-auth for the Furtka web UI.** Every `/apps`, `/api/*`, `/`, and `/settings/` route now requires a signed-in session. New `/login` page serves a username/password form; `POST /login` validates against `/var/lib/furtka/users.json` (werkzeug PBKDF2- hashed), sets a `furtka_session` cookie (`HttpOnly`, `SameSite= Strict`, 7-day TTL), and redirects to `/apps`. `POST /logout` revokes the server-side session and clears the cookie. Unauthenticated HTML requests get a 302 to `/login`; unauthenticated API requests get 401 JSON. The old "No authentication on this UI yet" banner is gone; the `/apps` header picks up a `Logout` link instead. - **First-run setup fallback for upgrade-path boxes.** Boxes upgrading from 26.10-alpha have no `users.json` yet — on the first visit `/login` renders a setup form (username + password + password-confirm) that creates the admin record on submit. Fresh installs skip this: the webinstaller writes `users.json` during the chroot post-install step using the step-1 password, so the first browser visit after boot goes straight to the login form. - **Caddy proxy routes `/login` and `/logout`.** `assets/Caddyfile` gets two new `handle` blocks in the shared `(furtka_routes)` snippet so both the `:80` block and the `hostname.local, hostname` HTTPS block forward the auth endpoints to the stdlib server on `127.0.0.1:7000`. Without this Caddy would serve a 404 from the static file server. ### Fixed - `tests/test_installer.py` ruff-format nit — the 26.10-alpha release commit had a misformatted list literal that failed `ruff format --check`. Caught when the Release page on Forgejo showed a red CI badge for the tag. - `pyproject.toml` version string bumped from the stale 26.8-alpha to 26.11-alpha. Release pipeline uses `GITHUB_REF_NAME` as source of truth for the artefact name, but having the two agree matters for local dev runs that read `pyproject.toml`. ## [26.10-alpha] - 2026-04-21 ### Added - **Remove-USB-stick hint on the installer's post-install screen.** `webinstaller/templates/install/rebooting.html` now shows a bold "Remove the USB stick now" line before the reboot, plus a muted fallback explaining the BIOS boot-menu keys (F11/F12/Esc) if the machine boots back into the installer anyway. Caught on the first bare-metal test (Medion i5-4gen, 2026-04-21) where the box didn't boot the installed system without manual BIOS-order changes. - **New `path` setting type for app manifests.** Apps can now declare a setting with `"type": "path"` whose value is an absolute filesystem path on the host; docker-compose bind-mounts it via the usual `.env` substitution (`${MEDIA_PATH}:/media`). Unlocks media/data-heavy apps (Jellyfin, later Paperless/Nextcloud/Immich) where the user points at an existing folder instead of copying everything into a Docker volume. The install form renders path settings as a plain text input with a `/mnt/…` placeholder hint. - **Server-side path validation.** Both `install_from()` and `update_env()` refuse values that aren't absolute, don't exist, aren't directories, or resolve (after `Path.resolve()`) into a system-path deny-list (`/`, `/etc`, `/root`, `/boot`, `/proc`, `/sys`, `/dev`, `/bin`, `/sbin`, `/usr/bin`, `/usr/sbin`, `/var/lib/furtka`). Catches `/mnt/../etc`-style traversal too. Error messages surface in the existing install/edit modal error line. ## [26.9-alpha] - 2026-04-21 ### Fixed - Landing-page app tiles with an `open_url` now open in a new tab (`target="_blank" rel="noopener"`), matching the Open button behaviour on `/apps`. Without this, clicking "Uptime Kuma" on the home screen replaced Furtka itself with the Kuma admin page. Internal links (the `Manage →` fallback for apps without an `open_url`) still open in the same tab. - `scripts/publish-release.sh` no longer fails the whole release when the ISO upload hits a Forgejo proxy 504. The core tarball + sha256 + release.json (which running boxes need for self-update) are uploaded first and the ISO is attempted last as a best-effort; a 504 now logs a warning and exits 0 so the release page still publishes. Surfaced by the 26.8-alpha cut: the tarball landed but the ~1 GB ISO upload timed out at the Forgejo reverse proxy. ### Changed - `furtka app list --json` now mirrors `/api/apps` field-for-field — previously the CLI emitted a slim projection missing `description_long`, `open_url`, and `settings`. Anyone piping the CLI output into jq for automation was seeing an incomplete view. ## [26.8-alpha] - 2026-04-20 ### Added - **Live-installer ISO attached to the Forgejo release page.** `.forgejo/workflows/release.yml` moves to the self-hosted runner, builds both the self-update tarball and the ISO, and `scripts/publish-release.sh` uploads the ISO as a fourth release asset (`furtka-.iso`) alongside the existing tarball + sha256 + release.json. Fresh-install users can now grab the ISO from the release page instead of hunting through `build-iso.yml` artifact retention windows. ISO build step is `continue-on-error` so an ISO flake doesn't hold back the core tarball that running boxes need for self-update. - **Reboot + Shut down buttons on `/settings`.** Replaces the two "Coming next" placeholders with real actions backed by `POST /api/furtka/power` (`{"action": "reboot" | "poweroff"}`). Handler kicks a delayed `systemd-run --on-active=3s systemctl {reboot|poweroff}` so the HTTP response reaches the browser before the kernel loses network. Each button opens a native confirm dialog first (reboot: "back in ~30 s", shut down: "need to press the physical power button"), then the UI swaps to a status line and — after a reboot — polls `/furtka.json` until the box is back, reloading the page automatically. No auth (same posture as install/remove). - **Manifest `open_url` field + Open button in `/apps` and on the landing page.** Apps declare a URL template (e.g. `smb://{host}/files` for fileshare, `http://{host}:3001/` for Uptime Kuma); the UI substitutes `{host}` with the current browser's hostname at render time so the link follows however the user reached Furtka (furtka.local, raw IP, a future reverse-proxy hostname). The landing page's hardcoded `if app.name === 'fileshare'` special-case is gone — any app with an `open_url` in its manifest now gets a proper "Open" link. The core seed `apps/fileshare/manifest.json` bumps to v0.1.2 to carry it. ### Changed - `.btn` CSS class introduced so an `` rendered-as-button lines up with its `