New crates/punktfunk-tray — a small per-user companion showing the host service
state at a glance (running / stopped / starting / degraded / failed + the live
session in the tooltip) with one-click actions: open web console, approve a
pending pairing request, start/stop/restart, open logs. No more digging through
logs to learn whether the service came back after a reboot or an update.
Status is service-manager-FIRST (SCM / systemd user unit — a port squatter can
never fake Running), then the new loopback-only unauthenticated
GET /api/v1/local/summary (counts/booleans only; the mgmt token and cert.pem
are SYSTEM/Admins-DACL'd on Windows, so a non-elevated tray cannot bearer-auth).
Windows: windows_subsystem binary (a console exe in the Run key would flash a
terminal at sign-in), Shell_NotifyIcon + hidden window, per-session single
instance, TaskbarCreated re-add, --quit for the uninstaller; service actions
elevate per click via ShellExecuteW "runas" onto the new
`punktfunk-host service restart` (stop → wait Stopped → start).
Linux: ksni/StatusNotifierItem over zbus, systemctl --user actions (no polkit),
/etc/xdg/autostart entry whose --autostart self-gates to actual host users.
Icons: scripts/gen-tray-icons.py (pure stdlib) renders the brand lens + status
dot into committed .ico/hicolor assets; deb/rpm/arch ship binary+autostart+icons.
Live-validated: Linux on the headless KDE session (SNI registration, state
transitions, menu-driven start, dbusmenu layout); Windows on the RTX box
(session-1 launch with no NIM_ADD failure, single instance, --quit, restart
round-trip, summary loopback-200/LAN-401).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Modern branded wizard: WizardStyle=modern dynamic windows11 (Inno >= 6.6,
plain-modern fallback for older compilers; CI provisioning upgrades a
pre-6.6 Inno). Brand-mark wizard side panels + header tiles (100-200% DPI)
and a multi-size punktfunk.ico (SetupIconFile + Apps & Features), generated
AND committed by branding/gen-branding.ps1 from the canonical brand geometry.
Gotcha encoded in the script: ISCC rejects all-PNG icons, so entries <= 64px
are classic DIBs (PNG only at 128/256), and the ICO is load-verified.
- VB-CABLE actually ships now: windows-host.yml never set VBCABLE_DIR, so every
published installer silently omitted the virtual mic (broken mic passthrough
in the field). CI provisions the pinned, SHA-256-verified official Pack45
(provision-windows-punktfunk-extras.ps1) and the pack now FAILS on a
supplied-but-invalid dir instead of shipping mic-less again. Attribution per
VB-Audio's bundling grant surfaced in the visible wizard task text (vendor,
vb-cable.com, donationware) on top of the licenses notice.
- GameStream (Moonlight) compat is a wizard task (checked by default) ->
service install --gamestream=on|off writes PUNKTFUNK_HOST_CMD=
serve[ --gamestream] into host.env. Only the two canonical values are ever
rewritten - a hand-customized command line survives upgrades. Silent
installs: /MERGETASKS="!gamestream".
- Driver uninstall (field report: our virtual-device drivers survived
uninstall): new `driver uninstall [--gamepad]` removes the pf-vdisplay
device node(s) + the pf-vdisplay/pf-dualsense/pf-xusb driver-store packages,
wired into [UninstallRun] after service uninstall. Locale-safe by
construction: devices matched on unlocalized VALUES (never pnputil's
localized labels), packages found by INF content scan - validated against a
German-locale box ("Instanz-ID:" parse; 7/7 punktfunk INFs matched, no
foreign hits). VB-CABLE is deliberately left installed (shared third-party
component with its own uninstaller).
Installer compile, cargo check/clippy/fmt, and the ASCII locale gate are green;
the wizard look + uninstall flow still need one on-glass pass on a disposable
box (this box runs the live host).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>