Commit Graph
4 Commits
Author SHA1 Message Date
enricobuehler e1ddd49e37 fix(client-core,ffvk): close the proof-lint hole in two of the three unguarded crates
`clippy::undocumented_unsafe_blocks` is what makes the SAFETY convention a rule rather than a habit,
and three crates had never adopted it — pf-client-core (91 unsafe items), pf-presenter (123) and
punktfunk-core (167) — while every other subsystem crate denied it. That gap is why the decoders'
`unsafe impl Send`s carried a one-line aside instead of an argument: nothing required one.

pf-client-core and pf-ffvk now deny it, with a proof written for all 58 + 3 sites they had.

⚠️ 44 of those 58 were WINDOWS-ONLY — `clipboard.rs` 24 and `video_d3d11.rs` 20 — and invisible to
the Linux measurement that sized this work at 14. Same trap as the E0133 sweep: a Linux-only survey
of a cross-platform crate undercounts by whatever the `cfg` hides, here by 3x. Landing the deny on
the strength of that number alone would have re-broken Windows CI, which is exactly the mistake this
session already made once with the `warn`-that-was-really-`deny`.

The proofs say what is actually load-bearing rather than restating the call. In `clipboard.rs` that
is the ownership split Win32 requires and nothing in the code stated: `GetClipboardData` returns a
handle BORROWED from the clipboard (never freed here), while `GlobalAlloc` + `SetClipboardData`
TRANSFERS ownership to it (which is why nothing frees that one either) — two opposite rules, three
lines apart. In `video_d3d11.rs` the recurring one is that libav's `get_format` list is
NUL-terminated by `AV_PIX_FMT_NONE`, which is what keeps the walk in bounds.

Remaining: punktfunk-core (~146, of which `abi.rs` is 141) and pf-presenter (~108). Both want the
"state the contract once" treatment — abi.rs's sites are a handful of repeating shapes (`opt_cstr`
on caller C strings, null-guarded out-param writes, forwarding calls), not 141 distinct arguments.
Note the vendored `fec-rs` (18 sites) is a separate path-dependency crate, so it is out of scope
rather than something to prove.

Verified: Linux .21 fmt + both CI clippy steps rc=0; Windows .47 `-p pf-client-core` clippy
`-D warnings` rc=0 (the only place the 44 are visible), plus the full Windows CI clippy set and
pf-capture's 18 tests.
2026-07-29 08:48:42 +02:00
enricobuehlerandClaude Opus 5 2a088e13a4 feat(client/windows): bind a host to a profile, connect with one, pin one, copy its link
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m8s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m37s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m25s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 3m43s
apple / swift (push) Successful in 5m17s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 0s
flatpak / build-publish (push) Canceled after 0s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Canceled after 0s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Canceled after 0s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Canceled after 0s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Canceled after 0s
docker / build-push-arm64cross (push) Canceled after 0s
docker / deploy-docs (push) Canceled after 0s
decky / build-publish (push) Canceled after 0s
deb / build-publish (push) Canceled after 0s
deb / build-publish-host (push) Canceled after 0s
deb / build-publish-client-arm64 (push) Canceled after 0s
apple / screenshots (push) Canceled after 0s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Canceled after 0s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Canceled after 0s
android / android (push) Canceled after 2m34s
ci / rust-arm64 (push) Canceled after 0s
ci / web (push) Canceled after 0s
ci / docs-site (push) Canceled after 0s
ci / bench (push) Canceled after 0s
ci / rust (push) Canceled after 2m30s
arch / build-publish (push) Canceled after 2m39s
The WinUI half of §5.2: `Target` carries a one-off profile into the session's `--profile`,
the host editor gains the binding picker, and the tile names its bound profile on a chip so
what a plain click will do is visible without opening anything.

Shape notes, both forced by this toolkit rather than chosen:

