diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fad714b66..4b6ad8f81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ permissions: env: NEXT_PUBLIC_SUPABASE_URL: https://sjrfecxgysukkwxsowpy.supabase.co NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: placeholder-ci-anon-key + SUPABASE_CLI_VERSION: 2.108.0 jobs: changes: @@ -305,15 +306,16 @@ jobs: - name: Setup Supabase CLI uses: supabase/setup-cli@v3 with: - version: latest + version: ${{ env.SUPABASE_CLI_VERSION }} - name: Restore Supabase Docker image cache + id: supabase-docker-cache uses: actions/cache@v6 with: path: /tmp/supabase-docker-cache - key: supabase-docker-${{ runner.os }}-${{ hashFiles('supabase/config.toml') }} + key: supabase-docker-${{ runner.os }}-cli-${{ env.SUPABASE_CLI_VERSION }}-${{ hashFiles('supabase/config.toml') }} restore-keys: | - supabase-docker-${{ runner.os }}- + supabase-docker-${{ runner.os }}-cli-${{ env.SUPABASE_CLI_VERSION }}- - name: Load cached Supabase Docker images run: | @@ -328,7 +330,7 @@ jobs: run: supabase db reset - name: Save Supabase Docker images - if: always() + if: success() && steps.supabase-docker-cache.outputs.cache-hit != 'true' continue-on-error: true run: | mkdir -p /tmp/supabase-docker-cache diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 183f81e2f..cc3907d73 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -15,15 +15,16 @@ permissions: contents: read jobs: - # Static application security testing. Semgrep is used instead of CodeQL + # Advisory static application security testing. Semgrep is used instead of CodeQL # because this repository is private without GitHub Advanced Security, so the - # code-scanning SARIF upload CodeQL relies on is unavailable; a build-failing - # scan mirrors the existing `npm audit` gate in ci.yml. The document parsers + # code-scanning SARIF upload CodeQL relies on is unavailable. The document parsers # (pdf-parse, pdfjs-dist, mammoth, exceljs, jszip) and the answer/ingestion - # paths process untrusted uploaded documents, so ERROR-severity findings block - # the merge. Runs OSS-engine only — no Semgrep account or token required. + # paths process untrusted uploaded documents, so ERROR-severity findings remain + # visible without making mutable registry rules a required merge dependency. + # Runs OSS-engine only — no Semgrep account or token required. semgrep: name: Semgrep + continue-on-error: true runs-on: ubuntu-24.04 timeout-minutes: 15 container: @@ -36,9 +37,9 @@ jobs: - name: Semgrep scan # --error fails the job on any ERROR-severity finding; --oss-only keeps - # it token-free; --metrics off sends no telemetry. Rulesets are pinned by - # name (no network `auto` inference). Secrets are covered by Gitleaks in - # secret-scan.yml, so no p/secrets here. Scope is source only. + # it token-free; --metrics off sends no telemetry. Named registry rules + # remain advisory because they can change independently of this repository. + # Secrets are covered by Gitleaks in secret-scan.yml, so no p/secrets here. run: > semgrep scan --error @@ -49,4 +50,4 @@ jobs: --config p/javascript --config p/react --config p/nodejs - src worker scripts + src worker scripts supabase/functions diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index e949aaeb5..53848d209 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -18,18 +18,19 @@ Use this ledger to prevent repeated branch and PR reviews when the reviewed HEAD ## Review Records -| Date | Branch or ref | Reviewed HEAD | Scope | Outcome | Checks | -| ---------- | -------------------------------------- | ---------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-07-09 | example/branch | abc1234 | branch-cleanup | Example: already merged into `main`; no unique patch content. | `git log --right-only --cherry-pick main...example/branch`; `git diff --name-status main...example/branch` | -| 2026-07-10 | codex/pr-testing-streamlining | 155c801cd58f797037d8aaa8b885405a1c599249 | working-tree diff: PR testing streamlining | Changes requested: 2 P1 clinical-gate defects and 7 P2/P3 scope, local parity, and UI-process defects. | `npm run check:ci-scope`; `npm run check:github-actions`; `npm run check:codex-autofix-workflow`; `npm run eval:rag:offline`; `npm run test:e2e:critical`; targeted scope classifications; `git diff --check` | -| 2026-07-10 | codex/pr-testing-streamlining | 155c801cd58f797037d8aaa8b885405a1c599249 | working-tree remediation review | All recorded P1-P3 findings fixed; no remaining high-confidence issue in the changed scope. | `npm run verify:cheap`; `npm run verify:pr-local`; `npm run eval:rag:offline`; `npm run test:e2e:critical`; `npm run test:e2e:advisory`; CI YAML parse; scope/action/Codex guards; `git diff --check` | -| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-flow | Fixed exact connector authorization, trusted-marker deduplication, and strict self-trigger matching; added regression coverage. | `npm run check:codex-autofix-workflow`; focused Vitest (4 passed); `npm run verify:cheap` pre-test stages passed before tool timeout; `npm test` (1,415 passed, 1 skipped); focused Prettier check; `npm run check:github-actions` | -| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-flow-followup | Fixed untrusted workflow-level concurrency interference and migrated the bridge from the Node 20 action runtime to `actions/github-script@v9`; added direct embedded-script execution coverage. | Focused Vitest (13 passed); targeted ESLint; `tsc --noEmit`; `npm run check:codex-autofix-workflow`; `npm run check:github-actions`; focused Prettier check; `git diff --check` | -| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-residual-fixes | Replaced one-shot PR deduplication with a three-cycle head-SHA cap, made comment permission failures fail visibly, and pinned `github-script` v9.0.0 to its verified immutable commit. | TDD red run (7 expected failures); focused Vitest green run (15 passed); `npm run verify:cheap` (152 files passed, 1 skipped; 1,426 tests passed, 1 skipped); focused Prettier check; `git diff --check`; official `git ls-remote` tag verification | -| 2026-07-10 | codex/architecture-review-fixes | 648abfa3f7c91395b5eeca543f70e0b6ea59e9e0 | architecture-review | Seven findings fixed in the working tree: three runtime cycles, unbounded owner caches, a client/server env boundary breach, reversed runtime-to-scripts ownership, and architecture-doc drift. | `npm run test -- tests/architecture-boundaries.test.ts tests/bounded-ttl-cache.test.ts tests/rag-score.test.ts tests/rag-cache-utils.test.ts tests/rag-cache-invalidation.test.ts tests/evidence-panels.test.ts tests/clinical-dashboard-merge-artifacts.test.ts`; `npm run verify:cheap`; `npm run check:production-readiness:ci` | -| 2026-07-10 | codex/architecture-review-fixes | 648abfa3f7c91395b5eeca543f70e0b6ea59e9e0 | frontend-architecture-review | Shared cycle/env findings confirmed and fixed; three additional findings fixed for defeated lazy boundaries, duplicate shell/dashboard subscriptions, and unstable search-context values. | `npm run test -- tests/architecture-boundaries.test.ts tests/evidence-panels.test.ts tests/clinical-dashboard-merge-artifacts.test.ts`; `npm run verify:cheap`; UI gate deferred pending explicit local-API approval | -| 2026-07-11 | codex/architecture-review-integration | b45df727b29aad8ba4ec5d4e96d1f0599d7dad8a | branch-integration-review | Replayed the reviewed architecture fixes onto current `origin/main`; preserved current CI/autofix history and found no new high-confidence defect in the integrated diff. | `npm run check:runtime`; `npm run check:github-actions`; `npm run sitemap:check`; `npm run lint`; `npm run typecheck`; focused Vitest (24 passed); full Vitest with `--testTimeout=30000` (1,433 passed, 1 skipped); `git diff --check` | -| 2026-07-10 | codex/quality-testing-typescript-fixes | 648abfa3f | code-quality + testing + TypeScript | 17 confirmed P2/P3 issues fixed; no P0/P1 findings; residual large-module complexity noted. | Focused Vitest and Playwright; full Vitest 1427 passed/1 skipped; coverage; lint; typecheck; production-readiness CI | -| 2026-07-11 | codex/quality-review-integration | d3fcef8bbc9ab12b929771421b532c1ed8b7e1e7 | branch-integration-review | Replayed the quality, testing, and TypeScript fixes onto current `origin/main` and consolidated the stronger standalone auth callback coverage into this branch. | Changed-file Prettier; focused Vitest (5 files, 23 tests); `git diff --check`; original branch full Vitest/coverage/lint/typecheck and targeted Chromium evidence retained | -| 2026-07-11 | codex/architecture-review-integration | 665103250ccc33b5870862b8d8467607a1ae5d23 | coderabbit-followup | Fixed POSIX project-root identity collisions and closed dynamic-import and self-cycle gaps in the architecture regression guard. | Local-server Vitest passed; architecture-boundaries Vitest passed (6 tests); `npm run typecheck`; focused Prettier; `git diff --check` | -| 2026-07-11 | codex/architecture-review-followup | f5deaaee98864f1d32c1060ae14966a4f5975872 | coderabbit-test-followup | Removed probabilistic no-collision assertions from the local identity test and replaced them with deterministic normalization, repeatability, ID-shape, and port-range checks. | Local-server Vitest (2 passed); focused Prettier; `git diff --check`; hosted CI/SAST/Secret Scan passed on the reviewed head | +| Date | Branch or ref | Reviewed HEAD | Scope | Outcome | Checks | +| ---------- | -------------------------------------- | ---------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-07-09 | example/branch | abc1234 | branch-cleanup | Example: already merged into `main`; no unique patch content. | `git log --right-only --cherry-pick main...example/branch`; `git diff --name-status main...example/branch` | +| 2026-07-10 | codex/pr-testing-streamlining | 155c801cd58f797037d8aaa8b885405a1c599249 | working-tree diff: PR testing streamlining | Changes requested: 2 P1 clinical-gate defects and 7 P2/P3 scope, local parity, and UI-process defects. | `npm run check:ci-scope`; `npm run check:github-actions`; `npm run check:codex-autofix-workflow`; `npm run eval:rag:offline`; `npm run test:e2e:critical`; targeted scope classifications; `git diff --check` | +| 2026-07-10 | codex/pr-testing-streamlining | 155c801cd58f797037d8aaa8b885405a1c599249 | working-tree remediation review | All recorded P1-P3 findings fixed; no remaining high-confidence issue in the changed scope. | `npm run verify:cheap`; `npm run verify:pr-local`; `npm run eval:rag:offline`; `npm run test:e2e:critical`; `npm run test:e2e:advisory`; CI YAML parse; scope/action/Codex guards; `git diff --check` | +| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-flow | Fixed exact connector authorization, trusted-marker deduplication, and strict self-trigger matching; added regression coverage. | `npm run check:codex-autofix-workflow`; focused Vitest (4 passed); `npm run verify:cheap` pre-test stages passed before tool timeout; `npm test` (1,415 passed, 1 skipped); focused Prettier check; `npm run check:github-actions` | +| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-flow-followup | Fixed untrusted workflow-level concurrency interference and migrated the bridge from the Node 20 action runtime to `actions/github-script@v9`; added direct embedded-script execution coverage. | Focused Vitest (13 passed); targeted ESLint; `tsc --noEmit`; `npm run check:codex-autofix-workflow`; `npm run check:github-actions`; focused Prettier check; `git diff --check` | +| 2026-07-10 | codex/review-autofix-flow | 155c801cd58f797037d8aaa8b885405a1c599249 | codex-autofix-residual-fixes | Replaced one-shot PR deduplication with a three-cycle head-SHA cap, made comment permission failures fail visibly, and pinned `github-script` v9.0.0 to its verified immutable commit. | TDD red run (7 expected failures); focused Vitest green run (15 passed); `npm run verify:cheap` (152 files passed, 1 skipped; 1,426 tests passed, 1 skipped); focused Prettier check; `git diff --check`; official `git ls-remote` tag verification | +| 2026-07-10 | codex/architecture-review-fixes | 648abfa3f7c91395b5eeca543f70e0b6ea59e9e0 | architecture-review | Seven findings fixed in the working tree: three runtime cycles, unbounded owner caches, a client/server env boundary breach, reversed runtime-to-scripts ownership, and architecture-doc drift. | `npm run test -- tests/architecture-boundaries.test.ts tests/bounded-ttl-cache.test.ts tests/rag-score.test.ts tests/rag-cache-utils.test.ts tests/rag-cache-invalidation.test.ts tests/evidence-panels.test.ts tests/clinical-dashboard-merge-artifacts.test.ts`; `npm run verify:cheap`; `npm run check:production-readiness:ci` | +| 2026-07-10 | codex/architecture-review-fixes | 648abfa3f7c91395b5eeca543f70e0b6ea59e9e0 | frontend-architecture-review | Shared cycle/env findings confirmed and fixed; three additional findings fixed for defeated lazy boundaries, duplicate shell/dashboard subscriptions, and unstable search-context values. | `npm run test -- tests/architecture-boundaries.test.ts tests/evidence-panels.test.ts tests/clinical-dashboard-merge-artifacts.test.ts`; `npm run verify:cheap`; UI gate deferred pending explicit local-API approval | +| 2026-07-11 | codex/architecture-review-integration | b45df727b29aad8ba4ec5d4e96d1f0599d7dad8a | branch-integration-review | Replayed the reviewed architecture fixes onto current `origin/main`; preserved current CI/autofix history and found no new high-confidence defect in the integrated diff. | `npm run check:runtime`; `npm run check:github-actions`; `npm run sitemap:check`; `npm run lint`; `npm run typecheck`; focused Vitest (24 passed); full Vitest with `--testTimeout=30000` (1,433 passed, 1 skipped); `git diff --check` | +| 2026-07-10 | codex/quality-testing-typescript-fixes | 648abfa3f | code-quality + testing + TypeScript | 17 confirmed P2/P3 issues fixed; no P0/P1 findings; residual large-module complexity noted. | Focused Vitest and Playwright; full Vitest 1427 passed/1 skipped; coverage; lint; typecheck; production-readiness CI | +| 2026-07-11 | codex/quality-review-integration | d3fcef8bbc9ab12b929771421b532c1ed8b7e1e7 | branch-integration-review | Replayed the quality, testing, and TypeScript fixes onto current `origin/main` and consolidated the stronger standalone auth callback coverage into this branch. | Changed-file Prettier; focused Vitest (5 files, 23 tests); `git diff --check`; original branch full Vitest/coverage/lint/typecheck and targeted Chromium evidence retained | +| 2026-07-11 | codex/architecture-review-integration | 665103250ccc33b5870862b8d8467607a1ae5d23 | coderabbit-followup | Fixed POSIX project-root identity collisions and closed dynamic-import and self-cycle gaps in the architecture regression guard. | Local-server Vitest passed; architecture-boundaries Vitest passed (6 tests); `npm run typecheck`; focused Prettier; `git diff --check` | +| 2026-07-11 | codex/architecture-review-followup | f5deaaee98864f1d32c1060ae14966a4f5975872 | coderabbit-test-followup | Removed probabilistic no-collision assertions from the local identity test and replaced them with deterministic normalization, repeatability, ID-shape, and port-range checks. | Local-server Vitest (2 passed); focused Prettier; `git diff --check`; hosted CI/SAST/Secret Scan passed on the reviewed head | +| 2026-07-11 | codex/pr-check-followup | 298e8f5bec2a4673dd225da3f446f008b8f25953 | residual-pr-check-hardening | Ported only the three PR-check improvements not already merged by PR #454: pinned Supabase CLI/cache ownership, advisory Semgrep coverage for Edge Functions, and regression guards for both contracts. | `npm run check:github-actions`; `npm run check:ci-scope`; focused Prettier; `git diff --check` | diff --git a/scripts/check-github-action-pins.mjs b/scripts/check-github-action-pins.mjs index ddf263d7e..d9c0947d4 100644 --- a/scripts/check-github-action-pins.mjs +++ b/scripts/check-github-action-pins.mjs @@ -34,6 +34,7 @@ const supportedMajorRanges = new Map([ const usesPattern = /^\s*uses:\s*([^@\s]+)@v(\d+)\s*(?:#.*)?$/; const runsOnLatestPattern = /^\s*runs-on:\s*ubuntu-latest\s*(?:#.*)?$/; const failures = []; +const expectedSupabaseCliVersion = "2.108.0"; for (const fileName of readdirSync(workflowDir) .filter((name) => /\.ya?ml$/i.test(name)) @@ -64,6 +65,35 @@ for (const fileName of readdirSync(workflowDir) }); } +const ciWorkflowPath = path.join(workflowDir, "ci.yml"); +const ciWorkflow = readFileSync(ciWorkflowPath, "utf8"); +const requiredCiFragments = [ + `SUPABASE_CLI_VERSION: ${expectedSupabaseCliVersion}`, + "version: ${{ env.SUPABASE_CLI_VERSION }}", + "id: supabase-docker-cache", + "supabase-docker-${{ runner.os }}-cli-${{ env.SUPABASE_CLI_VERSION }}-", + "if: success() && steps.supabase-docker-cache.outputs.cache-hit != 'true'", +]; + +for (const fragment of requiredCiFragments) { + if (!ciWorkflow.includes(fragment)) { + failures.push(`ci.yml: missing required pinned Supabase/cache contract: ${fragment}`); + } +} + +if (/\bversion:\s*latest\b/.test(ciWorkflow)) { + failures.push("ci.yml: required workflow tooling must not use version: latest."); +} + +const sastWorkflowPath = path.join(workflowDir, "sast.yml"); +const sastWorkflow = readFileSync(sastWorkflowPath, "utf8"); +if (!/^\s{4}continue-on-error:\s*true\s*$/m.test(sastWorkflow)) { + failures.push("sast.yml: Semgrep must remain advisory while it depends on mutable registry rules."); +} +if (!/src worker scripts supabase\/functions/.test(sastWorkflow)) { + failures.push("sast.yml: Semgrep must scan Supabase Edge Function source."); +} + if (failures.length > 0) { console.error("GitHub Actions pin check failed:"); for (const failure of failures) console.error(`- ${failure}`);