# Contributing to Punktfunk Thanks for your interest in contributing! ## Licensing of contributions (inbound = outbound) Punktfunk is dual-licensed under **MIT OR Apache-2.0**. > Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in > the work by you, as defined in the Apache-2.0 license, shall be dual licensed as **MIT OR > Apache-2.0**, without any additional terms or conditions. By opening a pull request you agree to license your contribution under these terms. This is the standard Rust-ecosystem "inbound = outbound" model; it keeps the project's licensing unambiguous (including the Apache-2.0 §5 contributor patent grant) and any future relicensing clean. You retain the copyright to your contributions. ### Do not paste copyleft (or otherwise incompatibly-licensed) code The single thing that could poison the permissive license is **copied source from a copyleft project**. Several adjacent projects (Sunshine, Apollo, Moonlight) are GPL-3.0. You may study them and reimplement a *technique*, protocol, or wire format — those are not copyrightable — but **never paste their code**, and do not translate a GPL implementation line-by-line. When a comment credits prior art, make clear it is an independent reimplementation, not a copy. The same applies to any third party's code under a license incompatible with MIT/Apache. If you add a new third-party dependency, it must be permissive (MIT / Apache-2.0 / BSD / ISC / Zlib / Unicode-3.0 / etc.). `about.toml` holds the accepted-license allow-list; regenerate the attribution file with `scripts/gen-third-party-notices.sh` when the dependency tree changes. ## Prerequisites The Rust toolchain is **pinned exactly** in `rust-toolchain.toml`; rustup installs it for you the first time you build, so don't override it — a different rustc reformats files nobody touched. The workspace links real system libraries, so a bare `cargo build --workspace` fails on a stock machine. The authoritative list is what CI installs, in `ci/rust-ci.Dockerfile` — on **Ubuntu 26.04**, which is what gets you FFmpeg 8: ```sh sudo apt install build-essential clang libclang-dev pkg-config cmake \ libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev libavdevice-dev \ libpipewire-0.3-dev libopus-dev libwayland-dev libxkbcommon-dev \ libgl-dev libegl-dev libgbm-dev \ libgtk-4-dev libadwaita-1-dev libsdl3-dev \ libvulkan-dev ``` (The last two groups are the Linux client shell and `pf-ffvk`; skip them only if you never build those crates. `scripts/bootstrap-ubuntu.sh` sets up an Ubuntu **capture-test host** — NVIDIA, Sway, PipeWire — and is not a substitute for the list above.) ## Before you push Enable the repo git hooks once per clone — they run the exact rustfmt gates CI runs (main workspace + the UMDF driver workspace) on every commit and push, so a push can never fail CI on formatting alone: ```sh git config core.hooksPath scripts/git-hooks ``` Then the usual full pass. Use `--locked` as CI does — otherwise a silent `Cargo.lock` update can pass locally and fail CI: ```sh cargo fmt --all --check cargo clippy --workspace --all-targets --locked -- -D warnings cargo test --workspace --locked ``` Two more gates that only apply to some changes: - **Touched `web/` or `docs-site/`?** CI builds and typechecks both. Run, in that directory: ```sh bun install && bun run build && bun run lint ``` Build first — it generates the API client / MDX typegen that the typecheck imports. - **Touched Windows- or Linux-gated code from another OS?** `scripts/xcheck.sh windows` (or `linux`) type-checks and lints that platform's `#[cfg(target_os = …)]` code in about a second, instead of waiting for the CI job that compiles it. Generated artifacts are checked in. `include/punktfunk_core.h` (cbindgen) is regenerated by the build and CI fails if the committed copy drifts. `api/openapi.json` is **not** gated — nothing in CI regenerates or diffs it, so regenerate and commit it yourself whenever you touch the management API, and copy the snapshot the docs site serves: ```sh cargo run -p punktfunk-host -- openapi > api/openapi.json cp api/openapi.json docs-site/public/openapi.json ``` Match the surrounding code's comment density and naming. Commit messages end with the `Co-Authored-By` trailer (see `git log`). See the [README's Build & test section](README.md#build--test-from-source) for the extra dev commands (the FEC loss harness, the standalone C-ABI proof) and [Design invariants](README.md#design-invariants) for the rules a change is expected to hold to, and the [docs site](https://docs.punktfunk.unom.io) for architecture and per-platform guides.