# 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] ### 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 `