supply-chain: promote cargo-deny gate to advisories+bans+sources; run… #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| # Born-green CI for PQSigner. Each job runs a command verified to pass on the | |
| # current tree (2026-06-16). The two pre-existing reds tracked in earlier | |
| # revisions of this file are now FIXED and GATED here (docs/work-todo.md §34): | |
| # * usb_hw raw-MMIO source-pin (commit 4d1d6476 — raw read/write_volatile | |
| # migrated to hw::mmio::Reg32). Gated by the `secure-tests` job (the full | |
| # sphincs-tz-secure host suite: 2076 passed / 0 failed on this tree). | |
| # * The `contracts` job was dying at COMPILE time in CI: the Foundry libs | |
| # (forge-std, solady, account-abstraction, …) are git-pinned by | |
| # contracts/smart-wallet/foundry.lock, but `lib/` is gitignored and they | |
| # are NOT git submodules — so a clean CI checkout had nothing to compile | |
| # against ("Unable to resolve imports"). The job now restores each lib at | |
| # its EXACT foundry.lock rev, then runs the full default `forge test` | |
| # (109 passed / 0 failed / 1 skipped — the skip is DeployedBytecodeReproCheck, | |
| # which only runs under the deploy profile). The committed codehash pins | |
| # (0xf1ef… verifier, 0x43c654… wallet) are canonical for exactly this | |
| # foundry.lock lib set; an extra/missing lib perturbs solc metadata and | |
| # therefore the codehash, so the restore must be lib-exact. | |
| # | |
| # Intentionally NOT in CI (kept as local/manual gates — slow + need the | |
| # patched halmos toolchain): the `deploy` foundry profile (runs=999999) and | |
| # `make -C contracts/verification verify-bytecode` (the symbolic discharge). | |
| # Under the deploy profile DeployedBytecodeReproCheck reproduces the on-chain | |
| # Base Mainnet bytecode exactly (verified locally in a clean lib-exact tree). | |
| on: | |
| push: | |
| branches: [master] | |
| # Skip CI when a push touches ONLY docs / proofs / formal-models — none of | |
| # these feed any CI job (the verify-bytecode + kontrol gates are local-only, | |
| # and contracts/verification/** is never compiled by the `contracts` job, | |
| # which builds contracts/smart-wallet). A push that ALSO changes any other | |
| # file still runs the full suite. Conserves private-repo Actions minutes. | |
| paths-ignore: | |
| - '**/*.md' | |
| - 'docs/**' | |
| - '**/*.lean' | |
| - 'contracts/verification/**' | |
| pull_request: | |
| paths-ignore: | |
| - '**/*.md' | |
| - 'docs/**' | |
| - '**/*.lean' | |
| - 'contracts/verification/**' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| invariant-gates: | |
| name: Invariant gates (#5 / #6 / #7) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Deterministic supply-chain gate (fail-hard): | |
| # * bans — invariant #5: no classical-signer crate (deny.toml [bans]) | |
| # * advisories — real CVEs in any dep (unmaintained is workspace-scoped per | |
| # deny.toml so transitive-unmaintained deps don't tripwire CI) | |
| # * sources — deps only from expected registries/remotes (typosquat / | |
| # dependency-confusion guard) | |
| # Licenses are deliberately NOT a hard gate (a compliance tripwire, not a | |
| # security property) — captured by the SBOM (`make sbom`) instead. | |
| - name: cargo deny check (advisories + bans + sources) | |
| uses: EmbarkStudios/cargo-deny-action@v2 | |
| with: | |
| command: check advisories bans sources | |
| # Invariants #5/#6/#7 (source level): the hard ERROR rules must be clean. | |
| - name: semgrep invariant rules (ERROR-level) | |
| run: | | |
| python3 -m pip install --quiet semgrep | |
| semgrep --config .semgrep/pqsigner-invariants.yml --severity ERROR --error --metrics off | |
| host-tests: | |
| name: Host unit tests (pure-logic crates) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: cargo test (pure-logic crates) | |
| run: | | |
| cargo test --locked --lib \ | |
| -p pqsigner-proto -p pqsigner-tx-core -p pqsigner-aa \ | |
| -p pqsigner-domain -p pqsigner-tx -p pqsigner-erc7730 \ | |
| -p sphincs-c10 -p pqsigner-fi | |
| secure-tests: | |
| name: Secure-world unit tests (host) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| # The secure crate host-builds with --no-default-features (the | |
| # semihosting backend is arch-gated to a host stub). This is the | |
| # `make test-unit` secure path; gates the usb_hw raw-MMIO fix. | |
| - name: cargo test (sphincs-tz-secure, host) | |
| run: | | |
| cargo test --locked -p sphincs-tz-secure \ | |
| --no-default-features \ | |
| --features mock-se,debug-log,ui-semihosting | |
| contracts: | |
| name: Contracts (forge test) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: foundry-rs/foundry-toolchain@v1 | |
| # lib/ is gitignored and the deps are git-pinned by foundry.lock (NOT | |
| # submodules), so restore each at its EXACT locked rev. The codehash | |
| # freeze tests are lib-exact: an extra/missing lib changes the | |
| # auto-generated remappings, which solc folds into the metadata hash | |
| # appended to the runtime bytecode → a different codehash. | |
| - name: Restore pinned Foundry libs (foundry.lock revs) | |
| working-directory: contracts/smart-wallet | |
| run: | | |
| set -euo pipefail | |
| declare -A URL=( | |
| [forge-std]=https://github.com/foundry-rs/forge-std | |
| [solady]=https://github.com/vectorized/solady | |
| [account-abstraction]=https://github.com/eth-infinitism/account-abstraction | |
| [openzeppelin-contracts]=https://github.com/openzeppelin/openzeppelin-contracts | |
| [p256-verifier]=https://github.com/daimo-eth/p256-verifier | |
| [safe-singleton-deployer-sol]=https://github.com/wilsoncusack/safe-singleton-deployer-sol | |
| [webauthn-sol]=https://github.com/base-org/webauthn-sol | |
| ) | |
| mkdir -p lib | |
| for key in $(jq -r 'keys[]' foundry.lock); do | |
| name="${key#lib/}" | |
| url="${URL[$name]:-}" | |
| if [ -z "$url" ]; then | |
| echo "::error::foundry.lock dep '$name' has no URL mapping in ci.yml — add it"; exit 1 | |
| fi | |
| rev=$(jq -r --arg k "$key" '.[$k].rev' foundry.lock) | |
| git clone -q "$url" "lib/$name" | |
| git -C "lib/$name" -c advice.detachedHead=false checkout -q "$rev" | |
| echo " restored $name @ $rev" | |
| done | |
| - name: forge test (default profile) | |
| working-directory: contracts/smart-wallet | |
| run: forge test |