Files
punktfunk/docs/releases/v0.22.3.md
T
enricobuehlerandClaude Fable 5 5790a3e334
ci / web (push) Successful in 2m25s
ci / rust-arm64 (push) Successful in 2m53s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 11s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 13s
ci / docs-site (push) Successful in 1m6s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 24s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 33s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 13s
docker / builders-arm64cross (push) Successful in 9s
docker / deploy-docs (push) Successful in 33s
ci / rust (push) Successful in 7m2s
docs(release): v0.22.3 notes — the Updates card and one-click updating join the installer fixes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 17:23:54 +02:00

12 KiB
Raw Blame History

Wire-compatible with 0.21.x and 0.22.x — nothing about streaming changed, and everything already paired keeps working. This release repairs the Windows installer and gives every host something new: the web console now tells you when a newer Punktfunk is out, and can install it for you where the platform allows. The apps on your phone, tablet, Mac and TV are unchanged.

If you stream to a Windows PC, update that PC. The 0.22.1 and 0.22.2 installers were built without the web console in them at all — not broken, absent. If the tray menu on your PC says "Open web console (not responding)" and the page never loads no matter what you try, that is this, and reinstalling those versions could never have fixed it.

New

  • The console tells you when a newer host is out. The Host page has an Updates card: the version you're running, the channel you follow (stable or canary), and — once something newer exists — release notes and the exact way to update your kind of install. The check is a small signed file the host verifies against keys built into it, so nothing between you and the project can feed it a fake update, and a feed that ever tried to roll you backwards is refused outright. It contacts only the Punktfunk forge, and PUNKTFUNK_UPDATE_CHECK=0 turns it off entirely. Scripts can react too: the host emits update.available and, after a successful update, update.applied on its event stream.

  • On Windows, updating the host is now one click. The card grows an Update now button: it asks for your console password again (a remembered login alone can't restart your PC's host), then downloads the installer, checks it against the signed release manifest and its code signature, and runs it silently — the service restarts and the page reconnects by itself. If someone is streaming you're warned first, because updating drops the stream. Every attempt leaves its outcome in the card even across the restart, with the installer's log path when something went wrong — and if a freshly installed version ever crash-loops, the host puts the previous installer back on its own and says so. PUNKTFUNK_UPDATE_APPLY=0 in host.env removes the button on hosts that should never have it.

  • Linux hosts can opt in to the same button. apt, Fedora, Bazzite (sysext and rpm-ostree) installs get one-click updating through a deliberately tiny root helper the packages now ship. It's off until you decide otherwise — enabling it is one command, sudo usermod -aG punktfunk-update $USER, and that group membership is the entire grant: the button can only ever run your package manager's normal update for the Punktfunk packages, from the same signed repositories you already use, and it never picks versions or URLs. rpm-ostree updates are staged and the card asks you to reboot (it never reboots for you). On Arch the button additionally requires opting into a full pacman -Syu in /etc/punktfunk/update.conf, because a partial upgrade is how Arch boxes break — we won't run one. Steam Deck on-device installs get the button with no opt-in at all: it runs the same rebuild update.sh always did, just from the couch. The full story is on the new Updating the Host docs page.

Fixed

  • The web console is in the installer again. On 0.22.1 and 0.22.2 the Windows installer shipped with the console missing entirely: the files it runs from were never included, so the PC had nothing to start and nothing to open. The host itself was fine the whole time — streaming, pairing and controllers all worked — but the settings page you reach in a browser simply was not there. The tray reported it as "not responding", which was true and also the only clue you got, and because every reinstall produced the same installer, uninstalling and reinstalling made no difference. Updating to 0.22.3 restores it; you don't need to touch your settings, your password, or your paired devices.

  • Updating no longer stops on a "DeleteFile failed; code 5" error. Partway through an update, the installer could stop on a dialog complaining that it could not replace bun\bun.exe, offering only Try again, Skip, or Cancel — and Try again usually failed the same way. Windows refuses to replace a program while it is running, and the pieces of Punktfunk that were still running weren't the ones the installer knew how to stop. It now shuts all of them down, waits for them to actually exit rather than assuming, and if something still holds the file it finishes the install and puts the new copy in place on your next restart instead of leaving you stuck at a dialog.

  • Updating no longer switches your plugins off. If you had enabled the script and plugin runner, every update quietly disabled it again, so plugins stopped running until you noticed and re-enabled them by hand. Updates now leave it exactly as you had it — on if it was on, and still off by default for everyone who has never turned it on.

Improved

  • You can save or share the host's log from the console. The Logs page has two new buttons: one downloads what you're looking at as a timestamped .log file, the other hands it to your phone or tablet's share sheet, or copies it to the clipboard on a desktop. Handy when someone asks you for a log — the file carries full dates and times, so it still makes sense once it leaves your browser. Whatever level filter and search you have applied is what you get, and it saves everything that matches rather than just the part on screen.

  • Televisions that struggle with the startup speed test can be told to ease off. Two seconds into a session Punktfunk briefly bursts traffic to measure how much room your network really has. On some TVs that burst is enough to disturb the very link it is measuring — one LG set showed no video for fourteen seconds when it went badly. The burst's size can now be capped, so a device that already limits its own speed test can keep ours in line with it. Nothing changes unless a device asks for it.

