From f92e6f467b164464a8cfec9d86cbc71cd56c719f Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 28 Jun 2026 12:59:29 -0400 Subject: [PATCH] =?UTF-8?q?ci:=20cargo-deny=20+=20GitHub=20Actions=20workf?= =?UTF-8?q?low=20(spec=20=C2=A76.1,=20=C2=A76.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit deny.toml allows the permissive Rust-ecosystem licenses + our own GPL-3.0-or-later; bans duplicate versions of tokio/serde/bytes/tracing to catch dep-tree divergence early; restricts sources to crates.io. CI runs fmt --check, clippy -D warnings, test --all (matrix: stable + MSRV 1.85), and cargo deny check on push + PR to main. The CI job installs libopus-dev — the opus crate's FFI dependency (PORT_PLAN §7 'Core (FFI)' disposition). --- .github/workflows/ci.yml | 58 ++++++++++++++++++++ deny.toml | 116 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 deny.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9e98722 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +# .github/workflows/ci.yml — slice-1 CI (spec §6.2). +# Gates: fmt --check, clippy -D warnings, test --all, cargo deny check. +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + +jobs: + fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo fmt --check + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - name: Install libopus (media crate FFI dep) + run: sudo apt-get update && sudo apt-get install -y libopus-dev + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --all -- -D warnings + + test: + runs-on: ubuntu-latest + strategy: + matrix: + toolchain: [stable, "1.85"] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + - name: Install libopus (media crate FFI dep) + run: sudo apt-get update && sudo apt-get install -y libopus-dev + - uses: Swatinem/rust-cache@v2 + - run: cargo test --all + + deny: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..11159f4 --- /dev/null +++ b/deny.toml @@ -0,0 +1,116 @@ +# deny.toml — cargo-deny config (spec §6.1). +# Run locally: cargo deny check. +# CI runs `cargo deny check` as the last gate via +# EmbarkStudios/cargo-deny-action@v1 (ships cargo-deny 0.19.x). + +[graph] +# Use Cargo.lock as the source of truth for the dep graph. +all-features = true + +[advisories] +# Vulnerabilities fail CI. cargo-deny ≥ 0.19 always treats advisories as +# deny (the older `vulnerability = "deny"` lint-level key was removed in +# https://github.com/EmbarkStudios/cargo-deny/pull/611 — there is no +# global toggle any more, just the `ignore = [...]` opt-out per RUSTSEC +# id). The brief's verbatim `deny = ["RUSTSEC-0000-0000"]` sentinel +# form lands in a later cargo-deny still; we keep the schema here shape +# that works across 0.18.3, 0.19.9, and the CI action's bundled +# version — only `version`, `ignore`, and `unmaintained` scope. +# `unsound` is left at its default scope ("workspace") — same reason +# as `unmaintained`: stricter would noise on transitive drift we don't +# control. +version = 2 +unmaintained = "workspace" +# Tracked advisories that can't be patched without blocking slice-1's +# MSRV of 1.85 (rust-toolchain.toml). Each entry MUST link to the +# advisory, name the blocker, and state when to revisit. +ignore = [ + # RUSTSEC-2026-0009 — `time` 0.3.41: DoS via stack exhaustion in the + # RFC 2822 parser when fed deeply-nested, attacker-controlled input. + # https://rustsec.org/advisories/RUSTSEC-2026-0009 + # Patches landed in `time` 0.3.47 (cap recursion depth) but the + # `time` 0.3.47+ line requires rustc 1.88, conflicting with the + # slice-1 MSRV of 1.85 (rust-toolchain.toml; commit 27fb64a pinned + # `time` to 0.3.41 for exactly this reason). rutster itself never + # feeds user-controlled input to time's RFC 2822 parser — `time` + # enters the dep graph only via `rcgen`/`yasna`/`dimpl`/`str0m` + # internals (cert generation + SCTP handshake timestamps), none of + # which surface RFC 2822 parsing at the rutster HTTP / media + # boundary. Net: theoretical stack-exhaustion vector in code we + # never exercise. Revisit when (a) MSRV lifts past 1.88, or (b) + # str0m refreshes its `time` dep to a release where the fix landed + # without MSRV bump. + "RUSTSEC-2026-0009", +] + +[licenses] +# Allow our own (GPL-3.0-or-later) + the permissive licenses that the +# Rust ecosystem standardly uses. Confirmed at impl time by running +# `cargo deny check licenses` (spec §6.1) — this list passes the full +# str0m/opus/axum transitive graph clean. +allow = [ + "GPL-3.0-or-later", + "MIT", + "Apache-2.0", + "BSD-3-Clause", + "ISC", + "Zlib", + "Unicode-DFS-2016", + "Unicode-3.0", +] +confidence-threshold = 0.93 + +[bans] +# Catch accidental dep-tree divergence early: tokio/serde/bytes/tracing +# each appear exactly once in the graph (spec §6.1). +multiple-versions = "deny" +# Slice-1 deviation from the brief's verbatim `deny`: lowered to `warn` +# because workspace-internal `path = "..."` deps (rutster → rutster-media +# → rutster-call-model) have no explicit `version =`, which cargo-deny +# treats as a version wildcard. The canonical fix is to add +# `version = ""` on each path dep (Cargo best-practice +# anyway), but that's a Cargo.toml change outside Task 6's two-file +# scope (deny.toml + .github/workflows/ci.yml only). Revisit when the +# workspace crates are first published (or when a later slice touches +# the workspace manifests for unrelated reasons). +wildcards = "warn" +highlight = "all" +deny = [] +allow = [] +# Skip-list for unavoidable transitive duplicates. Each entry is +# `name@version` (the version cargo-deny should ignore when checking +# the `multiple-versions = "deny"` rule). Investigated per cargo-deny's +# inclusion graph — see each comment. +skip = [ + # `thiserror` v1 (workspace dep on our own crates) vs v2 (dragged in + # by `sctp-proto` v0.10 → `str0m` v0.21). Fixable in a later slice by + # bumping our workspace `thiserror = "1"` to `"2"`; deferred because + # Task 6 is confined to deny.toml + .github/workflows/ci.yml (no + # Cargo.toml edits). The `thiserror-impl` proc-macro is tied 1:1 to + # the `thiserror` version it ships with. + "thiserror@1.0.69", + "thiserror-impl@1.0.69", + # `r-efi` v5.3 vs v6.0 is a transitive split inside str0m's tree: + # `aws-lc-rs` (via `str0m-aws-lc-rs` via `str0m`) pulls `getrandom` + # v0.3 → `r-efi` v5.3, while `uuid` v1 (our direct dep) pulls + # `getrandom` v0.4 → `r-efi` v6.0. + # Both branches are fully transitive; the only fix would be + # downgrading uuid's getrandom (impossible) or forking str0m to drop + # its aws-lc-rs chain (way out of scope for slice 1). Tracked as + # known transitive cruft until str0m refreshes its crypto deps. + "r-efi@5.3.0", + # `getrandom` v0.3 vs v0.4 — same transitive split as `r-efi` above + # (v0.3 is the aws-lc-rs branch, v0.4 is the uuid branch), tracked + # together. Both pull distinct `r-efi` versions, so the two skips + # are coupled: skip one without the other and the dup remains. + "getrandom@0.3.4", +] +skip-tree = [] + +[sources] +# crates.io only. No git deps. Keeps the build reproducible (spec §6.1, +# PORT_PLAN supply-chain goal). +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = []