Repo hardening: CI security workflows, RLS fix, top maintenance items#23
Merged
Conversation
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.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 673d20036a
ℹ️ 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".
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
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
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Repo hardening pass. No new product features — fixes, security, and small UX polish only.
Collaboration & docs
CLAUDE.mdandAGENTS.md(product invariants, branch protection rules, release gates, PR review workflow).CI / security
ci.yml: triggers ondevandmainpushes + all PRs; permissions block; npm audit (prod-only) and dependency review; Playwright a11y job; migration-filename validation..github/dependabot.yml: weekly grouped npm + github-actions updates.Dependencies
basic-ftptransitive advisory.apply-migrations.js(called a non-existentexec_sqlRPC) and the two loosefix-*.sqlone-off patches.minimatchoverride to 10.2.5 to close residual high-severity advisories transitively pulled in via eslint and typescript-eslint.npm auditreports 0 vulnerabilities (was 24: 1 critical / 18 high / 5 moderate).Supabase RLS
20260517000100_enable_rls_initial_tables.sqlenables RLS oncommenter_infoanddocket_tags(initial-schema oversight) with service-role + agency-member policies. Closes the Supabase advisorrls_disabled_in_publicalert.pgcryptonot enabled).scripts/hotfix-enable-rls-initial-tables.sqlis a standalone copy/paste for the Supabase dashboard SQL Editor that closes the advisor immediately without forcing a full backlog replay. The full migration applies automatically once the backlog clears.App resilience / UX
ErrorBoundaryat the app root so an unhandled render error no longer blanks the public site.TODO.SETUP / docs cleanup
npx supabase db push(removes the brokendb:custom-migrateflow).Follow-ups (not in this PR)
pgcryptoenabled first).console.log/errorcalls.Test plan
npm run typecheck— greennpm run lint— 0 errors (warnings allowed)npm run test:ci— 28 tests passnpm run build— greennpm run test:a11y— 13/13 axe routes passnpm audit --omit=dev— 0 vulnerabilitiesscripts/hotfix-enable-rls-initial-tables.sqlvia Supabase dashboard → confirm advisor alert clears