Commit Graph

944 Commits

Author SHA1 Message Date
enricobuehler 980939ed6b refactor(gamestream): extract + unit-test gamestream_admission (Stage 4)
Pull the GameStream mode-conflict decision out of h_launch into a pure
gamestream_admission(live, req_fp, policy) -> GsDecision so the 503/join/take-over
logic is unit-tested (no live session / same-client → Serve; different client →
Reject/Join/Serve per policy; anonymous requester treated as different) — the
GameStream path can't be driven without a Moonlight client, so this covers the logic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 10:43:08 +00:00
enricobuehler cfad0cf7ee feat(vdisplay): finish Stage 4 — typed reject, Windows join-default, GameStream 503
Completes the mode-conflict admission surface deferred from the initial Stage 4:

- REJECT now delivers the reason to the client: punktfunk/1 closes the QUIC
  connection with a distinct BUSY code (0x42) + the 'host busy: streaming WxH@Hz to
  <client>' string, which the client reads from ApplicationClosed (validated on
  loopback: the probe logs 'closed by peer: host busy … (code 66)').
- Windows default: separate (incl. the unconfigured default) resolves to JOIN — the
  Windows native host admits a second client at the live mode instead of the old
  silent last-wins reconfigure of the shared monitor (release-note behavior fix; the
  reconfigure is now opt-in as steal). separate stays multi-view on Linux.
- GameStream 503: h_launch tracks the session owner fp (LaunchSession.owner_fp, kept
  [u8;32] for Copy) and applies the policy when a DIFFERENT paired client launches —
  reject → 503 (Moonlight 'host busy'), join → serve the live mode, steal/separate →
  take over. Same-client re-launch is never a conflict.

