From 0925f1aaa14f7526df138ae70813d12133192ae1 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Fri, 26 Jun 2026 11:53:02 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20complete=20the=20docs/=E2=86=92design/?= =?UTF-8?q?=20and=20openapi=E2=86=92api/=20rename=20references?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The file moves (docs/ → design/, docs/api/openapi.json → api/openapi.json) landed in 8897286, but the matching reference updates did not — so mgmt.rs's drift-test `include_str!("../../../docs/api/openapi.json")` pointed at a path that no longer exists and the host failed to build. This restores it and updates every reference: - mgmt.rs include_str! → ../../../api/openapi.json (fixes the build) - web/orval.config.ts codegen target, web/Dockerfile, .dockerignore - deb/rpm/Arch packaging install paths - CLAUDE.md, the .gitea CI workflows, code doc-comments, design-doc cross-links docs-site route URLs (/docs/...) untouched. Co-Authored-By: Claude Opus 4.8 (1M context) --- .dockerignore | 4 ++-- .gitea/workflows/flatpak.yml | 2 +- .../workflows/windows-drivers-provision.yml | 2 +- .gitea/workflows/windows-drivers.yml | 2 +- CLAUDE.md | 19 +++++++++++++------ clients/apple/README.md | 2 +- crates/pf-driver-proto/src/lib.rs | 2 +- .../src/capture/windows/desktop_watch.rs | 2 +- .../src/capture/windows/idd_push.rs | 2 +- .../src/capture/windows/wgc_relay.rs | 2 +- crates/punktfunk-host/src/config.rs | 2 +- .../punktfunk-host/src/gamestream/crypto.rs | 2 +- crates/punktfunk-host/src/gamestream/mod.rs | 2 +- .../punktfunk-host/src/gamestream/pairing.rs | 2 +- crates/punktfunk-host/src/gamestream/video.rs | 2 +- .../src/inject/windows/dualsense_windows.rs | 2 +- crates/punktfunk-host/src/main.rs | 4 ++-- crates/punktfunk-host/src/mgmt.rs | 10 +++++----- crates/punktfunk-host/src/punktfunk1.rs | 2 +- crates/punktfunk-host/src/session_plan.rs | 2 +- crates/punktfunk-host/src/session_tuning.rs | 2 +- .../src/vdisplay/windows/pf_vdisplay.rs | 2 +- .../punktfunk-host/src/windows/wgc_helper.rs | 2 +- docs-site/README.md | 4 ++-- packaging/arch/PKGBUILD | 2 +- packaging/bazzite/README.md | 2 +- packaging/debian/build-deb.sh | 2 +- packaging/rpm/punktfunk.spec | 4 ++-- packaging/windows/README.md | 3 ++- packaging/windows/drivers/Cargo.toml | 2 +- .../windows/drivers/pf-vdisplay/Cargo.toml | 2 +- .../drivers/pf-vdisplay/src/adapter.rs | 2 +- .../drivers/pf-vdisplay/src/control.rs | 2 +- .../windows/drivers/pf-vdisplay/src/lib.rs | 2 +- scripts/bootstrap-ubuntu.sh | 2 +- scripts/ci/provision-windows-wdk.ps1 | 2 +- scripts/headless/run-headless-sway.sh | 2 +- web/Dockerfile | 4 ++-- web/README.md | 4 ++-- web/orval.config.ts | 4 ++-- web/src/styles.css | 2 +- 41 files changed, 65 insertions(+), 57 deletions(-) diff --git a/.dockerignore b/.dockerignore index bae4bbe0..7d2d835f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,9 @@ # Root build context is used only by web/Dockerfile, which needs web/ and -# docs/api/openapi.json. Allowlist those; keep everything else (target/, .git, crates) +# api/openapi.json. Allowlist those; keep everything else (target/, .git, crates) # out of the context upload. * !web -!docs/api/openapi.json +!api/openapi.json web/node_modules web/.output web/dist diff --git a/.gitea/workflows/flatpak.yml b/.gitea/workflows/flatpak.yml index c470ee19..baeee860 100644 --- a/.gitea/workflows/flatpak.yml +++ b/.gitea/workflows/flatpak.yml @@ -24,7 +24,7 @@ on: push: branches: [main] # The flatpak is the CLIENT — only rebuild when the client/core/manifest change, not on every - # docs/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too. + # design/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too. paths: - 'clients/linux/**' - 'crates/punktfunk-core/**' diff --git a/.gitea/workflows/windows-drivers-provision.yml b/.gitea/workflows/windows-drivers-provision.yml index dbade104..d590bd15 100644 --- a/.gitea/workflows/windows-drivers-provision.yml +++ b/.gitea/workflows/windows-drivers-provision.yml @@ -1,5 +1,5 @@ # One-shot provisioning of the WDK + cargo-wdk onto the persistent self-hosted windows-amd64 runner, so -# the all-Rust UMDF drivers can build there (docs/windows-host-rewrite.md, M0). The runner has the base +# the all-Rust UMDF drivers can build there (design/windows-host-rewrite.md, M0). The runner has the base # Windows SDK + MSVC + LLVM + Rust but NOT the WDK (no km/wdf/iddcx headers) or cargo-wdk. # # Dispatch manually (workflow_dispatch). Idempotent: re-running is a near no-op once provisioned. The diff --git a/.gitea/workflows/windows-drivers.yml b/.gitea/workflows/windows-drivers.yml index 2d90408d..677a8678 100644 --- a/.gitea/workflows/windows-drivers.yml +++ b/.gitea/workflows/windows-drivers.yml @@ -1,5 +1,5 @@ # Windows driver workspace CI — runs on the self-hosted Windows runner (home-windows-1, host mode; -# label windows-amd64). Part of the Windows-host rewrite (docs/windows-host-rewrite.md, M0). +# label windows-amd64). Part of the Windows-host rewrite (design/windows-host-rewrite.md, M0). # # Stage 1 (this file): PROBE the runner's driver toolchain (WDK / EWDK / cargo-make / LLVM / the # inf2cat/stampinf/devgen/signtool tools) so we know what's provisioned BEFORE writing driver code, diff --git a/CLAUDE.md b/CLAUDE.md index 562996fd..4c7c3d23 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,7 +2,7 @@ Low-latency desktop/game streaming stack, Linux-first, with a shared Rust protocol core (`punktfunk-core`) exposed over a C ABI and native clients per platform. Full design: -[`docs/implementation-plan.md`](docs/implementation-plan.md). Status table: `README.md`. +[`design/implementation-plan.md`](design/implementation-plan.md). Status table: `README.md`. ## Where the work stands @@ -104,9 +104,16 @@ Low-latency desktop/game streaming stack, Linux-first, with a shared Rust protoc captures the HDR desktop as FP16/Rgb10a2 (DDA FP16 for the secure desktop), the encoder forces HEVC Main10 + BT.2020 PQ (NVENC ABGR10/P010; AMF/QSV P010 + a swscale Rgb10a2→P010 fallback), the client auto-detects PQ from the HEVC VUI — gated by `PUNKTFUNK_10BIT` + client `VIDEO_CAP_10BIT`; **Windows - host only** (the Linux host stays 8-bit, blocked upstream). **AMF/QSV is CI-green but not yet - on-glass validated** (no AMD/Intel Windows box in the lab); NVENC is live-validated. Newer/less - battle-tested than the Linux host. Packaging: `packaging/windows/`. + host only** (the Linux host stays 8-bit, blocked upstream). **Vulkan-game HDR over the virtual + display**: NVIDIA/AMD Vulkan ICDs refuse to *advertise* an HDR color space for a surface on an IddCx + indirect display (so Vulkan games — Doom: The Dark Ages, id Tech, etc. — say "device does not support + HDR"), even though the ICD happily *accepts + presents* a forced HDR swapchain there. A tiny always-on + Vulkan **implicit layer** (`packaging/windows/pf-vkhdr-layer/`, `VK_LAYER_PUNKTFUNK_hdr_inject`) + injects the `HDR10_ST2084`/scRGB surface formats into `vkGetPhysicalDeviceSurfaceFormats[2]KHR`, + self-gated on the display's actual advanced-color state (no-op on SDR / real monitors); bundled + + HKLM-registered by the installer. **Live-validated: Doom: The Dark Ages enables HDR over the virtual + display.** **AMF/QSV is CI-green but not yet on-glass validated** (no AMD/Intel Windows box in the + lab); NVENC is live-validated. Newer/less battle-tested than the Linux host. Packaging: `packaging/windows/`. ## What's left @@ -245,8 +252,8 @@ bash crates/punktfunk-core/tests/c/run.sh # standalone C-ABI link + round-trip ``` Generated artifacts are **checked in** and CI fails on drift: `include/punktfunk_core.h` -(cbindgen from `punktfunk-core/src/abi.rs`) and `docs/api/openapi.json` (regenerate with -`cargo run -p punktfunk-host -- openapi > docs/api/openapi.json`; spec lives in `mgmt.rs`). +(cbindgen from `punktfunk-core/src/abi.rs`) and `api/openapi.json` (regenerate with +`cargo run -p punktfunk-host -- openapi > api/openapi.json`; spec lives in `mgmt.rs`). CI is Gitea Actions (`.gitea/workflows/`, guide: docs-site `ci.md`): `ci.yml` runs the workspace checks inside the `git.unom.io/unom/punktfunk-rust-ci` image plus web/docs-site diff --git a/clients/apple/README.md b/clients/apple/README.md index 12ffccf6..f8e6b308 100644 --- a/clients/apple/README.md +++ b/clients/apple/README.md @@ -361,4 +361,4 @@ ever switched to a logged-in GUI session, re-adding macOS to the job's capture s - Mid-stream renegotiation (resolution change without reconnect) is designed-for but not implemented (the Welcome is one-shot today). - Host-side gamepad injection needs `/dev/uinput` access on the box (udev rule from - `docs/linux-setup.md`). + `design/linux-setup.md`). diff --git a/crates/pf-driver-proto/src/lib.rs b/crates/pf-driver-proto/src/lib.rs index b7c98b98..900c5872 100644 --- a/crates/pf-driver-proto/src/lib.rs +++ b/crates/pf-driver-proto/src/lib.rs @@ -276,7 +276,7 @@ pub mod frame { /// These were hand-duplicated as `OFF_*`/`SHM_*` constants in `inject/{gamepad,dualsense}_windows.rs` /// and (as bare literals — `*view.add(140)`) in the standalone `xusb-driver`/`dualsense-driver` /// workspaces, guarded only by "must match" comments — the top ABI-drift hazard the audit flagged -/// (`docs/windows-host-rewrite.md` §2.7). Owning them here with `Pod` derives + `offset_of!` +/// (`design/windows-host-rewrite.md` §2.7). Owning them here with `Pod` derives + `offset_of!` /// asserts makes a one-sided edit a compile error. /// /// The host creates the section (privileged, permissive DACL so the restricted WUDFHost token can diff --git a/crates/punktfunk-host/src/capture/windows/desktop_watch.rs b/crates/punktfunk-host/src/capture/windows/desktop_watch.rs index 8ee9ff3f..459d68cf 100644 --- a/crates/punktfunk-host/src/capture/windows/desktop_watch.rs +++ b/crates/punktfunk-host/src/capture/windows/desktop_watch.rs @@ -1,5 +1,5 @@ //! Input-desktop watcher (Windows) — the authoritative "normal vs secure desktop" signal for the -//! two-process secure-desktop design (docs/windows-secure-desktop.md). +//! two-process secure-desktop design (design/windows-secure-desktop.md). //! //! Windows switches the *input desktop* to "Winlogon" (the secure desktop) for UAC elevation, the //! lock screen and the login screen, and back to "Default" for the normal session. WGC captures only diff --git a/crates/punktfunk-host/src/capture/windows/idd_push.rs b/crates/punktfunk-host/src/capture/windows/idd_push.rs index e599cf09..a36436ca 100644 --- a/crates/punktfunk-host/src/capture/windows/idd_push.rs +++ b/crates/punktfunk-host/src/capture/windows/idd_push.rs @@ -562,7 +562,7 @@ impl IddPushCapturer { /// Block (bounded) until the driver has ATTACHED to the host ring (`DRV_STATUS_OPENED`) **and published /// a first frame**, else fail so the caller can fall back to DDA (audit §5.1 + - /// `docs/windows-host-rewrite.md` §2.5 — the GB1 game-capture fix). + /// `design/windows-host-rewrite.md` §2.5 — the GB1 game-capture fix). /// /// Requiring the first frame — not just the attach — catches the *reconnect-into-a-broken-state* case: /// a fullscreen game can leave the virtual display in a format/size that the driver's `publish()` guard diff --git a/crates/punktfunk-host/src/capture/windows/wgc_relay.rs b/crates/punktfunk-host/src/capture/windows/wgc_relay.rs index 3a6f1701..3cf20cae 100644 --- a/crates/punktfunk-host/src/capture/windows/wgc_relay.rs +++ b/crates/punktfunk-host/src/capture/windows/wgc_relay.rs @@ -1,5 +1,5 @@ //! Host-side WGC helper relay (Windows two-process secure-desktop design, -//! docs/windows-secure-desktop.md — step 4). +//! design/windows-secure-desktop.md — step 4). //! //! WGC won't activate under the SYSTEM account, so the SYSTEM host can't capture the normal desktop //! itself. Instead it spawns `punktfunk-host wgc-helper` in the **interactive user session** (so WGC works) diff --git a/crates/punktfunk-host/src/config.rs b/crates/punktfunk-host/src/config.rs index 054c0dfe..991dcc0f 100644 --- a/crates/punktfunk-host/src/config.rs +++ b/crates/punktfunk-host/src/config.rs @@ -4,7 +4,7 @@ //! environment before the host starts, and **for the knobs captured here the environment is constant for the //! process lifetime**, so a lazily-parsed global is equivalent to "parsed once at startup". //! -//! **Goal-1 stages 1–2** (`docs/windows-host-rewrite.md` §2.2): stage 1 stood this up; stage 2 migrated the +//! **Goal-1 stages 1–2** (`design/windows-host-rewrite.md` §2.2): stage 1 stood this up; stage 2 migrated the //! genuinely-constant operator/dispatch knobs onto it (the dispatch-disagreement bug class: `idd_push`, //! `capture_backend`, `encoder_pref`, `render_adapter`, `no_wgc`, the vdisplay backend select — plus the //! plan-named `secure_dda`/`idd_depth`/`zerocopy`/`ten_bit` and the multi-site `perf`/`compositor`/ diff --git a/crates/punktfunk-host/src/gamestream/crypto.rs b/crates/punktfunk-host/src/gamestream/crypto.rs index 437f7512..53d1a589 100644 --- a/crates/punktfunk-host/src/gamestream/crypto.rs +++ b/crates/punktfunk-host/src/gamestream/crypto.rs @@ -1,7 +1,7 @@ //! Pairing crypto primitives (control plane only — distinct from `punktfunk_core`'s AES-GCM //! data-plane sealing). GameStream pairing uses: AES-128-**ECB** with **no padding**, //! SHA-256 (host appversion major ≥ 7), and RSA-PKCS1v15-SHA256 signatures. See the -//! `serverinfo + pairing` section of `docs/research/gamestream-protocol-research.json`. +//! `serverinfo + pairing` section of `design/research/gamestream-protocol-research.json`. use aes::cipher::generic_array::GenericArray; use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit}; diff --git a/crates/punktfunk-host/src/gamestream/mod.rs b/crates/punktfunk-host/src/gamestream/mod.rs index 83111ad0..083dd5cc 100644 --- a/crates/punktfunk-host/src/gamestream/mod.rs +++ b/crates/punktfunk-host/src/gamestream/mod.rs @@ -1,7 +1,7 @@ //! GameStream (P1) control plane — what a stock Moonlight/Artemis client talks to around //! the media streams: mDNS discovery, the nvhttp serverinfo + pairing HTTP(S) API, RTSP, //! and the ENet control stream. `tokio`/`axum` live here (control plane, I/O-bound — never -//! the per-frame hot path; that is `punktfunk_core`'s P1 wire codec). See `docs/gamestream-host-plan.md`. +//! the per-frame hot path; that is `punktfunk_core`'s P1 wire codec). See `design/gamestream-host-plan.md`. //! //! Status: P1.1 — mDNS `_nvstream._tcp` advertisement + `/serverinfo`. Pairing, RTSP, and //! the media streams follow (see the GameStream host task list / plan). diff --git a/crates/punktfunk-host/src/gamestream/pairing.rs b/crates/punktfunk-host/src/gamestream/pairing.rs index 3ad0ecc6..f763a015 100644 --- a/crates/punktfunk-host/src/gamestream/pairing.rs +++ b/crates/punktfunk-host/src/gamestream/pairing.rs @@ -1,7 +1,7 @@ //! The 4-phase GameStream pairing state machine (over HTTP), keyed by `uniqueid`. Proves //! both sides know the PIN (via the SHA-256(salt||pin) AES-ECB key) and own their certs //! (RSA signatures), then pins the client cert. The final `pairchallenge` happens over -//! HTTPS (handled in `nvhttp`). Byte-exact spec: `docs/research/…-research.json`. +//! HTTPS (handled in `nvhttp`). Byte-exact spec: `design/research/…-research.json`. use super::cert::ServerIdentity; use super::crypto; diff --git a/crates/punktfunk-host/src/gamestream/video.rs b/crates/punktfunk-host/src/gamestream/video.rs index 341aec12..2c644631 100644 --- a/crates/punktfunk-host/src/gamestream/video.rs +++ b/crates/punktfunk-host/src/gamestream/video.rs @@ -3,7 +3,7 @@ //! `RTP_PACKET(12, big-endian) + reserved[4] + NV_VIDEO_PACKET(16, little-endian) + payload` //! and the frame's bitstream is prefixed with an 8-byte `video_short_frame_header_t`, then //! striped into ≤4 FEC blocks of ≤255 shards. Byte-exact spec: -//! `docs/research/gamestream-protocol-research.json` (video plane). +//! `design/research/gamestream-protocol-research.json` (video plane). //! //! FEC (P1.5): each block carries `m = ⌈k·pct/100⌉` Reed–Solomon parity shards generated by //! `punktfunk_core::fec::Gf8Coder` (the nanors-compatible Cauchy GF(2⁸) coder). Crucially, RS runs diff --git a/crates/punktfunk-host/src/inject/windows/dualsense_windows.rs b/crates/punktfunk-host/src/inject/windows/dualsense_windows.rs index 67c66454..e7bda481 100644 --- a/crates/punktfunk-host/src/inject/windows/dualsense_windows.rs +++ b/crates/punktfunk-host/src/inject/windows/dualsense_windows.rs @@ -109,7 +109,7 @@ pub(super) struct SwDeviceProfile<'a> { /// `profile.instance`). The returned `HSWDEVICE` owns it — `SwDeviceClose` removes it on drop, so the /// pad appears/disappears with the session and nothing persists. /// -/// **Game-detection identity** (see `docs/windows-dualsense-game-detection.md`). `HIDD_ATTRIBUTES` +/// **Game-detection identity** (see `design/windows-dualsense-game-detection.md`). `HIDD_ATTRIBUTES` /// alone (VID/PID via the IOCTL) satisfies SDL/HIDAPI/RawInput, but a native PS5 path (libScePad- /// style raw HID) classifies the *connection type* by walking from the HID child to its parent /// (`CM_Get_Parent`) and string-matching `"USB"`/`"BTHENUM"` in that parent's diff --git a/crates/punktfunk-host/src/main.rs b/crates/punktfunk-host/src/main.rs index 026418ac..bf9643d5 100644 --- a/crates/punktfunk-host/src/main.rs +++ b/crates/punktfunk-host/src/main.rs @@ -389,7 +389,7 @@ fn real_main() -> Result<()> { } // USER-session WGC helper (Windows two-process secure-desktop design): capture the EXISTING // SudoVDA via WGC + NVENC, stream AUs on stdout to the SYSTEM host. Spawned by the host - // (CreateProcessAsUser), not run by hand. See docs/windows-secure-desktop.md. + // (CreateProcessAsUser), not run by hand. See design/windows-secure-desktop.md. #[cfg(target_os = "windows")] Some("wgc-helper") => { let get = |flag: &str| { @@ -704,7 +704,7 @@ SPIKE OPTIONS: NOTES: 'portal' needs headless Sway + xdg-desktop-portal-wlr running in this session - (see docs/linux-setup.md). 'synthetic' needs no capture session and always runs. + (see design/linux-setup.md). 'synthetic' needs no capture session and always runs. Encoded AUs are written to a playable file AND (unless --no-loopback) fed through a punktfunk_core host→client loopback that reassembles and byte-verifies each one. Both 'serve' and 'punktfunk1-host' advertise the native service over mDNS diff --git a/crates/punktfunk-host/src/mgmt.rs b/crates/punktfunk-host/src/mgmt.rs index 0c480ef3..09f1a6b3 100644 --- a/crates/punktfunk-host/src/mgmt.rs +++ b/crates/punktfunk-host/src/mgmt.rs @@ -6,7 +6,7 @@ //! The API is versioned under `/api/v1` and described by an OpenAPI 3.1 document generated //! at compile time with `utoipa` — `punktfunk-host openapi` prints it for client codegen, the //! running server serves it at `/api/v1/openapi.json` plus interactive docs at `/api/docs`, -//! and a copy is checked in at `docs/api/openapi.json` (a test fails if it drifts, like the +//! and a copy is checked in at `api/openapi.json` (a test fails if it drifts, like the //! cbindgen header). //! //! Security: binds loopback by default, serves HTTPS with the host's identity cert, and requires @@ -164,7 +164,7 @@ fn api_router_parts() -> (Router>, utoipa::openapi::OpenApi) { } /// The OpenAPI document as pretty JSON — what `punktfunk-host openapi` prints and what is -/// checked in at `docs/api/openapi.json` for client codegen. +/// checked in at `api/openapi.json` for client codegen. pub fn openapi_json() -> String { let (_, api) = api_router_parts(); let mut json = api.to_pretty_json().expect("serialize OpenAPI document"); @@ -1663,14 +1663,14 @@ mod tests { serde_json::json!([{}]) ); - let checked_in = include_str!("../../../docs/api/openapi.json"); + let checked_in = include_str!("../../../api/openapi.json"); // Compare content, not line-ending style: the generated `json` is LF (serde_json), but git // may check the file out CRLF on Windows. assert_eq!( json.trim().replace('\r', ""), checked_in.trim().replace('\r', ""), - "docs/api/openapi.json is stale — regenerate with: \ - cargo run -p punktfunk-host -- openapi > docs/api/openapi.json" + "api/openapi.json is stale — regenerate with: \ + cargo run -p punktfunk-host -- openapi > api/openapi.json" ); } diff --git a/crates/punktfunk-host/src/punktfunk1.rs b/crates/punktfunk-host/src/punktfunk1.rs index 0890bb3a..65c065a4 100644 --- a/crates/punktfunk-host/src/punktfunk1.rs +++ b/crates/punktfunk-host/src/punktfunk1.rs @@ -2221,7 +2221,7 @@ fn virtual_stream(ctx: SessionContext) -> Result<()> { // Windows two-process secure-desktop path: when the host runs as SYSTEM (required for the secure // desktop + SendInput), WGC can't activate in-process, so we capture the normal desktop via a // helper spawned in the user session and relay its AUs. (Single-process WGC/DDA is used as the - // user, and stays the path on Linux.) See docs/windows-secure-desktop.md. + // user, and stays the path on Linux.) See design/windows-secure-desktop.md. #[cfg(target_os = "windows")] if plan.topology == crate::session_plan::SessionTopology::TwoProcessRelay { return virtual_stream_relay(ctx); diff --git a/crates/punktfunk-host/src/session_plan.rs b/crates/punktfunk-host/src/session_plan.rs index f9a5b88a..f94b608f 100644 --- a/crates/punktfunk-host/src/session_plan.rs +++ b/crates/punktfunk-host/src/session_plan.rs @@ -1,7 +1,7 @@ //! `SessionPlan` — the per-session capture / topology / encoder decision, resolved **once** from //! [`HostConfig`](crate::config) (+ the handshake-negotiated bit depth) into a typed, logged value. //! -//! **Goal-1 stage 3** (`docs/windows-host-rewrite.md` §2.2): before this, the Windows session decision was +//! **Goal-1 stage 3** (`design/windows-host-rewrite.md` §2.2): before this, the Windows session decision was //! re-derived at three call sites — the capture backend inside `capture::capture_virtual_output`, the //! process topology in `punktfunk1::should_use_helper`, and the encode backend in //! `encode::windows_resolved_backend` — each reading [`config`](crate::config) independently, with no diff --git a/crates/punktfunk-host/src/session_tuning.rs b/crates/punktfunk-host/src/session_tuning.rs index e5da2c86..fcc04bae 100644 --- a/crates/punktfunk-host/src/session_tuning.rs +++ b/crates/punktfunk-host/src/session_tuning.rs @@ -9,7 +9,7 @@ //! Raw C-ABI FFI (winmm/kernel32/dwmapi/avrt) rather than the `windows` crate so it builds without //! pulling new windows-rs features. No-op on non-Windows. Per-thread effects (MMCSS, execution //! state) auto-revert at thread exit (= session end); the process-wide bits revert at process exit. -//! See `docs/host-latency-plan.md` Tier 3A. +//! See `design/host-latency-plan.md` Tier 3A. // Every `unsafe` block in this file carries a `// SAFETY:` proof; enforce it (unsafe-proof program). #![deny(clippy::undocumented_unsafe_blocks)] diff --git a/crates/punktfunk-host/src/vdisplay/windows/pf_vdisplay.rs b/crates/punktfunk-host/src/vdisplay/windows/pf_vdisplay.rs index 87d93aa5..99a5ad8d 100644 --- a/crates/punktfunk-host/src/vdisplay/windows/pf_vdisplay.rs +++ b/crates/punktfunk-host/src/vdisplay/windows/pf_vdisplay.rs @@ -6,7 +6,7 @@ //! //! Control surface: a device-interface-GUID + `CreateFileW` + `DeviceIoControl` IOCTL protocol, with //! the wire contract OWNED by [`pf_driver_proto::control`] (versioned + `#[repr(C)] Pod` structs, -//! NOT the SudoVDA ABI). No DLL, no named pipe. See `docs/windows-host-rewrite.md`. +//! NOT the SudoVDA ABI). No DLL, no named pipe. See `design/windows-host-rewrite.md`. //! //! This is a faithful clone of [`super::sudovda`] (the shipping fallback) repointed at the new driver: //! same reference-counted/lingering monitor lifecycle, same CCD isolation + active-mode forcing — those diff --git a/crates/punktfunk-host/src/windows/wgc_helper.rs b/crates/punktfunk-host/src/windows/wgc_helper.rs index a4dbf853..3ac9ef8f 100644 --- a/crates/punktfunk-host/src/windows/wgc_helper.rs +++ b/crates/punktfunk-host/src/windows/wgc_helper.rs @@ -1,5 +1,5 @@ //! USER-session WGC helper (Windows) — part of the two-process secure-desktop design -//! (docs/windows-secure-desktop.md). +//! (design/windows-secure-desktop.md). //! //! WGC won't activate under the SYSTEM account, but the host must run as SYSTEM for the secure //! desktop. So the SYSTEM host spawns THIS helper in the interactive user session diff --git a/docs-site/README.md b/docs-site/README.md index 6dce01e9..1b38dd9a 100644 --- a/docs-site/README.md +++ b/docs-site/README.md @@ -16,8 +16,8 @@ sidebar, and the landing page). It reads [`public/openapi.json`](public/openapi. ```sh # from the repo root — regenerate the spec, then copy the snapshot in: -cargo run -p punktfunk-host -- openapi > docs/api/openapi.json -cp docs/api/openapi.json docs-site/public/openapi.json +cargo run -p punktfunk-host -- openapi > api/openapi.json +cp api/openapi.json docs-site/public/openapi.json ``` ## Develop diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 655d2d80..c8838bd3 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -94,7 +94,7 @@ package_punktfunk-host() { install -Dm0644 "$R/scripts/host.env.example" "$pkgdir/usr/share/punktfunk/host.env.example" install -Dm0644 "$R/packaging/bazzite/host.env" "$pkgdir/usr/share/punktfunk/host.env.bazzite" install -Dm0644 "$R/packaging/kde/host.env" "$pkgdir/usr/share/punktfunk/host.env.kde" - install -Dm0644 "$R/docs/api/openapi.json" "$pkgdir/usr/share/punktfunk/openapi.json" + install -Dm0644 "$R/api/openapi.json" "$pkgdir/usr/share/punktfunk/openapi.json" install -Dm0644 "$R/LICENSE-MIT" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-MIT" install -Dm0644 "$R/LICENSE-APACHE" "$pkgdir/usr/share/licenses/punktfunk-host/LICENSE-APACHE" install -Dm0644 "$R/README.md" "$pkgdir/usr/share/doc/punktfunk-host/README.md" diff --git a/packaging/bazzite/README.md b/packaging/bazzite/README.md index 2e6e6a0e..0f13a175 100644 --- a/packaging/bazzite/README.md +++ b/packaging/bazzite/README.md @@ -257,7 +257,7 @@ journalctl --user -u punktfunk-host -f > ⚠️ **There is no firewall script or firewall doc in the repo.** The ports below are derived > directly from the code constants (`crates/punktfunk-host/src/gamestream/mod.rs`, `mgmt.rs`) and -> the GameStream-host port-map (`docs/gamestream-host-plan.md`). Treat the `firewall-cmd` lines as recommended-but-verified, +> the GameStream-host port-map (`design/gamestream-host-plan.md`). Treat the `firewall-cmd` lines as recommended-but-verified, > not a checked-in script. **GameStream / Moonlight ports** (fixed; Moonlight derives them from the HTTP base). These only apply diff --git a/packaging/debian/build-deb.sh b/packaging/debian/build-deb.sh index 001ab94f..b8942e7a 100755 --- a/packaging/debian/build-deb.sh +++ b/packaging/debian/build-deb.sh @@ -57,7 +57,7 @@ install -Dm0644 scripts/headless/punktfunk-sink.conf "$SHAREDIR/headless/punkt install -Dm0644 scripts/host.env.example "$SHAREDIR/host.env.example" install -Dm0644 packaging/bazzite/host.env "$SHAREDIR/host.env.bazzite" install -Dm0644 packaging/kde/host.env "$SHAREDIR/host.env.kde" -install -Dm0644 docs/api/openapi.json "$SHAREDIR/openapi.json" +install -Dm0644 api/openapi.json "$SHAREDIR/openapi.json" install -Dm0644 LICENSE-MIT "$DOCDIR/LICENSE-MIT" install -Dm0644 LICENSE-APACHE "$DOCDIR/LICENSE-APACHE" install -Dm0644 README.md "$DOCDIR/README.md" diff --git a/packaging/rpm/punktfunk.spec b/packaging/rpm/punktfunk.spec index 9206307c..fc29a8c4 100644 --- a/packaging/rpm/punktfunk.spec +++ b/packaging/rpm/punktfunk.spec @@ -224,7 +224,7 @@ install -Dm0644 packaging/kde/host.env %{buildroot}%{_datadir}/% # Bazzite KDE Desktop-mode one-shot setup (KWIN_WAYLAND_NO_PERMISSION_CHECKS + RemoteDesktop grant). install -d %{buildroot}%{_datadir}/%{name}/bazzite install -Dm0755 packaging/bazzite/kde-desktop-setup.sh %{buildroot}%{_datadir}/%{name}/bazzite/kde-desktop-setup.sh -install -Dm0644 docs/api/openapi.json %{buildroot}%{_datadir}/%{name}/openapi.json +install -Dm0644 api/openapi.json %{buildroot}%{_datadir}/%{name}/openapi.json %if %{with web} # --- web console subpackage (punktfunk-web) --- @@ -246,7 +246,7 @@ install -Dm0644 web/web.env.example %{buildroot}%{_datadir}/punkt %files %license LICENSE-MIT LICENSE-APACHE -%doc README.md docs/implementation-plan.md packaging/README.md +%doc README.md design/implementation-plan.md packaging/README.md %{_bindir}/punktfunk-host %{_udevrulesdir}/60-punktfunk.rules %{_prefix}/lib/sysctl.d/99-punktfunk-net.conf diff --git a/packaging/windows/README.md b/packaging/windows/README.md index eddd80a5..ab462ccd 100644 --- a/packaging/windows/README.md +++ b/packaging/windows/README.md @@ -76,10 +76,11 @@ read it from `%ProgramData%\punktfunk\web-password`. | `reset-pf-vdisplay.ps1` | **Dev:** recover a wedged driver — stop host → reap ghost monitor nodes → reload the adapter → start host (no reboot). See *Dev iteration* below. | | `redeploy-pf-vdisplay.ps1` | **Dev:** one-shot redeploy — (optional) build → stop host → `deploy-dev.ps1 -Install` → reload adapter → start host. | | `nvenc/nvenc.def`, `nvenc/gen-nvenc-importlib.ps1` | Synthesise `nvencodeapi.lib` for the `--features nvenc` link (llvm-dlltool / lib.exe). | +| `pf-vkhdr-layer/` | **HDR Vulkan layer** (standalone `cdylib`): lets Vulkan games (Doom: The Dark Ages, etc.) enable HDR over the virtual display by advertising the HDR surface formats the NVIDIA/AMD ICDs hide on an indirect display. Built by the packer, laid into `{app}\vklayer`, registered under `HKLM64\…\Khronos\Vulkan\ImplicitLayers` (opt-out *Install the HDR Vulkan layer* task). Self-gated on the display's HDR state. See its README. | > **Vendored driver:** pf-vdisplay is our **all-Rust IddCx** virtual display (UMDF2), built from > `packaging/windows/drivers/`. It replaced the vendored SudoVDA C++ driver — full story in -> [`docs/windows-virtual-display-rust-port.md`](../../docs/windows-virtual-display-rust-port.md). The +> [`design/windows-virtual-display-rust-port.md`](../../design/windows-virtual-display-rust-port.md). The > **signed** output (`pf_vdisplay.dll`/`.inf`/`.cat` + `punktfunk-driver.cer`; signer > `punktfunk-ds-test` — the same cert the gamepad drivers ship, Class=Display, HWID `root\pf_vdisplay`) > is checked in under `pf-vdisplay/`. To refresh it after a driver-source change, rebuild + re-sign with diff --git a/packaging/windows/drivers/Cargo.toml b/packaging/windows/drivers/Cargo.toml index a869bb37..f7dc964a 100644 --- a/packaging/windows/drivers/Cargo.toml +++ b/packaging/windows/drivers/Cargo.toml @@ -1,6 +1,6 @@ # Unified in-tree workspace for punktfunk's all-Rust UMDF drivers, on microsoft/windows-drivers-rs # (crates.io wdk/wdk-sys/wdk-build — NOT the dev-box ../../crates/wdk* path-deps). Part of the -# Windows-host rewrite (docs/windows-host-rewrite.md, M1). pf-vdisplay + the gamepad drivers move here. +# Windows-host rewrite (design/windows-host-rewrite.md, M1). pf-vdisplay + the gamepad drivers move here. # # Separate from the main cargo workspace (own [workspace] root) because driver crates are cdylibs built # with the WDK toolchain (cargo-wdk / wdk-build) on Windows only. Path-deps the shared ABI crate diff --git a/packaging/windows/drivers/pf-vdisplay/Cargo.toml b/packaging/windows/drivers/pf-vdisplay/Cargo.toml index 93287ea6..650c07d3 100644 --- a/packaging/windows/drivers/pf-vdisplay/Cargo.toml +++ b/packaging/windows/drivers/pf-vdisplay/Cargo.toml @@ -1,6 +1,6 @@ # pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite onto wdk-sys + the # owned pf-driver-proto ABI). Replaces the vendored-binding oracle at packaging/windows/vdisplay-driver/ -# (deleted once on-glass parity is reached, per docs/windows-host-rewrite.md §14 STEP 8). +# (deleted once on-glass parity is reached, per design/windows-host-rewrite.md §14 STEP 8). [package] name = "pf-vdisplay" edition.workspace = true diff --git a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs index 43297cce..033c4d31 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs @@ -137,7 +137,7 @@ pub(crate) fn adapter() -> Option { /// iGPU+dGPU box the OS may otherwise pick the iGPU to render the virtual monitor, so the host's shared /// ring textures (created on the NVENC dGPU) can't be opened → `DRV_STATUS_TEX_FAIL` → the host's 20 s /// black bail. Pinning the render adapter to the encode GPU fixes that. Unconditional — NOT the -/// SudoVDA-parity default-off branch (`docs/windows-host-rewrite.md` §2.8). Returns +/// SudoVDA-parity default-off branch (`design/windows-host-rewrite.md` §2.8). Returns /// `STATUS_NOT_FOUND` if called before the adapter exists. pub fn set_render_adapter(luid_low: u32, luid_high: i32) -> NTSTATUS { let Some(adapter) = adapter() else { diff --git a/packaging/windows/drivers/pf-vdisplay/src/control.rs b/packaging/windows/drivers/pf-vdisplay/src/control.rs index 3f9c3bcb..22c6bc8c 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/control.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/control.rs @@ -27,7 +27,7 @@ static WATCHDOG_STARTED: AtomicBool = AtomicBool::new(false); /// without a cooperative REMOVE (crash / `TerminateProcess`) left its virtual monitor + swap-chain /// worker + pooled D3D device wedged in WUDFHost until the next host start's CLEAR_ALL, and a /// not-restarted host left the orphan monitor in the desktop topology indefinitely -/// (`docs/windows-host-rewrite.md` §2.8). This thread closes that: if no IOCTL arrives for +/// (`design/windows-host-rewrite.md` §2.8). This thread closes that: if no IOCTL arrives for /// `WATCHDOG_TIMEOUT_S` while monitors exist, it departs them all. /// /// (A WDF `EvtFileClose` on the control handle would be more immediate — the plan's preferred §3.4 diff --git a/packaging/windows/drivers/pf-vdisplay/src/lib.rs b/packaging/windows/drivers/pf-vdisplay/src/lib.rs index b855ce3d..397a6667 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/lib.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/lib.rs @@ -1,5 +1,5 @@ //! pf-vdisplay — the all-Rust UMDF IddCx virtual-display driver (M1 step-2 rewrite, on wdk-sys + the -//! owned pf-driver-proto ABI). See docs/windows-host-rewrite.md §14 for the full port plan. +//! owned pf-driver-proto ABI). See design/windows-host-rewrite.md §14 for the full port plan. //! //! STEP 2: the IddCx driver SKELETON — DriverEntry → driver_add builds the full `IDD_CX_CLIENT_CONFIG` //! (14 IddCx callbacks + the PnP `EvtDeviceD0Entry`, all stubs) sized via the versioned diff --git a/scripts/bootstrap-ubuntu.sh b/scripts/bootstrap-ubuntu.sh index 8951ad01..221b92e9 100755 --- a/scripts/bootstrap-ubuntu.sh +++ b/scripts/bootstrap-ubuntu.sh @@ -205,5 +205,5 @@ cat <<'NEXT' export XDG_RUNTIME_DIR=/run/user/$(id -u) WAYLAND_DISPLAY=wayland-1 swaymsg -t get_outputs # confirm HEADLESS-1 bash scripts/headless/capture-smoke-test.sh # wf-recorder -> hevc_nvenc -> /tmp/*.mkv - 5. Then start M0 proper: see docs/linux-setup.md. + 5. Then start M0 proper: see design/linux-setup.md. NEXT diff --git a/scripts/ci/provision-windows-wdk.ps1 b/scripts/ci/provision-windows-wdk.ps1 index f6ef5aaf..7077d041 100644 --- a/scripts/ci/provision-windows-wdk.ps1 +++ b/scripts/ci/provision-windows-wdk.ps1 @@ -1,6 +1,6 @@ # Provision the Windows Driver Kit (WDK) + cargo-wdk on the self-hosted windows-amd64 runner, so the # all-Rust UMDF drivers (pf-vdisplay + the gamepad drivers, unified on microsoft/windows-drivers-rs) -# can build there. See docs/windows-host-rewrite.md (M0). +# can build there. See design/windows-host-rewrite.md (M0). # # The runner already has the base Windows SDK 10.0.26100 (um/ headers) + MSVC + LLVM + Rust, but NOT the # WDK — no km/ + wdf/ + um/iddcx headers, no inf2cat/stampinf/devgen. wdk-sys's bindgen needs those. diff --git a/scripts/headless/run-headless-sway.sh b/scripts/headless/run-headless-sway.sh index 12c05595..e9b658af 100755 --- a/scripts/headless/run-headless-sway.sh +++ b/scripts/headless/run-headless-sway.sh @@ -5,7 +5,7 @@ # ScreenCast portal (xdg-desktop-portal-wlr) and the punktfunk host share one bus. After this # is up, run `prepare-session.sh` from a second shell to set the mode + portal env. # -# Prereqs (see docs/linux-setup.md / scripts/bootstrap-ubuntu.sh): +# Prereqs (see design/linux-setup.md / scripts/bootstrap-ubuntu.sh): # - nvidia-drm.modeset=Y # - the NVIDIA GL/EGL userspace (libnvidia-gl-NNN) — provides libEGL_nvidia + the GLVND # vendor JSON; without it wlroots can't init EGL on the GPU and falls back to pixman, diff --git a/web/Dockerfile b/web/Dockerfile index 38a2dbf8..a17b2217 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,6 +1,6 @@ # punktfunk management console — TanStack Start built with Bun, served by the Nitro `bun` # preset bundle. Build context is the REPO ROOT (orval generates the API client from -# docs/api/openapi.json, referenced as ../docs/api/openapi.json from web/): +# api/openapi.json, referenced as ../api/openapi.json from web/): # # docker build -f web/Dockerfile -t punktfunk-web . # @@ -15,7 +15,7 @@ WORKDIR /repo/web COPY web/package.json web/bun.lock ./ RUN bun install --frozen-lockfile --ignore-scripts -COPY docs/api/openapi.json /repo/docs/api/openapi.json +COPY api/openapi.json /repo/api/openapi.json COPY web/ ./ # prebuild runs orval (openapi → src/api/gen); the paraglide vite plugin compiles i18n. RUN bun run build diff --git a/web/README.md b/web/README.md index 7d3234c0..be2b4238 100644 --- a/web/README.md +++ b/web/README.md @@ -1,7 +1,7 @@ # punktfunk web — management console The browser UI for the punktfunk host's **management REST API** (`crates/punktfunk-host/src/mgmt.rs`, -OpenAPI at `docs/api/openapi.json`). It shows live status, host capabilities, paired +OpenAPI at `api/openapi.json`). It shows live status, host capabilities, paired clients, the pairing-PIN flow, and session controls. Stack: **TanStack Start** (full SSR) on **Bun** via **Nitro v2** (`bun` preset) · **React @@ -88,7 +88,7 @@ Generated code is **not committed** (gitignored) — reproduced from sources: `bun install` (`prepare`) and before `dev`/`build` (`pre*` for orval; the Vite plugin compiles paraglide on dev/build). - After a management-API change, regenerate the spec on the Rust side first: - `cargo run -p punktfunk-host -- openapi > docs/api/openapi.json`, then `bun run api:gen`. + `cargo run -p punktfunk-host -- openapi > api/openapi.json`, then `bun run api:gen`. ## Layout diff --git a/web/orval.config.ts b/web/orval.config.ts index e076fb6f..fe6e396c 100644 --- a/web/orval.config.ts +++ b/web/orval.config.ts @@ -2,11 +2,11 @@ import { defineConfig } from "orval"; // Generates a typed React Query client from the host's checked-in OpenAPI document. // Regenerate after any management-API change: `pnpm api:gen` (the Rust side regenerates -// docs/api/openapi.json via `cargo run -p punktfunk-host -- openapi`). +// api/openapi.json via `cargo run -p punktfunk-host -- openapi`). export default defineConfig({ punktfunk: { input: { - target: "../docs/api/openapi.json", + target: "../api/openapi.json", }, output: { mode: "tags-split", diff --git a/web/src/styles.css b/web/src/styles.css index d5f05d5c..fae655ab 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -11,7 +11,7 @@ /* ── punktfunk brand · violet product chrome ──────────────────────────────── Two themes on one violet identity: LIGHT (lavender docs surface — the same - palette the docs/Scalar reference uses: white bg, faint-violet cards/borders, + palette the design/Scalar reference uses: white bg, faint-violet cards/borders, #6c5bf3 brand) is the :root default; DARK (the violet-tinted app-icon chrome #141019 / #1c1530, #a79ff8 brand) is the `.dark` override. The live console pins `` so it stays dark by default — removing or toggling