767e67ca's per-channel mechanics were correct; they were aimed at the wrong binary. Each one is
restored here pointed at punktfunk-encode-worker, and every host-side removal from #136 stays
verbatim. All grants remain best-effort — an uncapped worker still encodes, at default priority, so
a failed setcap must never fail an install.
* Arch: setcap in post_install AND post_upgrade (a replaced binary is a new inode).
* RPM: %caps(cap_sys_nice=ep) in %files, never a %post setcap — %caps applies, restores and
verifies, and covers Fedora as well as Bazzite via rpm-ostree layering.
* Bazzite + Arch sysext: setcap on the staging tree before mksquashfs, which does record
security.capability. The assertion is amended, not removed: host EMPTY is still a hard fail, and
the worker must carry exactly cap_sys_nice=ep — missing is fine, anything else is not.
* deb: setcap in postinst.
* NixOS: security.wrappers for the WORKER plus PUNKTFUNK_ENCODE_WORKER in the unit. A file
capability cannot live on a store path, and an ambient grant is right here precisely because
nothing ever identifies the worker. The host's ExecStart stays on the store path.
* Steam Deck: setcap the worker; the .desktop the script writes stays valid this time.
Four things the plan's channel table missed:
* packaging/arch/build-sysext.sh had no capability handling at all, and a sysext can never run a
pacman scriptlet — the SteamOS image would have shipped the lever permanently inert.
* scripts/steamdeck/update.sh had none either. It rebuilds both binaries, so a new inode drops the
grant, and it is the documented steady-state path: the lever would have died on the first update.
It also never healed a Deck already capped by 0.26.0-1.
* A capped worker is AT_SECURE, and glibc drops $ORIGIN-expanded RPATH entries for secure binaries
unless they normalise into a trusted system dir. Copying the host's rpath under BUNDLE_FFMPEG=1
would have left the capped worker unable to find libavcodec on exactly the channel that bundles
it. Absolute DT_RPATH instead.
* Nix crane scopes by -p, so the worker would not have been built at all, and it needs its own
addDriverRunpath.
scripts/ci/assert-cap-matrix.sh mechanizes the lesson from 0.26.0-1 — verify the PACKAGE, never the
board. It unpacks the built Arch package, the deb, the rpm and the mounted sysext raw and asserts one
matrix: the host carries NOTHING (hard fail), the worker exactly cap_sys_nice=ep. The sysext reader
first proves it can round-trip a capability through mksquashfs/unsquashfs at all, so an unreadable
artifact fails rather than issuing a blind PASS, and --self-test red-teams the assertions themselves.
Red-teaming the leg found a real bug: setcap originally ran BEFORE the assertion, so "the worker
arrived carrying something unexpected" was unreachable and a stray %caps would have been silently
overwritten. Both sysext scripts now assert, then grant, then assert again.