Conversation
…iliation, CI, and v1 api
Aligns OpenComments with the MetaPhase house standard used in dutystation, ITspending, ceta, and minimis. Captures product invariants (RLS-on-everything, WCAG 2.1 AA, anonymous-friendly submission), branch protection rules, release gates, and PR review workflow.
Aligns CI with the MetaPhase house standard. New workflows are warn-only where appropriate so flaky scans don't block merges, but findings surface in the Security tab. Adds Dependabot weekly grouped updates for npm and github-actions ecosystems.
- Drop Cypress (only Playwright remains as E2E framework). Removes the critical basic-ftp transitive advisory. - Delete broken apply-migrations.js (called a non-existent exec_sql RPC) and the two loose fix-*.sql one-off patches. - Remove the db:custom-migrate npm script; SETUP.md now points at 'npx supabase db push' as the only documented path. - Bump minimatch override to 10.2.5 to close the remaining high-severity advisories transitively pulled in via eslint and typescript-eslint. - npm audit reports 0 vulnerabilities.
Closes the Supabase advisor 'rls_disabled_in_public' alert. Both tables were created in the initial schema without ENABLE ROW LEVEL SECURITY. Policies: - commenter_info: service_role full access; active agency members of the parent docket's agency can read for moderation. No anon access. - docket_tags: public SELECT (tags are part of public docket display); writes restricted to active agency members of the docket's owning agency. Both tables are read in production only via SECURITY DEFINER search functions (20250729100012, 20250729100013), so enabling RLS does not break any existing client query path.
- LICENSE.md (Protoware v1.0, U.S. gov use only) replaces MIT LICENSE. Mirrors CETA and other MetaPhase CivicTech repos. - README badge and License section updated. - About page 'Open Source' section now describes Protoware instead of MIT. - Last-updated date on Privacy, Terms, Accessibility, Security, About, Onboarding, and UserGuide pages bumped to May 17, 2026. - Add ErrorBoundary at app root so an unhandled render error no longer blanks the public site; users get a reload-friendly fallback. - DocketDetail copy-to-clipboard now shows a polite toast on success/error instead of a silent TODO. - Hotfix SQL at scripts/hotfix-enable-rls-initial-tables.sql lets the remote Supabase advisor be closed without forcing a full migration backlog replay.
- aquasecurity/trivy-action@0.28.0 is the briefly-compromised release;
dependency-review-action flags it as critical. Move to 0.36.0 (matches
dutystation's pin).
- Drop .github/workflows/codeql.yml. GitHub's default CodeQL setup is
already enabled on this repo; the advanced workflow conflicts with
it ('CodeQL analyses from advanced configurations cannot be processed
when the default setup is enabled').
test-results/ leaked into the previous commit; ignore it (plus the playwright-report/ and .cache directories) so local runs don't pollute future commits.
Both gates pass cleanly on this branch (npm audit reports 0 production vulnerabilities; all 13 axe routes pass), so continue-on-error: true is no longer needed and was masking real regressions. Required checks now fail the merge if a high-severity production dep advisory lands or an axe critical violation is introduced.
…cleanly Three changes lets the full chain replay against the linked Supabase project: 1. New 20260211000050_enum_additions.sql extracts the ALTER TYPE ADD VALUE calls for agency_role and comment_status out of the reconcile migration. Postgres rejects using a freshly-added enum value in the same transaction (SQLSTATE 55P04 'unsafe use of new value'); the reconcile migration's RLS helper functions reference 'manager', so the value must commit first. 2. 20260211000100 now ensures the pgcrypto extension exists in the extensions schema and schema-qualifies gen_random_bytes() so the invitation-token default works regardless of the connection's search_path. 3. The reconcile migration's enum-add blocks are removed (now in ...000050) with a pointer comment so the split stays discoverable. Verified with 'supabase db push --linked --include-all' — all 9 local migrations now present on remote, supabase advisor 'rls_disabled_in_public' alert is closed. The scripts/hotfix-enable-rls-initial-tables.sql one-off is no longer needed and has been removed.
- netlify.toml NODE_VERSION 18 -> 20 (CI already on 20). - README tech-stack line no longer lists Cypress (removed earlier in this PR). Calls out Playwright + axe-core as the E2E/a11y stack. - CLAUDE.md and AGENTS.md updated to reflect the unified Node 20 pin.
Combines a one-time fix and a permanent guardrail so the pgcrypto class of bug stops biting us: - supabase/migrations/20250729100000_create_initial_schema.sql now creates the 'extensions' schema and installs pgcrypto into it. Mirrors Supabase's managed layout. Every fresh deploy (local, CI, future branch) has the extension from migration zero. Idempotent: harmless on the already-applied remote since CREATE EXTENSION IF NOT EXISTS is a no-op there. - scripts/validate-migrations-fresh.sh now creates the same extensions schema and aligns the test DB's search_path with Supabase's (public, extensions), so schema-qualified calls like extensions.gen_random_bytes() and unqualified calls both resolve the way they do in production. - New CI job 'Migration Replay (fresh DB)' boots a throwaway PostgreSQL 16 and runs npm run db:validate:fresh. This catches the drift we just spent half this PR fixing — out-of-order enum value use, missing extension prerequisites, etc — before merge instead of after. Verified locally: fresh replay against an empty Postgres applies all 17 migrations cleanly and produces 20 public tables.
Drops the initial bundle from 837 kB (199 kB gzipped) to 367 kB (107 kB gzipped) — roughly 56 % off the first-paint payload — by turning all 40 page components into dynamic imports. Each route now ships as its own ~10–30 kB chunk fetched on demand. A single top-level <Suspense> with an accessible RouteFallback (spinner with aria-live='polite' and an sr-only 'Loading…' label) wraps the router. Landing-page chrome (Header, Hero, StateDirectory, FeatureHighlights, CalloutBanner, Footer) stays eager so '/' never shows the fallback. Why this matters: a public commenting platform takes meaningful traffic on mobile and constrained connections. Cutting the JS payload in half improves TTI for the audience the product is designed to reach, and keeps the WCAG 2.1 AA release gate honest — slow networks disproportionately affect users on assistive tech. Verified: - npm run typecheck — green - npm run test:ci — 28/28 passing - npm run test:a11y — 13/13 axe routes passing (Suspense fallback doesn't introduce critical violations) - npm run build — succeeds; no Vite chunk-size warning
Repo hardening: CI security workflows, RLS fix, top maintenance items
Bumps the github-actions group with 5 updates: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4` | `6` | | [actions/setup-node](https://github.com/actions/setup-node) | `4` | `6` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `7` | | [actions/dependency-review-action](https://github.com/actions/dependency-review-action) | `4` | `5` | | [github/codeql-action](https://github.com/github/codeql-action) | `3` | `4` | Updates `actions/checkout` from 4 to 6 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v6) Updates `actions/setup-node` from 4 to 6 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@v4...v6) Updates `actions/upload-artifact` from 4 to 7 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v4...v7) Updates `actions/dependency-review-action` from 4 to 5 - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](actions/dependency-review-action@v4...v5) Updates `github/codeql-action` from 3 to 4 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/setup-node dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/dependency-review-action dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com>
…wright 1.60, lucide 0.577 Consolidates the six Dependabot grouped PRs (#24–#29) into a single upgrade pass with one CI run. Runtime: - react / react-dom: 18.3.1 -> 19.2.6 - react-router-dom: 7.7.1 -> 7.15.1 - @supabase/supabase-js: 2.52.1 -> 2.105.4 - lucide-react: 0.344.0 -> 0.577.0 (last 0.x; v1.x drops brand icons like Github/Linkedin that this codebase uses; staying on 0.x adds React 19 peer support without losing the icons) Dev: - @types/react / @types/react-dom: bumped to 19.x to match runtime - vite: 7.0.6 -> 8.0.13 (now rolldown-powered) - @vitejs/plugin-react: 4.7.0 -> 6.0.2 - vitest: 3.2.4 -> 4.1.6 - @playwright/test / playwright: 1.58.2 -> 1.60.0 - @axe-core/playwright: 4.10.2 -> 4.11.3 - @testing-library/jest-dom: 6.6.4 -> 6.9.1 - @testing-library/react: 16.3.0 -> 16.3.2 - jest-environment-jsdom: 30.0.5 -> 30.4.1 - eslint-plugin-react-refresh: 0.4.11 -> 0.5.2 - globals: 15.9.0 -> 17.6.0 Intentionally NOT bumped: - eslint 9.x and @eslint/js 9.x kept (eslint 10 requires eslint-plugin-react-hooks 7, which adds strict React-Compiler rules that error on ~84 currently-fine patterns — orthogonal refactor). - eslint-plugin-react-hooks 5.x kept for the same reason. GitHub Actions: - actions/checkout: v4 -> v6 - actions/setup-node: v4 -> v6 - actions/upload-artifact: v4 -> v7 - actions/dependency-review-action: v4 -> v5 - github/codeql-action: v3 -> v4 Verified locally: - npm install — 0 vulnerabilities - npm run typecheck — green - npm run lint — 0 errors (170 pre-existing warnings unchanged) - npm run build — 503 KB initial (still well under the pre-split 837 KB) - npm run test:ci — 28/28 passing - npm run test:a11y — 13/13 axe routes passing - npm run db:validate:fresh — 17 migrations replay cleanly, 20 public tables
Vite 8 (rolldown) and a few other deps ship platform-specific native binaries. npm install on macOS only writes the host platform's optional deps into the lockfile, so npm ci on Linux runners fails with 'Missing: @emnapi/core@1.10.0 from lock file' even though everything resolves correctly locally. Trading strict ci reproducibility for the practical workaround other repos in the org use. The lockfile is still committed and used by npm install; --no-audit / --no-fund just keep the install output focused on the real work.
…tions/github-actions-0d9431b73f ci(deps): bump the github-actions group with 5 updates
Bulk dependency upgrade: React 19, Supabase 2.105, Vite 8, Vitest 4
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ec132fbfa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - name: Run a11y suite | ||
| env: | ||
| VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL || 'https://example.supabase.co' }} | ||
| VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY || 'placeholder-anon-key' }} |
There was a problem hiding this comment.
Use valid fallback Supabase anon key in CI env
When repository secrets are unavailable (for example, PRs from forks), the workflow injects placeholder-anon-key, but validateSupabaseConfig rejects any key that does not start with eyJ or sb_ (src/lib/supabase.ts, key format guard). That makes the frontend throw during startup under Playwright, so the accessibility job can fail even though application code is fine. Use a syntactically valid dummy key (e.g., sb_...) for the fallback to keep CI runnable without secrets.
Useful? React with 👍 / 👎.
Summary
Syncs `main` with `dev`. Brings everything that landed since the previous `main` cut into production:
Repo hardening (#23)
Bulk dependency upgrade (#30)
Test plan