Harden security, recovery, and release assurance #46
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 | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| # Least privilege: CI only reads the repo. `pull_request` (not | |
| # `pull_request_target`) already denies fork PRs the write token and secrets. | |
| permissions: | |
| contents: read | |
| jobs: | |
| cbor-oracle: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Carapace | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| path: Carapace | |
| - name: Install Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: "3.12" | |
| cache: pip | |
| cache-dependency-path: Carapace/requirements-cbor-vectors.txt | |
| - name: Install pinned oracle dependencies | |
| run: python -m pip install --requirement Carapace/requirements-cbor-vectors.txt | |
| - name: Check independent CBOR vectors | |
| working-directory: Carapace | |
| run: python cbor_vectors.py --check | |
| gui: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Carapace | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| path: Carapace | |
| - name: Install pinned Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24.18.0 | |
| cache: npm | |
| cache-dependency-path: Carapace/gui/package-lock.json | |
| - name: Install pinned npm | |
| run: npm install --global npm@11.16.0 | |
| - name: Verify Node.js tools | |
| run: | | |
| test "$(node --version)" = "v24.18.0" | |
| test "$(npm --version)" = "11.16.0" | |
| - name: Install locked GUI dependencies | |
| working-directory: Carapace/gui | |
| run: npm ci | |
| - name: Check GUI source | |
| working-directory: Carapace/gui | |
| run: npm run check | |
| - name: Test GUI contracts | |
| working-directory: Carapace/gui | |
| run: npm test | |
| - name: Install pinned browser runtime | |
| working-directory: Carapace/gui | |
| run: npx playwright install --with-deps chromium | |
| - name: Test GUI in a real browser | |
| working-directory: Carapace/gui | |
| run: npm run test:browser | |
| - name: Build embedded GUI | |
| working-directory: Carapace/gui | |
| run: npm run build | |
| - name: Verify embedded GUI is current | |
| working-directory: Carapace | |
| run: git diff --exit-code -- crates/carapace-api/static | |
| supply-chain: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Carapace | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| path: Carapace | |
| - name: Read pinned Chela revision | |
| id: chela-pin | |
| shell: bash | |
| run: | | |
| revision="$(tr -d '\r\n' < Carapace/chela-revision.txt)" | |
| [[ "$revision" =~ ^[0-9a-f]{40}$ ]] | |
| echo "revision=$revision" >> "$GITHUB_OUTPUT" | |
| - name: Checkout chela | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| repository: SecretSplitKit/Chela | |
| ref: ${{ steps.chela-pin.outputs.revision }} | |
| token: ${{ secrets.CHELA_CHECKOUT_TOKEN || github.token }} | |
| path: chela | |
| - name: Check tracked files for secrets | |
| working-directory: Carapace | |
| run: scripts/check-tracked-secrets.sh | |
| - name: Check supply-chain configuration | |
| working-directory: Carapace | |
| run: scripts/check-supply-chain-config.sh | |
| - name: Check dependency licenses, sources, bans, and advisories | |
| uses: EmbarkStudios/cargo-deny-action@d755fbddac377c2d538f556dd0f9c7728c7f73e4 # v2.0.14 | |
| with: | |
| rust-version: 1.95.0 | |
| manifest-path: Carapace/Cargo.toml | |
| arguments: --all-features | |
| command-arguments: --config /github/workspace/Carapace/deny.toml | |
| - name: Prepare lock file for cargo audit | |
| run: cp Carapace/Cargo.lock Cargo.lock | |
| - name: Audit Rust dependencies | |
| uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 # v2.0.0 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| test: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-24.04, ubuntu-24.04-arm, macos-15-intel, macos-15, windows-2025, windows-11-arm] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| # Carapace depends on chela-engine/chela-bip39/chela-share via a path | |
| # dependency (`../../../chela/...` from crates/carapace-recovery), so | |
| # both repos must land as siblings under the same parent directory. | |
| - name: Checkout Carapace | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| path: Carapace | |
| - name: Read pinned Chela revision | |
| id: chela-pin | |
| shell: bash | |
| run: | | |
| revision="$(tr -d '\r\n' < Carapace/chela-revision.txt)" | |
| [[ "$revision" =~ ^[0-9a-f]{40}$ ]] | |
| echo "revision=$revision" >> "$GITHUB_OUTPUT" | |
| echo "CHELA_REV=$revision" >> "$GITHUB_ENV" | |
| - name: Checkout chela | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 | |
| with: | |
| repository: SecretSplitKit/Chela | |
| ref: ${{ steps.chela-pin.outputs.revision }} | |
| # The default GITHUB_TOKEN is scoped to this repository. Use the | |
| # optional token if Chela becomes private. | |
| token: ${{ secrets.CHELA_CHECKOUT_TOKEN || github.token }} | |
| path: chela | |
| - name: Verify Chela revision | |
| shell: bash | |
| run: | | |
| actual_revision="$(git -C chela rev-parse HEAD)" | |
| test "$actual_revision" = "$CHELA_REV" | |
| - name: Check release workflow | |
| shell: bash | |
| working-directory: Carapace | |
| run: scripts/check-release-workflow.sh | |
| - name: Check shared restore layout | |
| shell: bash | |
| working-directory: Carapace | |
| run: scripts/check-restore-layout.sh | |
| - name: Check requirement-to-test inventory | |
| shell: bash | |
| working-directory: Carapace | |
| run: scripts/check-test-inventory.sh | |
| - name: Check operational log sources | |
| shell: bash | |
| working-directory: Carapace | |
| run: scripts/check-operational-logs.sh | |
| - name: Check state fixture coverage and integrity | |
| shell: bash | |
| working-directory: Carapace | |
| run: scripts/state-fixtures.sh check | |
| - name: Install fuzz toolchain | |
| if: runner.os == 'Linux' | |
| uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| with: | |
| toolchain: nightly-2026-06-01 | |
| - name: Run all fuzz targets with bounded budgets | |
| shell: bash | |
| working-directory: Carapace | |
| run: | | |
| if [[ "$RUNNER_OS" == "Linux" ]]; then | |
| cargo install cargo-fuzz --version 0.13.1 --locked | |
| scripts/check-fuzz-targets.sh --smoke | |
| else | |
| scripts/check-fuzz-targets.sh | |
| fi | |
| - name: Install pinned Rust | |
| uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | |
| with: | |
| toolchain: 1.95.0 | |
| components: clippy, rustfmt | |
| - name: Cache cargo | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| Carapace/target | |
| key: ${{ matrix.os }}-cargo-${{ hashFiles('Carapace/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ matrix.os }}-cargo- | |
| - name: cargo fmt --check | |
| working-directory: Carapace | |
| run: cargo fmt --all -- --check | |
| - name: cargo clippy | |
| working-directory: Carapace | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| - name: cargo test | |
| working-directory: Carapace | |
| run: cargo test --workspace --locked |