ci / bun-nix (pull_request) Successful in 17s
ci / web (pull_request) Successful in 1m7s
apple / swift (pull_request) Successful in 1m38s
ci / rust-arm64 (pull_request) Successful in 1m38s
apple / screenshots (pull_request) Skipped
ci / docs-site (pull_request) Successful in 1m46s
android / android (pull_request) Successful in 5m31s
ci / rust (pull_request) Failing after 9m2s
nix / flake (pull_request) Successful in 12m24s
The Arch fix in the previous commit was incomplete. 0.26.0-1 granted the host CAP_SYS_NICE through
every Linux channel we ship, and each one breaks KWin identification the same way:
* packaging/rpm/punktfunk.spec .......... %caps(cap_sys_nice=ep) in %files <- Fedora AND Bazzite
via rpm-ostree layering
* packaging/bazzite/build-sysext.sh ..... setcap on the staging tree, recorded by mksquashfs
* packaging/debian/build-deb.sh ......... setcap in the postinst
* packaging/nix/nixos-module.nix ........ security.wrappers with capabilities = "cap_sys_nice=ep"
* scripts/steamdeck/install.sh .......... setcap on $BIN, six lines after writing the .desktop
whose Exec= it thereby voids
Bazzite was NOT a separate fault, as first reported here — it is this one. Verified by mounting the
published punktfunk-0.26.0-1-x86-64.raw: `getcap usr/bin/punktfunk-host` reports cap_sys_nice=ep,
stored as security.capability in the squashfs. The claim in packaging/arch/build-sysext.sh that
"file capabilities don't survive this squashfs path" is false and is corrected here; mksquashfs
records them, which is exactly why the image shipped one.
NixOS deserves its own note: a security.wrappers entry does not dodge the problem. The wrapper
raises the capability into its AMBIENT set before exec'ing the store binary, precisely so it
survives — which lands CAP_SYS_NICE in the exec'd process's permitted set and fails the readlink
identically to a file capability. ExecStart now points at the store path directly, which is also the
path packages.nix substitutes into the .desktop's Exec=, so the two finally agree.
Measured blast radius of holding a capability, same-uid reader, CachyOS kernel 7.1.6:
/proc/PID/exe ....... EPERM <- KWin's identification. Desktop sessions die.
/proc/PID/root/* .... EPERM <- xdg-desktop-portal reads .flatpak-info here to resolve an
app id; the wlroots and Hyprland backends go through it
/proc/PID/environ ... EPERM
/proc/PID/cgroup .... OK
/proc/PID/status .... OK
/proc/PID/cmdline ... OK
Compositor backends, by exposure: KWin is broken outright (proven, field-confirmed). gamescope has
no identity gate and was never affected, which matches the field — only Desktop mode was reported.
Mutter drives Mutter's own D-Bus API, not the portal, and looks unaffected. wlroots and Hyprland go
through the ScreenCast portal, whose app-id resolution reads a path the capability blocks — a real
exposure, not something I reproduced end to end.
The sysext build now HARD-FAILS if a capability is staged, rather than trusting that the RPM payload
never carries one: a merged sysext's /usr is read-only squashfs, so a bad image cannot be repaired
on the box, and the spec was one %caps() away from baking one in again.
Docs corrected, because they advertised the capability as a feature:
* docs-site running-as-a-service "GPU scheduling priority" — rewritten: the host carries no
capability, why it must not, and how to clear a 0.26.0-1 install (Bazzite needs a new image)
* docs-site configuration.md — the PYROWAVE_QUEUE_PRIORITY row no longer claims the packages grant it
* packaging/bazzite/README.md — §6.5 still described the kde-desktop-setup.sh behaviour from
before it stopped writing KWIN_WAYLAND_NO_PERMISSION_CHECKS and started REMOVING it; plus a
note that 0.26.0-1 Desktop mode cannot be repaired in place
* packaging/arch/README.md — the false "capabilities don't survive the sysext" line
* CHANGELOG v0.26.0 PW1 — annotated with the 0.26.0-2 correction rather than rewritten, and the
owed PyroWave-under-load A/B now says it needs a gamescope-only box
Verified: bash -n on all five changed shell files; nix-instantiate --parse on nixos-module.nix and
packages.nix; the published 0.26.0-1 sysext mounted and its capability read; getcap on an uncapped
file exits 0 with empty output, so the new build assertion cannot false-positive.