Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,25 @@ jobs:
if: always()
working-directory: infra/compose
run: docker compose down -v

dependency-audit:
runs-on: ubuntu-latest
# E10: fail on high/critical production advisories only. Policy:
# docs/ops/dependency-audit.md
steps:
- uses: actions/checkout@v7

- uses: pnpm/action-setup@v6
with:
version: 9.15.0

- uses: actions/setup-node@v7
with:
node-version: "20"
cache: "pnpm"

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: pnpm audit (prod, high+)
run: pnpm audit:ci
51 changes: 51 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Weekly Monday 06:30 UTC
- cron: "30 6 * * 1"

concurrency:
group: codeql-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze JavaScript / TypeScript
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
# Required once GitHub code scanning is enabled on the repo (Settings →
# Code security). Until then we keep upload:never so analysis still gates CI.
security-events: write

steps:
- uses: actions/checkout@v7

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
build-mode: none

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:javascript-typescript"
# Private repos without Code Scanning / GHAS cannot upload SARIF to
# the Security tab. Analysis still runs and fails the job on query
# errors. Enable code scanning in repo settings to switch to upload.
upload: never

- name: Upload SARIF artifact
uses: actions/upload-artifact@v4
with:
name: codeql-javascript-typescript
path: ${{ runner.temp }}/codeql/javascript/results/*.sarif
if-no-files-found: ignore
retention-days: 14
20 changes: 20 additions & 0 deletions docs/ops/codeql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# CodeQL (E10)

Workflow: `.github/workflows/codeql.yml` — runs on `main` PRs/pushes + weekly.

## Behavior

- Analyzes JavaScript/TypeScript (`build-mode: none`).
- **Upload to GitHub Code Scanning** is `never` until code scanning is enabled on this private repository (Settings → Code security and analysis → Code scanning). Without that, SARIF upload fails the job even when analysis succeeds.
- SARIF is retained as a workflow artifact (`codeql-javascript-typescript`) for 14 days.

## Enabling Security-tab upload

1. Repo **Settings → Code security** → enable **Code scanning**.
2. Change `upload: never` → `upload: always` (or remove the `upload` key) in `.github/workflows/codeql.yml`.
3. Keep `permissions.security-events: write`.

## Related

- Dependency audit gate: [`dependency-audit.md`](./dependency-audit.md)
- Dependabot: `.github/dependabot.yml`
45 changes: 45 additions & 0 deletions docs/ops/dependency-audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Dependency audit policy (E10)

**Goal:** catch high/critical production advisories in CI without papering over real risk.

## CI gate

| Command | When | Fail on |
|---------|------|---------|
| `pnpm audit:ci` → `pnpm audit --prod --audit-level=high` | Every PR (`ci.yml` job `dependency-audit`) | **high** and **critical** only |

Moderate / low findings are **visible** in local `pnpm audit --prod` but do not fail the gate. Prefer fixing them via Dependabot (already weekly) rather than ignoring.

## Allowlist (carefully)

If a high/critical advisory cannot be fixed immediately (no patch, or only via a breaking major):

1. Prefer `pnpm.overrides` / dependency bump that removes the vulnerable path.
2. Only if blocked: add the **CVE / GHSA id** under `pnpm.auditConfig.ignoreCves` in the **root** `package.json`, with an inline comment in `docs/ops/dependency-audit.md` stating:
- advisory id + package
- why production risk is accepted (or not reachable)
- owner + review-by date
3. Never ignore an advisory “to make CI green” without that note.
4. Revisit allowlisted entries every Dependabot cycle; delete when fixed.

Empty allowlist is the default. Do **not** copy npm’s `--force` / blanket ignore.

Example shape (comments belong in this doc, not in `package.json`):

```json
{
"pnpm": {
"auditConfig": {
"ignoreCves": ["CVE-YYYY-NNNNN"]
}
}
}
```

Document each ignored id in this file with package, rationale, owner, and review-by date.

## Related

- Dependabot: `.github/dependabot.yml` (weekly npm + Actions minors/patches)
- CodeQL: `.github/workflows/codeql.yml` (SAST on default branch + PRs) — see [`codeql.md`](./codeql.md)
- Local: `pnpm audit --prod` (all severities)
5 changes: 4 additions & 1 deletion infra/ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ This folder is reserved for reusable CI helper scripts if they outgrow the workf
| `compose-smoke-test` | Infra startup | Compose Postgres + Redis + Qdrant healthy |
| `integration-test` | Product path (D5.4 e2e) | `pnpm build` → migrate → `pnpm test:integration` |
| | Golden eval (D5.2) | `pnpm test:eval` (hit@3 ≥80%, citation 100%) |
| `dependency-audit` | E10 supply-chain | `pnpm audit:ci` (prod, fail on high/critical) — see [`docs/ops/dependency-audit.md`](../../docs/ops/dependency-audit.md) |

All of the above use the checked-in sample-repo fixture + fake OpenAI-compatible provider — **no** GitHub/Ollama/cloud network on the required path (₹0 / offline CI).
**Also on PRs / main (separate workflow):** CodeQL JavaScript/TypeScript — `.github/workflows/codeql.yml`.

All product-path jobs above use the checked-in sample-repo fixture + fake OpenAI-compatible provider — **no** GitHub/Ollama/cloud network on that path (₹0 / offline CI). Dependency audit and CodeQL need network for the advisory DB / CodeQL pack download.

**Not in CI:** `codeoracle replay` against a product/dogfood index (needs a ready repo + real embeddings). That is an ops gate — see [`test/replay/README.md`](../../test/replay/README.md) and [`infra/dogfood/README.md`](../dogfood/README.md).

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"test:golden": "vitest run --config test/golden-queries/vitest.config.ts",
"test:eval": "INTEGRATION_TEST=1 vitest run --config test/golden-queries/eval.vitest.config.ts",
"test:retrieval-gates": "pnpm --filter @codeoracle/core-domain test -- test/absolute-score-floor.test.ts test/secret-path-class.test.ts && pnpm --filter @codeoracle/retrieval exec vitest run test/search-codebase.test.ts test/find-decision.test.ts test/explain-file.test.ts && pnpm --filter @codeoracle/cli test -- src/replay/score.test.ts",
"audit:ci": "pnpm audit --prod --audit-level=high",
"typecheck:e2e": "tsc -p test/e2e/tsconfig.json",
"typecheck:golden": "tsc -p test/golden-queries/tsconfig.json",
"fixture:sample-repo:tree": "pnpm --filter @codeoracle/worker exec tsx ../../test/fixtures/sample-repo/write-tree-cli.ts",
Expand Down
Loading