Native reject-reason loopback-validated; Windows join-default pending .173 rebuild;
GameStream 503 pending a Moonlight client (can't drive /launch autonomously).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 10:34:49 +00:00
enricobuehler 42b1158ea7 feat(vdisplay): mode-conflict admission — separate/join/steal/reject (Stage 4)
The mode_conflict policy is now enforced at ADMISSION, before the punktfunk/1
Welcome, when a DIFFERENT client connects while another client's session is live:
- separate (default, unconfigured → no change): each client its own display.
- join: admit at the live display's mode (honest-downgrade — the Welcome carries it).
- steal: signal the victim session(s)' stop flags, wait the release grace, serve.
- reject: refuse the handshake with a busy reason (live mode + client label).

New vdisplay/admission.rs: the pure decide() (unit-tested — same-client never
conflicts, anonymous clients each distinct, join targets the oldest session) + a
live-session registry (identity + mode + stop flag) sessions register in once up.
Wired into punktfunk1 serve_session: admit() before validate_dimensions, register
after the data plane binds. A same-client reconnect never conflicts.

Validated on loopback (two probes, distinct identities, differing modes) across all
four policies: separate→own mode, join→live mode, steal→victim interrupted,
reject→handshake refused.

Remaining Stage-4 surface (deferred): GameStream 503 path, Windows-specific
defaults (separate→join map, silent-reconfigure→steal), reject reason delivered to
the client as a typed message (currently host-side log + connection close).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 10:21:28 +00:00
enricobuehler 029d1134a9 harden(vdisplay/windows): verify+retry exclusive isolation; pack primary layout
Exclusive (topology=exclusive) was fire-and-forget — a field-reported bug had a
physical monitor STAY ACTIVE. isolate_displays_ccd now re-queries after each apply
and RETRIES (up to 4x) until count_other_active()==0, never trusting rc alone;
logs SOLE-active on success, an error if a display survives all attempts. Secure
desktop correctness depends on the lock screen not landing on a stray panel.

Primary: drop the temporary per-path diagnostic; pack the kept displays left-to-
right from the virtual's right edge instead of blindly shifting each by virt_width
(which left a dead gap when extend already placed them right).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 09:55:13 +00:00
enricobuehler e35b6991e2 fix(vdisplay/windows): topology=primary force-extends to reactivate the physical
Root cause: on a headless box the IDD auto-activates as the SOLE display, so
QueryDisplayConfig sees only the virtual — the physical is already deactivated
before set_virtual_primary_ccd runs (no physical to keep). Force EXTEND first to
reactivate every connected display alongside the virtual, then reposition to make
the virtual primary, keeping the physical active.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 09:41:20 +00:00
enricobuehler 913f6ce659 diag(vdisplay/windows): log active paths in set_virtual_primary_ccd
Temporary diagnostic — the physical monitor goes black in topology=primary
despite rc=0; the SSH/session-0 view can't see the real interactive-session
topology, so log the active paths the host actually operates on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 09:36:53 +00:00
enricobuehler d23bd9b0cf fix(vdisplay/windows): DISPLAYCONFIG_PATH_SOURCE_INFO union field access
modeInfoIdx lives in the Anonymous union (windows-rs), not directly on
sourceInfo — set_virtual_primary_ccd now reads .Anonymous.modeInfoIdx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 09:27:07 +00:00
enricobuehler eda7cac78e feat(vdisplay/windows): topology=primary — keep physicals active, virtual primary
Implements the deferred Windows primary-only CCD (Stage 2). set_virtual_primary_ccd
repositions the virtual output's source to (0,0) = primary and shifts the physical
display(s) to its right, ALL kept active — one atomic CCD SetDisplayConfig (not GDI
CDS_SET_PRIMARY, which storms MODE_CHANGE_IN_PROGRESS with another display live).
The manager's should_isolate() becomes topology_action() (3-way): extend (skip),
primary (set_virtual_primary_ccd), exclusive (isolate_displays_ccd). Restore-on-teardown
covers both. Validates the user's two scenarios on a physical-monitor .173.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 09:17:41 +00:00
enricobuehler d73951414c feat(vdisplay): KWin per-slot output naming for persistent scaling (Stage 3)
The KWin backend names its output Virtual-punktfunk-<id> from the client's
stable identity slot, so KWin persists per-output config (scale/mode) by name in
kwinoutputconfig.json and reapplies that client's scaling on reconnect — the KDE
scaling ask. Also fixes the latent clash where two concurrent sessions both used
Virtual-punktfunk (topology name-matching now uses the per-slot name).

- identity::global() + resolve_slot(fp, mode, default) — the shared persisted map
  (Windows manager dropped its own field; both use the global — never same-process).
  Default identity is per-platform: PerClient on Windows, Shared on Linux, so
  unconfigured hosts keep today's behavior (Linux = single 'punktfunk' name).
- KwinDisplay carries the client fp (set_client_identity), computes the per-slot
  name, threads it through the stream_virtual_output name + the topology helpers
  (set_custom_refresh / apply_virtual_primary[_only] / other_enabled_outputs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 08:54:39 +00:00
enricobuehler b150d79626 feat(vdisplay): platform-neutral identity map + per-client-mode (Stage 3)
Generalize the Windows-only per-client stable-id map into vdisplay/identity.rs:
- DisplayIdentityMap keyed on a composable string (identity_key: fingerprint,
  or fingerprint+resolution under per-client-mode); LRU at 15, persisted to
  display-identity.json (migrated from the legacy pf-vdisplay-identity.json).
- Windows manager wired to it, picking the key from the identity policy.
- Foundation for KWin per-slot output naming (persistent KDE scaling) — the
  KWin wiring is the next Stage-3 step (needs a KWin box).
- Unit-tested (stable, per-client-mode split, LRU, key composition).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 08:40:18 +00:00
enricobuehler cb7ddc0411 feat(vdisplay): topology decoupling — distinct primary level (Stage 2)
The three topology levels become distinct behaviors (Stage 0 only did
extend-vs-exclusive, faking primary):
- vdisplay::effective_topology() -> the concrete level (console policy > legacy
  *_VIRTUAL_PRIMARY env > Auto default). Backends read it directly at create
  time; apply_session_env no longer writes the boolean env (one fewer connect-
  path env mutation).
- Mutter: extend (no config), primary (virtual primary + physicals kept as
  secondaries — build_primary_keeping_physicals), exclusive (sole, physicals
  disabled). KWin: extend (no-op), primary (kscreen primary only), exclusive
  (primary + disable others).
- Windows should_isolate treats primary as isolate (the primary-only CCD variant
  is a follow-up); wlroots exclusive + the physical-keep effect need a
  display-attached box (headless lab boxes can't observe primary vs exclusive).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 00:18:46 +00:00
enricobuehler 60816709c4 fix(vdisplay): call life.acquire() outside debug_assert (release no-op)
The pooled entry's lifecycle transition was inside debug_assert_eq!, whose
arguments don't evaluate in release builds — so acquire() never ran, the entry
stayed Idle, and release saw Noop → immediate teardown (no keep-alive). Caught
on-glass on the CachyOS box.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 23:45:36 +00:00
enricobuehler 783c52dfad feat(vdisplay): Linux keep-alive pool — registry-owned display lifecycle (Stage 1b)
The ownership split (design/display-management.md §3): the registry owns the
per-session virtual-display lifecycle on Linux, so a display can outlive its
session (keep-alive) and be reused on reconnect.

- registry.rs: a Linux pool driven by the pure lifecycle machine. acquire()
  reuses a kept (lingering/pinned) display of the same backend+mode, else
  creates one and keeps the backend's keepalive so the compositor output (and
  its PipeWire node_id) survives the session. The session's capturer holds a
  gen-stamped DisplayLease instead of the real keepalive; its drop drives
  linger/teardown. Enabling fact: KWin/Mutter/gamescope put their node on the
  DEFAULT PipeWire daemon (remote_fd=None) — reconnect re-attaches by node_id,
  no fd re-open. wlroots (remote_fd=Some, xdpw portal) passes through unchanged
  (teardown-on-drop) pending the fresh-portal-capture re-attach.
- Default (unconfigured) linger = Immediate → today's teardown-on-disconnect,
  so no behavior change without a keep-alive policy; concurrent sessions still
  each create their own output (reuse only matches LINGERING entries).
- Wired build_pipeline (punktfunk1) + gamestream through registry::acquire;
  capture_virtual_output signature unchanged. Windows delegates to vd.create
  (the manager already leases) — unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 23:37:21 +00:00
enricobuehler 2dd17dda80 test(mgmt): display state/release endpoint smoke test
Covers the idle path (empty /display/state + released:0 /display/release) on a
unit-test host, exercising the wiring + auth without touching any global owner.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 21:27:52 +00:00
enricobuehler 87f0ce7997 feat(vdisplay): lifecycle state machine + display state/release API (Stage 1)
Stage 1 of design/display-management.md — the lifecycle core + the display
management surface:

- vdisplay/lifecycle.rs: pure per-slot state machine (Idle/Active{refs}/
  Lingering{until}/Pinned) with acquire/release/expiry/force-release
  transitions. No I/O, no OS types — the platform-neutral distillation of the
  Windows manager's model. Unit + a 200k-iteration seeded property walk
  (no leaks / double-frees / refcount underflow across arbitrary interleavings).
- vdisplay/registry.rs: neutral snapshot/release facade over the per-OS
  lifecycle owners. Windows reads/controls the VirtualDisplayManager; Linux
  keep-alive (a per-session pool) lands in a following increment (needs GPU-box
  validation).
- windows/manager.rs: additive snapshot() + force_release() (no behavior change
  to the on-glass-validated path).
- mgmt: GET /api/v1/display/state (live/kept displays) + POST /api/v1/display/release
  (tear down lingering/pinned now; refuses active). OpenAPI regenerated.
- web console: Virtual displays card gains a live-display list (polled) with
  per-row + release-all buttons and a linger countdown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 20:32:03 +00:00
enricobuehler bbd98241e4 feat(vdisplay): display-management policy surface (Stage 0)
A user-configurable policy layer above the per-compositor VirtualDisplay
backends: keep-alive, topology, conflict, identity, layout, max-displays —
persisted to display-settings.json, editable from the web console, applied
per connect. Design: design/display-management.md.

Stage 0 stands up the surface and wires the two behaviors the existing code
can already express — the Windows monitor linger duration and the
"make the streamed output the sole desktop" topology — through it; every
other option is stored + echoed but not yet enforced (later stages). An
unconfigured host (no display-settings.json) keeps today's exact behavior.

- vdisplay/policy.rs: pure DisplayPolicy + 5 presets + JSON store (gpu-settings
  pattern) + EffectivePolicy; 9 unit tests.
- vdisplay.rs: resolve_topology(Auto); apply_session_env drives *_VIRTUAL_PRIMARY
  from the policy only when a settings file exists.
- windows/manager.rs: linger_ms() + should_isolate() read the policy when configured.
- mgmt: GET/PUT /api/v1/display/settings (bearer-only); PUT rejects keep_alive
  forever until the lifecycle stage. OpenAPI regenerated.
- web console: Host → Virtual displays card (preset picker + custom fields); en+de.
- docs-site: virtual-displays.md + configuration.md cross-links.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 19:44:18 +00:00
enricobuehler 202f40fd4e chore(release): bump workspace version to 0.7.4
apple / swift (push) Successful in 1m7s
audit / cargo-audit (push) Successful in 1m33s
ci / web (push) Successful in 46s
ci / docs-site (push) Successful in 58s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 51s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 55s
ci / rust (push) Successful in 7m8s
android-screenshots / screenshots (push) Successful in 46s
ci / bench (push) Successful in 4m49s
android / android (push) Successful in 3m20s
release / apple (push) Successful in 9m30s
windows-host / package (push) Successful in 7m13s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m24s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m13s
arch / build-publish (push) Successful in 8m8s
apple / screenshots (push) Successful in 5m47s
deb / build-publish (push) Successful in 2m56s
decky / build-publish (push) Successful in 14s
flatpak / build-publish (push) Successful in 4m53s
linux-client-screenshots / screenshots (push) Successful in 1m40s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 9m51s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m36s
docker / deploy-docs (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
web-screenshots / screenshots (push) Successful in 2m40s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v0.7.4
2026-07-04 17:46:34 +00:00
enricobuehler 8f90563ffd docs: dedicated Arch Linux host+client guide
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
apple / swift (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
Every other distro has a full Host Setup page; Arch only had table rows. Add
docs/arch.md (signed pacman binary repo: key import + repo + install, GPU
prereqs, service/linger, web console, client, PKGBUILD appendix), slot it into
the nav after fedora-kde, and point the install/client tables at it. Update the
client-install rows from 'from the PKGBUILD' to the binary repo now that it exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 17:37:01 +00:00
enricobuehler 2e6b822fd6 docs(ci/arch): correct the header's pacman setup (key import, not TrustAll) + note the trust root
android / android (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 17:19:28 +00:00
enricobuehler f7c5314b5e fix(packaging/arch): correct pacman setup — import the registry key, cache cargo git
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 3m18s
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
The Gitea Arch registry signs its DB + packages, so 'SigLevel = Optional TrustAll' fails
non-interactively (pacman still needs the key to verify). Document the one-time
pacman-key import instead; install is then signature-validated under pacman's default
SigLevel (verified end-to-end: clean archlinux container -> repo sync -> install,
'Validated By: Signature').

Also cache /usr/local/cargo/git in arch.yml: the workspace pulls clients/windows'
git-pinned windows-reactor/windows deps to resolve, cloning windows-rs (huge) every run
otherwise — same registry+git cache deb.yml uses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 17:16:24 +00:00
enricobuehler d6669fc3fb fix(ci/arch): create CARGO_HOME before chown — actions/cache doesn't on a miss
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
apple / swift (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
arch / build-publish (push) Successful in 7m31s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 17:03:46 +00:00
enricobuehler e292084225 fix(ci/arch): install nodejs before actions/checkout — act_runner doesn't inject node
apple / screenshots (push) Has been cancelled
apple / swift (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
android / android (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
arch / build-publish (push) Failing after 43s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 17:02:17 +00:00
enricobuehler c758b0393a docs: sysext + pacman repo are the Bazzite/Arch install paths
apple / swift (push) Successful in 1m8s
ci / rust (push) Successful in 1m37s
ci / web (push) Successful in 53s
android / android (push) Successful in 3m37s
ci / docs-site (push) Successful in 58s
apple / screenshots (push) Successful in 5m23s
ci / bench (push) Successful in 4m52s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
deb / build-publish (push) Successful in 4m36s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 52s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 9m57s
docker / deploy-docs (push) Successful in 20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m40s
arch / build-publish (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:39:01 +00:00
enricobuehler d6a659a1ee feat(packaging/arch): distribute binary packages via the Gitea Arch registry
New arch.yml builds the split PKGBUILD (host/client/web, PF_WITH_WEB=1) in an
archlinux:base-devel container on every push and publishes to the pacman repos
'punktfunk' (tags) / 'punktfunk-canary' (main, X.Y.Z-0.<run#> — pkgrel allows
only digits+dots, so the run number carries the ordering). Consumers add one
pacman.conf section; no more build-it-yourself as the only Arch path.

PKGBUILD: pkgver/pkgrel env-driven (PF_PKGVER/PF_PKGREL), source=() when
PF_SRCDIR is set (a canary version has no tag to clone), stale NVENC-only
header fixed, and options=('!lto' '!debug') — makepkg's lto option injects
-flto=auto into CFLAGS, aws-lc-sys compiles its C with it, and rust's lld
cannot read GCC LTO bitcode: 'undefined symbol: aws_lc_*' at link (reproduced
minimally on Arch + rust 1.90). Full build + clean-container install
smoke-tested locally (binaries run, payload + scriptlets intact).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:39:01 +00:00
enricobuehler 2190dad2ad feat(packaging/bazzite): systemd-sysext replaces rpm-ostree layering as the primary install path
Layering is a last resort per the Bazzite docs (slows every OS update, can
block upgrades until removed); a sysext never enters an rpm-ostree
transaction, survives OS updates, and installs/updates with no reboot —
the mechanism Fedora Atomic ships via fedora-sysexts.

- build-sysext.sh wraps the built host+web RPMs into punktfunk-<V-R>-x86-64.raw:
  /etc payload relocated to /usr/share/punktfunk/etc (a sysext carries only
  /usr), the punktfunk-sysext helper embedded, ID=fedora + VERSION_ID pinned
  (merges on Bazzite via ID_LIKE; REFUSED after a major rebase instead of
  running soname-broken binaries — both behaviors validated live on Bazzite 43).
  SELinux labels are baked in as squashfs pseudo-xattrs from matchpathcon:
  unlabeled files run fine for user units but system daemons are DENIED
  (udev couldn't read the gamepad rule under enforcing) — validated on-glass.
  Refuses duplicate input package names (a stale noarch punktfunk-web next to
  the x86_64 one built a chimera image with the dead node launcher once).
- punktfunk-sysext.sh: install/update/status/remove against per-Fedora-major
  feeds (…/generic/punktfunk-sysext/f43[-canary]), SHA-256-verified, applies
  the udev/sysctl scriptlet work + /etc copies, prints the layering-migration
  hint. Live-validated on the .41 Bazzite box incl. service restart + web console.
- publish-sysext-feed.sh + rpm.yml: build + publish the image per matrix leg
  (fedver 43/44), canary feeds pruned to 6, stable release assets attached.
- update-punktfunk.sh warns when the sysext shadows a layered install.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:39:01 +00:00
enricobuehler 5b5ec15ead fix(client-linux): GL presenter — eglCreateImageKHR takes EGLint attribs, not EGLAttrib
apple / swift (push) Successful in 1m12s
apple / screenshots (push) Successful in 5m47s
android / android (push) Successful in 3m18s
ci / rust (push) Successful in 1m35s
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m35s
ci / bench (push) Successful in 4m57s
decky / build-publish (push) Successful in 15s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
deb / build-publish (push) Successful in 4m37s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
flatpak / build-publish (push) Successful in 4m18s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m57s
docker / deploy-docs (push) Successful in 6s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m14s
The KHR variant reads 32-bit attrib pairs; the pointer-sized array fed it
garbage and every plane import came back rejected (observed on-Deck; the
new fallback ladder caught it and demoted to software exactly as designed).
Also print the real EGL error enum instead of its discriminant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:32:06 +00:00
enricobuehler c9ff144492 Merge branch 'main' of git.unom.io:unom/punktfunk
apple / swift (push) Successful in 1m6s
ci / rust (push) Successful in 1m49s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m6s
android / android (push) Successful in 3m51s
windows-host / package (push) Successful in 6m56s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m22s
deb / build-publish (push) Successful in 4m40s
ci / bench (push) Successful in 4m48s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
release / apple (push) Successful in 7m51s
decky / build-publish (push) Successful in 24s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m19s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 50s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m17s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 58s
flatpak / build-publish (push) Successful in 4m12s
apple / screenshots (push) Successful in 5m39s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m50s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m41s
docker / deploy-docs (push) Successful in 20s
2026-07-04 14:29:40 +00:00
enricobuehler 7930d2f0f4 fix(core): split WIRE_VERSION from ABI_VERSION — new clients locked out of every deployed host
ABI_VERSION was doing double duty: the embeddable C surface AND the punktfunk/1
Hello/Welcome version that hosts equality-check. The WoL feature's v3 bump added
a client-local FFI function without changing a single wire byte — and every new
client started refusing against every deployed host ("ABI mismatch: client 3
host 2", observed live Deck → Bazzite). The wire now carries its own
WIRE_VERSION (still 2); ABI_VERSION stays 3 for the C header and the mgmt API's
informational field. Bump WIRE_VERSION only when the handshake/planes actually
change incompatibly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:29:33 +00:00
enricobuehler 160b67d043 fix(apple/release): embed Developer ID provisioning profile in the DMG
apple / swift (push) Successful in 1m8s
windows-host / package (push) Successful in 7m45s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m18s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m12s
ci / web (push) Successful in 47s
ci / rust (push) Successful in 12m28s
ci / docs-site (push) Successful in 58s
ci / bench (push) Successful in 5m4s
release / apple (push) Successful in 9m21s
apple / screenshots (push) Successful in 5m42s
android-screenshots / screenshots (push) Successful in 2m25s
android / android (push) Successful in 3m34s
decky / build-publish (push) Successful in 20s
deb / build-publish (push) Successful in 4m49s
flatpak / build-publish (push) Successful in 4m21s
linux-client-screenshots / screenshots (push) Successful in 2m15s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m56s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m51s
docker / deploy-docs (push) Successful in 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
web-screenshots / screenshots (push) Successful in 2m33s
The notarized Developer ID .dmg was SIGKILLed at launch ("Launchd job spawn
failed", POSIX errno 163) before main() ran: the sandboxed macOS app declares
the MANAGED keychain-access-groups entitlement, which AMFI only honors when an
embedded provisioning profile authorizes it. The DMG embedded none — App Sandbox
and the network/device keys are self-asserted for Developer ID, but a keychain
access group is not — so every launch was killed at spawn. Validly signed and
notarized (Gatekeeper accepted it), which is why this looked like a mystery. ⌘R
and the App Store build hid it: Xcode embeds a development / App Store profile;
the raw-codesign DMG path did not, so "⌘R == DMG" never held for this entitlement.

Embed a "Punktfunk macOS Developer ID" profile (Keychain Sharing) into
Contents/embedded.provisionprofile before codesign so its entitlements authorize
the access group, exactly like the App Store build's profile does. If the profile
isn't installed on the runner, warn and strip keychain-access-groups instead so
the app still launches via ClientIdentityStore's legacy file-keychain fallback —
a missing/expired profile can never reship the errno-163 brick again.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.7.3
2026-07-04 15:00:56 +02:00
enricobuehler 6c4ba77606 fix(wol): clippy + cfg-gate the Windows client module — main compiles again
windows-host / package (push) Successful in 7m18s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m17s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 50s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 56s
apple / swift (push) Successful in 1m16s
android / android (push) Successful in 3m40s
ci / web (push) Successful in 46s
ci / docs-site (push) Successful in 58s
ci / rust (push) Successful in 8m16s
ci / bench (push) Successful in 4m42s
release / apple (push) Successful in 8m37s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
deb / build-publish (push) Successful in 3m45s
apple / screenshots (push) Successful in 5m29s
flatpak / build-publish (push) Successful in 4m29s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m51s
docker / deploy-docs (push) Successful in 20s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m26s
The Wake-on-LAN batch landed with lints that fail `clippy -D warnings`
(doc continuation, char-array split, io::Error::other, redundant closure)
and an ungated `mod wol;` in the Windows client, which pulls windows-only
crates into the non-Windows stub build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 12:02:45 +00:00
enricobuehler eeee2782f5 Merge remote-tracking branch 'origin/main'
apple / screenshots (push) Has been cancelled
audit / cargo-audit (push) Has been cancelled
ci / rust (push) Has been cancelled
windows-host / package (push) Failing after 2m40s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m9s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m10s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 41s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 42s
apple / swift (push) Successful in 1m16s
android / android (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
2026-07-04 12:00:18 +00:00
enricobuehler b488bd1d99 feat(client-linux): in-process GL presenter — hardware decode ships on the Steam Deck
VAAPI decode stays; what changes is who touches the YUV. The direct path hands
the NV12 dmabuf (tiled AMD modifier since Mesa 25.1) to GdkDmabufTexture, and
GTK's tiled-NV12 import renders corrupt/gray/washed-out on the Deck. Moonlight
and mpv are clean on the same box because they import the dmabuf into their own
EGL context and convert with their own shader — video_gl.rs is that
architecture for the GTK client: per-plane EGLImages (R8 + GR88, modifier
passed through) → our YUV→RGB shader (matrix/range from the stream's CICP
signaling, unit-tested) → RGBA texture in a GdkGLContext-shared context →
fence-synced GdkGLTexture. GTK composites plain RGBA; no YUV negotiation, no
compositor CSC.

The Deck's decoder default flips back to hardware (the software stopgap is
gone); desktops keep the direct dmabuf path (offload/scan-out eligible).
PUNKTFUNK_PRESENT=direct|gl overrides either way. New failure ladder: GL
converter init failure or a convert-error streak raises a shared flag and the
session pump demotes the decoder to software with a keyframe re-request — the
same mechanism also closes the old silent-black-screen gap where a rejected
dmabuf import had no recovery at all.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 12:00:18 +00:00
enricobuehler 7e6561aaa2 style: rustfmt the Wake-on-LAN modules
ci / rust (push) Failing after 51s
ci / web (push) Successful in 53s
windows-host / package (push) Failing after 2m54s
apple / swift (push) Successful in 1m19s
ci / docs-site (push) Successful in 1m10s
android / android (push) Successful in 3m38s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m21s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m11s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 39s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 41s
ci / bench (push) Successful in 4m48s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
release / apple (push) Successful in 8m47s
deb / build-publish (push) Successful in 9m26s
flatpak / build-publish (push) Successful in 4m44s
apple / screenshots (push) Successful in 5m56s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
docker / deploy-docs (push) Successful in 17s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 13:52:17 +02:00
enricobuehler e9c5030190 feat(clients): Wake-on-LAN in apple/linux/windows/android/decky
apple / swift (push) Successful in 1m7s
audit / cargo-audit (push) Successful in 1m14s
ci / rust (push) Failing after 49s
ci / web (push) Successful in 52s
windows-host / package (push) Failing after 2m58s
ci / docs-site (push) Successful in 1m5s
android / android (push) Successful in 4m7s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m15s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m15s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 48s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 49s
ci / bench (push) Successful in 5m5s
decky / build-publish (push) Successful in 29s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 4s
release / apple (push) Successful in 8m30s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
apple / screenshots (push) Has been cancelled
docker / deploy-docs (push) Successful in 19s
Each client learns a host's MAC from the mDNS `mac` TXT while it's awake, persists it on the saved-host record, and — when reconnecting to an offline host — sends a magic packet before connecting, plus an explicit "Wake host" action. Apple wraps the C-ABI; linux/windows call the core fn directly (linux also gains a --wake CLI mode); android via a new nativeWakeOnLan JNI export (the mDNS browse record gains a 7th mac field); decky shells out to the linux client's --wake before launching the stream.

iOS/tvOS need the managed com.apple.developer.networking.multicast entitlement (pending Apple approval), so the wake path + UI are gated off via PunktfunkConnection.wakeOnLANAvailable and the entitlement is commented out — keeping iOS/tvOS releasable. MAC-learning stays active on every platform so it lights up the moment it's ungated. macOS works today.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 13:39:44 +02:00
enricobuehler 22c0d92f2e feat(core,host): Wake-on-LAN sender + host MAC advertisement
Add a runtime-free Wake-on-LAN sender in punktfunk-core (per-interface subnet-directed broadcast + 255.255.255.255 on ports 9/7, repeated, optional last-known-IP unicast) exposed both as a Rust fn and a punktfunk_wake_on_lan C-ABI (ABI v3), plus a parse_mac helper. The host enumerates its wake-capable NIC MAC(s) and advertises them in a new mDNS `mac` TXT record (routed NIC first), and best-effort detects & warns (never modifies) when the NIC isn't armed for WoL.

MAC delivery is via the unauthenticated mDNS TXT rather than the connection handshake by design: a spoofed MAC only makes a wake fail (the packet is inert; the cert fingerprint still gates the connection), and it avoids threading through the hot connect path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 13:39:44 +02:00
enricobuehler 097cc6faf4 fix(apple/gamepad): deliver PS/Home + Share buttons on macOS
macOS reserves the controller Home/PS and Share/Create buttons for its own system gestures and never delivers them to the app unless it declares the Game Controllers capability. Add GCSupportsControllerUserInteraction=YES to the macOS target only (iOS/tvOS rely on the focus engine, so it must not be in the shared plist), alongside the existing preferredSystemGestureState=.disabled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 13:39:44 +02:00
enricobuehler 8b37badae4 docs(security): record measured WDA_EXCLUDEFROMCAPTURE behavior + capture-vs-viewer framing
Tested on .173: a WDA_EXCLUDEFROMCAPTURE window (affinity readback 0x11,
confirmed active) is pixel-identically visible in the punktfunk/1 stream
across no-flag / flag-set / flag-cleared phases — the flag makes no
difference to a present-tap capture. Replace the "untested, treat as
expected" note in the IDD-push residual list with the measured result,
and correct the framing: WDA visibility matches what a person at the
screen sees (it exceeds an ordinary capture tool, not the physical
viewer).

Add the matching public-facing paragraph to the security page covering
both asymmetries — WDA windows appear (same as a physical viewer), DRM
video is blanked (less than a physical viewer) — tied back to the page's
"a client sees what someone at the machine sees" model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 11:16:18 +00:00
enricobuehler 90c2d8b3a0 fix(host): don't count punktfunk's own virtual Deck as a physical Steam controller
apple / swift (push) Successful in 1m7s
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / web (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
The Steam-conflict gate scanned /sys/bus/hid/devices for non-virtual 28DE
devices, but the usbip/gadget virtual Decks present a REAL USB device (vhci
resolves through vhci_hcd, not /devices/virtual/) — so a just-ended session's
pad still detaching, or a concurrent session's live one, read as "physical
Steam controller attached" and degraded every back-to-back Deck session to
DualSense (observed live on Bazzite). Exclude our pads by their PFDK… serial
(HID_UNIQ), with the vhci_hcd path as belt and braces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 11:14:24 +00:00
enricobuehler 853e7fe92f fix(client-linux): Deck trackpad clicks — bind to the correct pad, stop riding the button plane
apple / swift (push) Successful in 1m6s
ci / rust (push) Successful in 1m27s
ci / web (push) Successful in 50s
android / android (push) Successful in 3m19s
ci / docs-site (push) Successful in 1m6s
apple / screenshots (push) Successful in 5m29s
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
SDL's Steam Deck mapping delivers the pad clicks as gamepad BUTTONS with no
surface identity: the generic `touchpad` button is the LEFT pad's click and
`misc2` the RIGHT's (SDL_gamepad_db.h `touchpad:b17,misc2:b16`). The client
forwarded `touchpad` as wire BTN_TOUCHPAD — which the host maps to the RIGHT
pad click (DualSense convention) — and dropped `misc2` entirely: a left-pad
click registered on the right pad, a right-pad click nowhere, and the
mis-routed state could stick.

Clicks from a multi-touchpad pad now ride the rich plane as TouchpadEx with
their surface, reusing the surface's live contact point (click buttons carry
no position). forward_touch carries the held click through motion frames so a
touch update can't clear a click mid-press, and the flush lifts held clicks on
detach/pad-switch. A DualSense's single touchpad button stays on the button
plane unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 11:08:44 +00:00
enricobuehler df496776b0 fix(client-linux): Deck raw-pad capture — clear Steam's SDL device filter, honest degradation warning
apple / swift (push) Successful in 1m14s
apple / screenshots (push) Successful in 5m41s
android / android (push) Successful in 3m46s
ci / web (push) Successful in 49s
ci / rust (push) Successful in 1m23s
ci / docs-site (push) Successful in 58s
ci / bench (push) Successful in 4m52s
deb / build-publish (push) Successful in 4m34s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Successful in 4m29s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m58s
docker / deploy-docs (push) Successful in 6s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m8s
The Deck's built-in controller can never leave Steam Input ("Steam Controller"
is always-required in the shortcut's matrix; Disable Steam Input only affects
other controller brands), so the raw 28DE:1205 device is the only path to the
trackpads/paddles/gyro. Steam hides it from SDL by launching shortcuts with
SDL_GAMECONTROLLER_IGNORE_DEVICES naming every physical pad it virtualized —
clear it (and _EXCEPT) at startup while single-threaded, logging what Steam set
as field evidence. The post-attach warning now states the real condition (raw
pad never enumerated; sticks + buttons still work) instead of advising a
Steam Input toggle that doesn't exist for the built-in controller.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 10:06:48 +00:00
enricobuehler 5310176ab5 fix(client-linux,host): Deck video defaults to software decode + input-interception diagnostics
apple / swift (push) Successful in 1m8s
apple / screenshots (push) Successful in 5m38s
windows-host / package (push) Successful in 7m12s
android / android (push) Successful in 3m36s
ci / rust (push) Successful in 1m31s
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 57s
ci / bench (push) Successful in 4m56s
decky / build-publish (push) Successful in 14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
deb / build-publish (push) Successful in 4m38s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
flatpak / build-publish (push) Successful in 4m55s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m57s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m21s
docker / deploy-docs (push) Successful in 17s
Video (Deck): the VAAPI zero-copy path renders corrupt/gray/washed-out on the
Deck — root-caused to Mesa >= 25.1 exporting radeonsi VCN decode surfaces TILED
(the Flatpak runtime's Mesa 26 drives both the decoder and GTK's GL, and GTK's
tiled-NV12 dmabuf import mishandles it; desktop Tier-1 validations ran distro
Mesa with linear export). `auto` now resolves to software on a Deck (clean,
correct-colour, easily handles 1280x800 HEVC); PUNKTFUNK_DECODER=vaapi still
forces the hw path, with the descriptor modifier dump + GSK_RENDERER as the
bisect levers. Also reserve extra_hw_frames=4 on the VAAPI decoder: the
presenter pins mapped surfaces past receive_frame, and the fixed pool recycling
a surface the renderer still samples is intermittent block corruption anywhere.

Input (Deck): with Steam Input ON for Punktfunk, SDL sees only Steam's virtual
X360 pad — the right trackpad arrives as a plain right stick and the left
trackpad/paddles/gyro not at all, silently. The client now checks once the
post-attach enumeration settles and raises a toast + warn naming the fix
(disable Steam Input for the shortcut). The host logs a one-shot warning when
InputPlumber is running (Bazzite default) since it can grab the virtual Deck
pad and re-emit it under a different identity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 09:56:06 +00:00
enricobuehler 76ff616dcf fix(flatpak): drop --socket=pipewire (unknown to the builder) — keep the xdg-run bind
apple / swift (push) Successful in 1m13s
apple / screenshots (push) Successful in 5m46s
android / android (push) Successful in 11m8s
ci / web (push) Successful in 46s
ci / docs-site (push) Successful in 57s
ci / rust (push) Successful in 12m53s
ci / bench (push) Successful in 4m44s
decky / build-publish (push) Successful in 18s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 4m34s
flatpak / build-publish (push) Successful in 4m5s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 9m54s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m45s
docker / deploy-docs (push) Successful in 18s
The v0.7.2 flatpak build failed: `error: Unknown socket type pipewire` — this
flatpak-builder toolchain (and the Deck's flatpak 1.16 override CLI) don't
accept --socket=pipewire. --filesystem=xdg-run/pipewire-0 binds the same native
socket and is the portable form already validated on-Deck (pipewire-0 appears
in the sandbox, client audio node registers, no pw-connect error). Keep only
that + --socket=pulseaudio.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 09:20:52 +00:00
enricobuehler ac706ba839 chore(release): bump workspace version to 0.7.2
audit / cargo-audit (push) Successful in 18s
apple / swift (push) Successful in 1m10s
ci / web (push) Successful in 49s
ci / docs-site (push) Successful in 58s
ci / rust (push) Successful in 9m41s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 47s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 54s
ci / bench (push) Successful in 4m40s
windows-host / package (push) Successful in 7m13s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m22s
release / apple (push) Successful in 9m14s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m14s
android-screenshots / screenshots (push) Successful in 53s
apple / screenshots (push) Successful in 5m45s
android / android (push) Successful in 3m15s
decky / build-publish (push) Successful in 14s
deb / build-publish (push) Successful in 3m31s
linux-client-screenshots / screenshots (push) Successful in 2m17s
flatpak / build-publish (push) Failing after 4m6s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 10m1s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m7s
web-screenshots / screenshots (push) Successful in 2m44s
docker / deploy-docs (push) Successful in 17s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 6s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
Ship the flatpak PipeWire-socket audio fix (94b5f48) to the stable channel —
a tag is required (main pushes only publish the canary flatpak branch), and
0.7.1 stable users on the Deck have no client audio until this lands. Bump
[workspace.package] + the 9 Cargo.lock workspace entries (CI builds --locked).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.7.2
2026-07-04 08:59:26 +00:00
enricobuehler 94b5f48d0b fix(flatpak): expose native PipeWire socket so client audio works
The Linux client speaks the native PipeWire protocol (audio.rs `pw connect`),
but the manifest granted only --socket=pulseaudio, so the sandbox had just
`pulse/native` and no `pipewire-0`. Playback + mic both died with
"pw connect (is PipeWire running in this session?)" — reproduced live on a
Steam Deck in Gaming Mode (no client audio node ever appeared).

Add --socket=pipewire (canonical) + --filesystem=xdg-run/pipewire-0 (portable
bind of the same socket). Validated on-Deck via a `flatpak override
--filesystem=xdg-run/pipewire-0`: pipewire-0 then appears in the sandbox and
the client registers its "punktfunk-client" PipeWire node with no pw-connect
error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 08:59:11 +00:00
enricobuehler 139d032e55 docs(bazzite): fix the "rpm-ostree upgrade doesn't update punktfunk" trap
apple / swift (push) Successful in 1m11s
android / android (push) Successful in 4m18s
ci / rust (push) Successful in 4m51s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 1m0s
apple / screenshots (push) Successful in 5m47s
deb / build-publish (push) Successful in 2m56s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
ci / bench (push) Successful in 4m45s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 10m2s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m0s
`rpm-ostree upgrade` re-resolves layered packages only when the BASE image
changes; on a frozen Bazzite base (pinned :stable tag / paused rebase) it
reports "No updates available" and never bumps the layered punktfunk even
when newer RPMs are live in the repo — observed on the .41 host stuck at
0.6.0 while 0.7.x sat in the registry.

- Add packaging/bazzite/update-punktfunk.sh: detects the layered punktfunk
  packages, refreshes rpmmd, and forces a re-resolve via
  `rpm-ostree update --uninstall <pkg> --install <pkg>` (the one-transaction
  idiom that actually pulls a new layered version on a static base).
- Document the trap + the fix in packaging/bazzite/README.md, including the
  channel gotcha: an enabled punktfunk-canary.repo (<next-minor>.0-0.ciN)
  outranks stable X.Y.Z-1, so the box silently tracks canary — enable one
  channel only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 08:38:52 +00:00
enricobuehler caa7a1c735 chore(release): bump workspace version to 0.7.1
apple / swift (push) Successful in 1m5s
audit / cargo-audit (push) Successful in 16s
ci / web (push) Successful in 1m6s
ci / docs-site (push) Successful in 1m24s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 48s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 52s
ci / bench (push) Successful in 5m1s
android-screenshots / screenshots (push) Successful in 47s
ci / rust (push) Successful in 9m48s
windows-host / package (push) Successful in 7m10s
android / android (push) Successful in 3m53s
release / apple (push) Successful in 8m47s
decky / build-publish (push) Successful in 15s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m20s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m14s
deb / build-publish (push) Successful in 2m59s
apple / screenshots (push) Successful in 5m42s
flatpak / build-publish (push) Successful in 4m11s
linux-client-screenshots / screenshots (push) Successful in 1m39s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 10m19s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m19s
docker / deploy-docs (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
web-screenshots / screenshots (push) Successful in 2m34s
Cut 0.7.1 to test the GTK + Decky polish batch (57ae00a) on-device: the
host-click / disconnect-chord / gray-screen-recovery / leak fixes on the
Linux client, the Deck launcher perf profile, and the Decky pin/pairing
fixes. The [workspace.package] version (inherited by every crate via
version.workspace) is the release being cut; refresh the 9 workspace
entries in Cargo.lock to match (CI builds --locked). Canary derives from
the tag (scripts/ci/pf-version.sh), so cutting v0.7.1 auto-advances canary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.7.1
2026-07-04 07:47:58 +00:00
enricobuehler 13dc7fc49f style(linux): rustfmt the keyframe-recovery throttle line
apple / swift (push) Successful in 1m9s
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
Wrap the `last_kf_req.is_none_or(...)` guard to satisfy `cargo fmt --all
--check` (CI Format step).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 07:47:16 +00:00
enricobuehler 57ae00a9c8 fix(clients): GTK + Decky polish batch from live Deck/Windows testing
ci / rust (push) Failing after 41s
apple / swift (push) Successful in 1m8s
ci / web (push) Successful in 55s
ci / docs-site (push) Successful in 1m6s
android / android (push) Successful in 3m20s
deb / build-publish (push) Successful in 2m55s
decky / build-publish (push) Successful in 27s
apple / screenshots (push) Successful in 5m46s
ci / bench (push) Successful in 5m5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 34s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 3m20s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m31s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 53s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m18s
docker / deploy-docs (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
GTK Linux client:
- hosts/library: clicking a card was dead — the handler was on
  FlowBoxChild::activate (never emitted on click); bridge child-activated
  → child.activate() on the FlowBox (ui_hosts, ui_library).
- stream: the Ctrl+Alt+Shift+D/Q/S chords (and all key forwarding) were
  dropped because the key controller sat on the overlay, which loses focus
  to the header back button after nav.push+fullscreen — move it to the
  window and remove it on teardown.
- video: a mid-session VAAPI decode error rebuilt a software decoder but
  never requested a keyframe, so under the infinite GOP the picture stayed
  gray/frozen forever. Request an IDR on any VAAPI error, keep the hardware
  decoder, and demote to software only after repeated failures.
- stream: fix a per-session Capture↔overlay reference cycle that leaked the
  overlay subtree + the Arc<NativeClient> on every session end — hold the
  overlay weakly.
- stream: accumulate the fractional wheel remainder so precision-scroll
  (Deck trackpad / hi-res wheels) sub-unit deltas aren't dropped.
- gamepad library: keep the launcher smooth on the Deck — freeze the aurora
  and trim the visible card range (fewer 3D offscreen passes) on low-power.
- gamepad: log full pad identity (vid:pid:name:type:virtual) on attach to
  diagnose an empty controller list on the Deck.
- cli: --connect host:<badport> silently did nothing; default to 9777 + warn.
- css: add the missing .pf-neutral pill rule; fix the clipped most-recent
  accent (inset outline instead of a corner-clipped box-shadow bar).

Decky plugin:
- surface the on-screen library browser: label the host-row Games button.
- fix silent pin data-loss — the detached Games modal captured a frozen
  pins array, so pinning a second game clobbered the first; mirror pins in
  a ref and track the modal's pinned ids locally for a live label.
- route pair-required hosts through the pairing modal from the fullscreen
  Stream button (parity with the QAM panel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 07:37:04 +00:00
enricobuehler 882a3d57f6 chore(release): bump workspace version to 0.7.0
android-screenshots / screenshots (push) Successful in 2m12s
windows-host / package (push) Successful in 6m43s
android / android (push) Successful in 9m24s
release / apple (push) Successful in 9m35s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m8s
apple / swift (push) Successful in 1m10s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 50s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 53s
linux-client-screenshots / screenshots (push) Successful in 1m41s
apple / screenshots (push) Successful in 5m37s
web-screenshots / screenshots (push) Successful in 2m37s
audit / cargo-audit (push) Successful in 1m12s
ci / web (push) Successful in 1m8s
ci / docs-site (push) Successful in 1m22s
ci / rust (push) Successful in 4m34s
deb / build-publish (push) Successful in 3m0s
ci / bench (push) Successful in 4m57s
decky / build-publish (push) Successful in 12s
flatpak / build-publish (push) Successful in 4m7s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 10m2s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m14s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m42s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m15s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 54s
docker / deploy-docs (push) Successful in 20s
The [workspace.package] version (inherited by every crate via
version.workspace) is the release being cut. Refresh the 9 workspace entries
in Cargo.lock to match (CI builds --locked). Canary derives from the tag now
(scripts/ci/pf-version.sh), so no canary-base edit is needed — cutting v0.7.0
auto-advances canary to 0.8.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.7.0
2026-07-03 22:45:45 +00:00
enricobuehler fa28fa19a0 Merge remote-tracking branch 'origin/main'
android / android (push) Has been cancelled
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
2026-07-03 22:41:42 +00:00