Supply Chain¶
The supply-chain model is builder-first, and the CI/CD toolchain is explicitly back on Wolfi.
What the Builder Owns Now¶
The custom GitHub Action builder image is the repository trust root for:
a digest-pinned Chainguard Wolfi base image
Wolfi
rust-1.95=1.95.0-r0pinned
toxandsphinx-rustdocgenRust toolchain installation, including
rustfmtand Clippy from Wolfi packagesOpenSSL development headers from Wolfi packages
Xvfb and the Xlib runtime libraries required for GUI screenshot smoke tests
Sphinx and Python docs tooling
local scanner CLIs used by the deeper release-candidate gates, including
cargo-audit,semgrep,osv-scanner,syft, andtrivya pinned RustSec advisory DB checkout used by builder-emulated
cargo audit --no-fetchcargobuild / test / clippy / fmt runsdocs-site builds from the repository root
vendored Cargo dependency resolution
Remote Rust CI invokes the same make ci target used locally, inside this builder.
Linux release validation, published-release surface verification, and downloaded
asset smoke verification also run through the same builder instead of installing
ad hoc packages onto the Ubuntu runner.
The Dependency Scan job in .github/workflows/ci.yml runs on pull requests and
workflow_dispatch (not on push) and executes cargo run -p xtask -- dependency-scan
inside the same builder image. That subcommand runs cargo audit --no-fetch --stale
and the OSV lockfile actionable-findings check the local scanner subset also uses,
so pull requests get dependency/advisory coverage in remote CI instead of only
through the local-only make quality / make quality-emulate scanner gates.
Semgrep, cargo-deny, Syft, and Trivy remain local/builder-emulate-only scanners.
Allowed (Pinned-but-Visible) OSV Advisories¶
check_osv_actionable_findings in xtask/src/main.rs treats an osv-scanner finding as
actionable (scan failure) unless it matches an entry in the ALLOWED_OSV_ADVISORIES table.
That table exists for advisories that have a fixed upstream release, but where this workspace
cannot reach the fix because a transitive dependency’s own Cargo.toml pins the affected
crate below the fixed version, and no newer release of that transitive dependency exists yet.
This is distinct from the existing unmaintained-with-no-fix path (advisories with
informational = "unmaintained" and no fixed version anywhere in the OSV record), which are
always printed as warnings and never need an allowlist entry.
Each ALLOWED_OSV_ADVISORIES entry records:
the crate name and advisory id it applies to
reason: why the fix is unreachable viacargo update -p/--precisetoday, plus why the vulnerable code path is not actually exercised in this repo’s usagerevisit_condition: the exact upstream condition (e.g. “wayland-scanner releases with quick-xml >= 0.41.0”) that should prompt removing the entry and re-runningcargo update -p <crate>
An allowed advisory is never silenced: dependency-scan still prints it as a WARN osv-scanner: ... has allowed advisory ... line carrying the reason and revisit condition, and
it is excluded from the finding list that would otherwise fail the scan. Currently allowed:
quick-xml/RUSTSEC-2026-0194andRUSTSEC-2026-0195: pinned to"^0.39"bywayland-scannerv0.31.10’s own manifest (reached viaparanoid-gui -> slint -> i-slint-backend-winit -> softbuffer -> wayland-client -> wayland-scanner), which only parses repo-local Wayland protocol XML at build time, never attacker-controlled input. Revisit when awayland-scannerrelease raises itsquick-xmlrequirement to>= 0.41.0.
Historical CI Rigor Baseline¶
The older C/WASM GitHub Pages line carried a stricter release discipline than the Rust-native branch had drifted into: native CMake/CTest, WASM validation and export/import checks, Playwright E2E, CodeQL, SonarCloud, ShellCheck, hallucination checks, supply-chain verification, and a Wolfi/melange/apko release path.
The Rust-native product no longer ships the browser app or JavaScript
secret-handling surface, so those exact gates are not copied forward blindly. The
replacement standard is that remote CI must be at least as strict for the current
surface: full local make ci in Wolfi, docs and link validation, GUI/TUI/vault
e2e coverage, release payload inspection, published-release verification,
attestation checks, and repo-owned supply-chain scripts.
What It No Longer Builds¶
the retired interactive browser app
WebAssembly artifacts
GitHub Pages site zips pulled from releases
Release Outputs¶
The release pipeline now focuses on:
native CLI and GUI archives
macOS GUI
.dmgpackagesLinux
.debpackages for both binarieschecksums
provenance / attestations
package-manager metadata
repo-owned package metadata
Before attestation, the release workflow now validates:
per-platform archive smoke tests
macOS GUI
.dmgpayload validation and host smoke testsDebian package payload validation and Linux smoke tests for
.debartifacts in the Wolfi builderaggregate checksums
Homebrew / Scoop / Chocolatey manifest generation
the docs-hosted
install.shflow against a local artifact serverthe checked-in release-validation scripts instead of workflow-only inline shell
GitHub Pages is rebuilt directly from main using the Sphinx docs tree instead of downloading a site zip from a release artifact.
Branch Protection Discipline¶
The repository now carries scripts/verify_branch_protection.sh plus make verify-branch-protection so operators can detect stale required-check policies before they block a merge. This is a manual or authenticated check because branch protection lives in GitHub configuration rather than the Git tree.
Cargo Dependency Discipline¶
Cargo.lockis committed and release-aware.Cargo dependencies are vendored under
vendor/.Workspace Cargo commands run with
--locked --frozen --offlineinmakeand CI.Dependabot remains enabled for GitHub Actions only. Cargo dependency PRs are not automated through Dependabot because the repository’s
.cargo/config.tomlreplacescrates.iowith the checked-invendor/tree, and Dependabot’s Cargo updater does not maintain vendored Cargo source directories. Cargo dependency updates must therefore be maintainer-driven: updateCargo.toml/Cargo.lock, refresh the affected vendored crates, preserve.cargo-checksum.json, and prove the result with locked/frozen/offline Cargo gates before PR.make verify-deepruns Rust-nativextaskchecks for offline metadata, dependency source and license policy, repo-owned shell linting, Python syntax checks for the existing docs/test harness scripts, and tracked-file secret scanning.make qualityis the local release-candidate gate: it runsverify-deep, the enforced local scanner subset,ci, and the host-supported GUI e2e harness before remote CI is treated as confirmation. It also requires the local security scanner stack to be installed.make quality-emulateruns the same release-candidate posture inside the custom Wolfi builder where possible:verify-deep, the builder-owned scanner subset,ci, and the Linux GUI visual regression harness. Shell scripts are parsed withbash -nthere when the Wolfi package set does not provide ShellCheck.deny.tomlrecords the local dependency license/source policy forcargo-deny.scripts/hallucination_check.shverifies math/security invariants inparanoid-core.scripts/supply_chain_verify.shverifies vendoring, workflow pinning, and release prerequisites.scripts/security_assurance_gate.pyverifies the claim-led PR assurance protocol wiring.Release packaging lives in repo-owned scripts instead of workflow-only inline shell.
Scanner Toolchain Pin Manifest¶
Scanner and tooling updates are tracked in supply-chain/scanner-toolchain.env. That manifest is
the source of truth for:
Wolfi apk scanner versions installed into the repository builder (
cargo-audit,semgrep,osv-scanner,syft, andtrivy)the RustSec advisory DB revision checked out into the builder for no-fetch cargo-audit runs
the pinned
github/codeql-actionversion and commit SHA used by workflow CodeQL jobshost-local scanner tools that
xtaskmust continue to discover formake verify-deep/make qualityhost-local scanner versions for ShellCheck, cargo-deny, cargo-audit, cargo-vet, and the CodeQL CLI when
make qualityenables strict local-tool checking
scripts/supply_chain_verify.sh sources the manifest and fails if the Dockerfile, workflow CodeQL
references, or xtask local-tool visibility checks drift from it. Updating a scanner therefore
requires changing the manifest, updating the corresponding builder, workflow reference, or host
version check, and rerunning the assurance gate plus make quality or make quality-emulate
rather than letting the runner or workstation resolve a new scanner version implicitly.