Under the hood (for developers)

  • The console's absence was one CI variable in the wrong place. windows-host.yml exported WEB_OUTPUT_DIR on the last line of "Build + smoke-boot web console (bun)", and be2fabcf had just put that step behind if: steps.webconsole.outputs.cache-hit != 'true'. So the first build after the cache was populated — and every build after it with web/** and sdk/** unchanged — skipped the step, left the variable unset, and pack-host-installer.ps1 reads an unset WEB_OUTPUT_DIR as "omit the console", announcing it in a single Write-Host before packing happily. Confirmed from the job logs rather than inferred: on both the v0.22.1 (run 14235) and v0.22.2 (run 14272) tag builds, step 12 is skipped and the job is green. BUN_EXE and SCRIPTING_BUNDLE are exported from unconditional steps, which is why those installers still carried bun and the plugin runner but no {app}\web.
  • Downstream, web setup bailed at web launcher missing: {app}\web\web-run.cmd before registering anything, so there was no PunktfunkWeb task, no listener on 47992, and no firewall rule — and Inno ignores [Run] exit codes, so the failure left no trace in the install at all. WEB_OUTPUT_DIR now comes from its own unconditional step that throws when web\.output\server\index.mjs is absent, and a new pre-pack step asserts all five payloads (console, bun, plugin runner, FFmpeg DLLs, VB-CABLE) so a missing input fails the build rather than silently redefining the installer. The shape is borrowed from the packer's existing VB-CABLE check. FFmpeg was the most dangerous of the silent ones: an amf-qsv host link-imports avcodec, so an installer without those DLLs ships a host that cannot start at all.
  • The same cache-hit build is why bun.exe locked. It ships under WithWeb or WithScripting, but the installer's pre-copy stop was #ifdef WithWeb — so a console-less installer shipped bun while the only code that stopped bun was compiled out. StopBunRuntimes replaces StopWebConsole behind the same WithWeb || WithScripting gate the payload uses, and covers what the old routine structurally could not: neither bun runs under the host service (both are Task Scheduler tasks — PunktfunkWeb as SYSTEM, PunktfunkScripting as LocalService), and the runner listens on no port, so a task-name-plus-port sweep could never see it. It now disables both tasks before stopping them — they carry restart-on-failure at 10× and 999× a minute, and the web task also has a logon trigger, so a force-kill alone invited a respawn into the middle of a copy that takes over a minute at lzma2/max — kills any bun whose image lives under the install dir (by path, so an unrelated bun survives), and polls until they are gone, since Stop-ScheduledTask returns on request and Stop-Process is TerminateProcess. bun.exe also gained restartreplace, so a survivor defers to reboot instead of dead-ending the install.
  • Disabling a task is not free: unlike a stopped one it does not return at the next boot, so an aborted install would have taken the console down permanently. Two restores cover it — a last-in-[Run] entry for the normal flow and DeinitializeSetup, which Inno calls even on user cancel — both re-enabling only what was enabled before the copy. That is also the plugin-runner fix: the scripting [Run] entry re-registers its task and then unconditionally disables it, correct on a first install and wrong on every upgrade since.
  • PUNKTFUNK_ABR_PROBE_KBPS sets the startup capacity probe's burst target for embedders. Unset, zero or unparseable keeps the 2 Gbps default, so existing sessions are unchanged; PUNKTFUNK_ABR_PROBE=0 remains a poor substitute because it pins the climb ceiling at the negotiated ~20 Mbps.
  • The console's log export serializes the filters' full result rather than the rendered tail — the 1000-row cap is a DOM budget and has no business truncating a file destined for a bug report — and stamps each line with a local ISO 8601 timestamp plus numeric offset. Web Share level 2 is probed at runtime after mount (SSR has no navigator, and guessing there would mismatch on hydration), falling back to the clipboard, and the button is omitted only where neither exists.
  • The update check's truth is a per-channel Ed25519-signed manifest (…/generic/punktfunk-update/{stable,canary}/manifest.json + .sig), verified against keys pinned in the host binary via the plugin-index machinery, with a persisted monotonic serial as the anti-rollback floor and the channel name bound into the signed document. Stable manifests publish from announce.yml — the existing manual fleet-green gate doubles as the gate for the fleet learning about a release; canary rides windows-host.yml. TLS and the registry are transport, never trust.
  • /api/v1/update/* is admin-lane only: whole-prefix denied to the plugin token and absent from the paired-cert allowlist. Apply requests carry no version, URL, or channel — the privileged side derives everything from its own verified state — and the console's BFF re-verifies the console password per apply (sharing the login throttle) while every mutating route now requires a same-origin Sec-Fetch-Site. Outcomes survive the host's own restart via an intent record reconciled at boot.
  • The Linux packages grow four pieces: the dep-free root helper /usr/libexec/punktfunk/pf-update, the fixed-ExecStart oneshot punktfunk-update.service, a polkit rule granting exactly that unit's start verb to the punktfunk-update group, and the group itself — created empty by every postinst, populated by no one.
  • No wire, ABI or driver-protocol changes: wire protocol 2, C ABI 13, Windows virtual-gamepad channel 3, virtual-display driver protocol 6 — identical to 0.22.0, 0.22.1 and 0.22.2.