- The flyout has no submenus, so "Connect with", "Pin as card" and "Unpin card" are flat
  items, one per profile, matched by prefix. The prefixes end in ": " so a profile named
  "Copy link" can't collide with a fixed entry.
- The binding picker commits on change rather than at Save. The rest of that sheet is text
  boxes with draft refs, which need a Save; a ComboBox doesn't, and making it wait would be
  the odd one out.

Semantics stay identical to the Linux client, because they are the design's, not the
platform's: "Connect with" never rebinds, "Default settings" is `Some("")` so it really
does override a bound host for one session, and a binding whose profile was deleted reads
as Default settings and resolves to it.

`pf_client_core::clipboard::set_text` is the small addition the crate needed for "Copy
link" — the OS clipboard plumbing was already there, just private to the streaming bridge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 00:17:15 +02:00
enricobuehlerandClaude Fable 5 8fe90a8a4b fix(client): clipboard poll cadence was never applied (and CI clippy)
ci / web (push) Successful in 1m8s
apple / swift (push) Successful in 1m17s
ci / docs-site (push) Successful in 1m9s
apple / screenshots (push) Successful in 6m17s
ci / bench (push) Successful in 6m51s
decky / build-publish (push) Successful in 21s
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 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
deb / build-publish (push) Successful in 9m11s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
android / android (push) Successful in 13m32s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8m1s
arch / build-publish (push) Successful in 17m21s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Failing after 5m6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7m43s
deb / build-publish-host (push) Successful in 11m42s
flatpak / build-publish (push) Failing after 8m23s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Failing after 6m14s
ci / rust (push) Successful in 25m38s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 5m45s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m54s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m32s
docker / deploy-docs (push) Successful in 27s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 9m8s
POLL was dead: the local clipboard was re-read once per inbound event wait
(<=120 ms) instead of on its own 400 ms cadence, so the constant documenting
the interval described something the code did not do. Give it a deadline of
its own -- the event wait is short because it bounds teardown latency, which
is no reason to hammer the Win32 clipboard eight times a second while the
user is copying in another app.

Build State in one expression while here, and note for next time: CI runs
clippy as --workspace --all-targets -- -D warnings, so a scoped run without
-D warnings (what I did) does not reproduce it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:22:24 +02:00
enricobuehlerandClaude Fable 5 cab6350723 feat(client): shared clipboard on Windows
The protocol half has been in punktfunk-core since the clipboard work
landed -- the per-session fetch task, plus clip_control/clip_offer/
clip_fetch/clip_serve/next_clip on NativeClient -- but only the Apple
client ever drove it, through the C ABI. The Windows and Linux clients link
the core directly and simply never wired it, so copy-paste between host and
client worked on a Mac and nowhere else.

This adds the missing half: the OS-clipboard bridge, on its own session
thread beside the audio one.

Local -> remote stays lazy by construction, as the design asks: a
GetClipboardSequenceNumber poll spots a local copy and we announce only the
FORMAT LIST; bytes are read when (and only when) the host actually pastes
and sends a FetchRequest.

Remote -> local is EAGER in this first cut, which is a deliberate deviation
worth naming. macOS gets laziness free from NSPasteboardItemDataProvider;
the Windows equivalent is delayed rendering, which needs a clipboard-owning
window running its own message pump. So we fetch on the offer and place real
bytes under a 4 MB cap -- text always crosses, a large image is skipped
rather than pulled for a paste that may never come. Delayed rendering lifts
the cap later.

Echo suppression is the design's Windows rule verbatim (capture the
sequence number right after our own SetClipboardData); without it every
copy ping-pongs between the machines forever. Content marked
ExcludeClipboardContentFromMonitorProcessing -- what password managers set
-- is never announced and never served.

Text and PNG for now. Apps that publish only CF_DIB need the conversion the
host already has. Linux keeps a stub: the bridge itself is
platform-neutral and will drive a data-control seam unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:06:06 +02:00