security-adversarial: gate CI on npm audit production findings (issue… #205
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] | |
| # Least privilege: CI only needs to read the repo. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| strategy: | |
| matrix: | |
| node: [22, 24] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: { fetch-depth: 0 } # Pinned historical codec differential oracle. | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| - run: npm ci | |
| - name: Independent source typecheck | |
| run: npm run typecheck | |
| - name: Build | |
| run: npm run build | |
| - name: ClaimReceipt production benchmark | |
| if: matrix.node == 22 | |
| run: node scripts/bench-claim-receipt.mjs | |
| - name: Lint | |
| run: npm run lint | |
| - name: Test (with coverage) | |
| run: npx vitest run --coverage | |
| - name: Governance and contract regression tests | |
| run: npm run test:governance | |
| - name: Validate Edge v1 contracts and mission plan | |
| run: npm run check:edge-contracts | |
| - name: Prohibit exposed development test services | |
| run: npm run check:development-policy | |
| - name: CLI smoke test (proves the published bin works) | |
| run: | | |
| node packages/cli/dist/bin.js version | |
| node packages/cli/dist/bin.js init --repo acme/widget --out /tmp/c.json | |
| node packages/cli/dist/bin.js compile /tmp/c.json --out /tmp/p.md | |
| test -s /tmp/p.md | |
| echo "hello" > /tmp/r.md | |
| W=$(node packages/cli/dist/bin.js witness stamp /tmp/r.md $(git rev-parse HEAD) | awk '/witness /{print $3}') | |
| node packages/cli/dist/bin.js witness verify /tmp/r.md $(git rev-parse HEAD) "$W" | |
| software-evidence: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: { fetch-depth: 0 } # Pinned historical codec differential oracle. | |
| - uses: actions/setup-node@v4 | |
| with: { node-version: 24, cache: npm } | |
| - run: npm ci --ignore-scripts | |
| - name: Full deterministic nonactuating software mission | |
| run: node scripts/ci-software-evidence.mjs | |
| - name: Preserve synthetic evidence only | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: software-evidence-${{ github.sha }} | |
| path: .dream/evidence/run-*/ | |
| include-hidden-files: true | |
| if-no-files-found: error | |
| retention-days: 14 | |
| dependency-audit: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v4 | |
| with: { node-version: 24, cache: npm } | |
| - run: npm ci --ignore-scripts | |
| - name: Audit locked dependency graph | |
| run: npm audit --audit-level=high | |
| dependency-security: | |
| # Issue #43: `npm ci` can report critical/high findings while CI stays | |
| # green, because nothing gates on the audit output. This job classifies | |
| # `npm audit --omit=dev` (the production-reachable dependency graph — | |
| # npm's own authoritative reachability computation, not re-derived here) | |
| # through `dream-machine audit-gate` and fails only on a reachable | |
| # high/critical production finding. Dev-toolchain findings (e.g. today's | |
| # vitest/vite/esbuild advisories, tracked separately in #37) are reported | |
| # by `npm audit` in the job log but never gate CI here — see ADR-0002's | |
| # "classify, don't silently trust or silently fix" precedent. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: { node-version: 20, cache: npm } | |
| - run: npm ci | |
| - name: Typecheck + build | |
| run: npm run build | |
| - name: Full audit (report only, includes dev toolchain) | |
| run: npm audit || true | |
| - name: Production-scoped audit gate (fails on reachable high/critical) | |
| run: | | |
| npm audit --omit=dev --json > /tmp/audit-prod.json || true | |
| node packages/cli/dist/bin.js audit-gate --path /tmp/audit-prod.json | |
| no-optional-deps: | |
| # ADR-150 invariant: the engine builds and tests with the optional | |
| # ruvector/RVF wasm backends ABSENT. They are declared peer-optional in | |
| # @dream-machine/memory, so a plain `npm ci` never installs them — this | |
| # default install IS the "no optional backend" scenario. (We deliberately | |
| # do NOT pass `npm ci --omit=optional`, which trips the known npm bug | |
| # npm/cli#4828 and removes rollup's platform binary that vitest needs.) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v4 | |
| with: { node-version: 24, cache: npm } | |
| - run: npm ci | |
| - name: Assert ruvector backends are NOT installed | |
| run: | | |
| test ! -d node_modules/@ruvector/wasm && test ! -d node_modules/@ruvector/rvf-wasm \ | |
| && echo "confirmed: ruvector wasm backends absent (peer-optional)" | |
| - run: npm run build | |
| - name: Memory adapter degrades gracefully without ruvector | |
| run: npx vitest run packages/memory |