Skip to content

Repo hardening: CI security workflows, RLS fix, top maintenance items#23

Merged
brianfunk merged 13 commits into
devfrom
repo-hardening
May 18, 2026
Merged

Repo hardening: CI security workflows, RLS fix, top maintenance items#23
brianfunk merged 13 commits into
devfrom
repo-hardening

Conversation

@brianfunk

@brianfunk brianfunk commented May 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Repo hardening pass. No new product features — fixes, security, and small UX polish only.

Collaboration & docs

  • Add CLAUDE.md and AGENTS.md (product invariants, branch protection rules, release gates, PR review workflow).
  • Refresh the "Last Updated" date on Privacy, Terms, Accessibility, Security, About, Onboarding, and UserGuide pages.

CI / security

  • Harden ci.yml: triggers on dev and main pushes + all PRs; permissions block; npm audit (prod-only) and dependency review; Playwright a11y job; migration-filename validation.
  • New workflows: Trivy (filesystem + config SARIF), TruffleHog secret scan, CycloneDX SBOM. Security scans are warn-only so flaky scans don't block, but findings post to the Security tab.
  • .github/dependabot.yml: weekly grouped npm + github-actions updates.

Dependencies

  • Remove Cypress; Playwright is now the sole E2E framework. Drops the critical basic-ftp transitive advisory.
  • Delete dead scripts: apply-migrations.js (called a non-existent exec_sql RPC) and the two loose fix-*.sql one-off patches.
  • Bump minimatch override to 10.2.5 to close residual high-severity advisories transitively pulled in via eslint and typescript-eslint.
  • npm audit reports 0 vulnerabilities (was 24: 1 critical / 18 high / 5 moderate).

Supabase RLS

  • New migration 20260517000100_enable_rls_initial_tables.sql enables RLS on commenter_info and docket_tags (initial-schema oversight) with service-role + agency-member policies. Closes the Supabase advisor rls_disabled_in_public alert.
  • Both tables are read in production only via SECURITY DEFINER search functions, so enabling RLS does not break any existing client query path.
  • Remote currently has an 8-migration backlog (pre-existing, pgcrypto not enabled). scripts/hotfix-enable-rls-initial-tables.sql is 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

  • Add ErrorBoundary at the app root so an unhandled render error no longer blanks the public site.
  • DocketDetail copy-to-clipboard now shows a polite toast on success/error instead of a silent TODO.

SETUP / docs cleanup

  • SETUP.md rewritten to point at npx supabase db push (removes the broken db:custom-migrate flow).

Follow-ups (not in this PR)

  • Push the 8-migration backlog to remote Supabase (separate operational PR; needs pgcrypto enabled first).
  • Logger wrapper + reduce raw console.log/error calls.

Test plan

  • npm run typecheck — green
  • npm run lint — 0 errors (warnings allowed)
  • npm run test:ci — 28 tests pass
  • npm run build — green
  • npm run test:a11y — 13/13 axe routes pass
  • npm audit --omit=dev — 0 vulnerabilities
  • Local smoke: docket "Share" / copy link → toast appears
  • CI on this PR: all required jobs green
  • Apply scripts/hotfix-enable-rls-initial-tables.sql via Supabase dashboard → confirm advisor alert clears

brianfunk added 7 commits May 17, 2026 21:32
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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/ci.yml Outdated
@github-advanced-security

Copy link
Copy Markdown

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:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@brianfunk brianfunk changed the title Repo hardening: house-standard CI, RLS fix, Protoware license, top-5 maintenance Repo hardening: CI security workflows, RLS fix, top maintenance items May 18, 2026
brianfunk added 5 commits May 17, 2026 21:53
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
@brianfunk brianfunk merged commit 3610781 into dev May 18, 2026
18 checks passed
@brianfunk brianfunk deleted the repo-hardening branch May 18, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants