amal66 makes Mike's privacy checks harder to wave through

A new review gate now tests whether a fresh Mike installation actually keeps browser access locked down.

securityinfrastructure

amal66 has turned previously optional security checks into a repeatable review step. Each proposed change gets a temporary, self-contained copy of the core database and sign-in services, then the checks run against a clean installation.

  • Browser-facing access is tested as deny-by-default, so client apps should not be able to read database records directly.
  • Sign-in tokens are checked to ensure the backend identifies the right user.
  • Pagination is also tested against the same realistic setup.

The environment is created solely for the check and discarded afterwards, with no accounts, secrets, or outside services involved. The work deliberately tests new installations, not upgrade paths, which remain a separate question.

So what Legal teams and product owners should care because a change that weakens core access controls is far less likely to look safe in review.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

3 commits from amal66/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
44ed40db ci: run the Supabase RLS/stack integration suite on every PR Amalanand Muthukumaran 2026-07-25 ↗ GitHub
commit body
The gated stack tests (backend/src/__tests__/integration/*.supabase.test.ts)
prove the deny-all RLS firewall and the auth<->API contract against a real
local Supabase stack, but no CI trigger ever set the SUPABASE_TEST_* env
vars, so they silently self-skipped on every PR. Add a workflow that boots
the stack on the runner (supabase CLI pinned, minimal service set: db, auth,
rest, kong), bootstraps the database the way backend/scripts/test-stack.sh
does, and runs the suite. No secrets: everything is local to the runner.

The bootstrap loads schema.sql and then applies every dated migration on
top in filename order, which doubles as a schema-drift smoke test: the
snapshot and the migrations must apply cleanly together. Running it
surfaced five migrations that could not apply on top of the current
schema.sql - three whose backfills read documents columns that later
migrations moved to document_versions, and two overview RPCs whose return
row type `create or replace` cannot change. Guard the backfills on the
historical columns' existence and drop-before-create the RPCs (the pattern
20260703_02 already uses); behavior on era deployments is unchanged, and
the full sequence now applies cleanly end to end (verified locally: fresh
stack, schema + 44 migrations, 5/5 stack tests green).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
22542d8d ci: bootstrap the stack from schema.sql only; restore historical migrations Amal 2026-08-05 ↗ GitHub
commit body
Addresses willchen96's review on PR #256.

WHY THIS MATTERS

The previous revision of this workflow built the CI database as:

    empty database -> current schema.sql -> every dated migration

and called it a "schema-drift smoke test". But that sequence is not a real
installation path. Per README.md, this repo has two deliberately separate
database artifacts:

  - backend/schema.sql      -> the COMPLETE shape for FRESH databases
  - backend/migrations/     -> incremental steps that move OLDER, already-
                               deployed databases forward from the version
                               they are on

A fresh install runs schema.sql and stops. An existing deployment runs only
the migrations dated after its version. Nobody ever replays the full
migration history on top of the current snapshot - so when five old
migrations "failed" under that replay, they were not broken; the harness
was. They had run correctly on the era-appropriate schemas they were
written for.

WHAT IS MIGRATION IMMUTABILITY

Once a migration has shipped and real deployments have executed it, the
file becomes a historical record of "the change that was required at that
point in time". Editing it afterwards cannot help any database that already
ran it - it only makes the repo's history diverge from what production
actually executed, which is exactly the record you need intact when
debugging a deployment later. (Tools like Flyway enforce this with
checksums: a modified applied migration is a hard error.) The previous
revision rewrote five historical migrations to satisfy the artificial
replay; worse, the column-existence guards it added made those backfills
silently no-op on unexpected schemas - converting the loud failure a drift
check exists to produce into a silent skip.

HOW THIS COMMIT FIXES IT

1. The five historical migrations are restored byte-for-byte to their
   state on main (20260424_01, 20260427_01, 20260602_01, 20260613_02,
   20260613_05).
2. The workflow's bootstrap step now loads schema.sql only - the same
   thing backend/scripts/test-stack.sh does locally and the same thing the
   README documents for a fresh deployment. The suite therefore tests the
   real contract: "a fresh Mike database enforces deny-all RLS and the
   auth<->API contract."

Real drift protection (does baseline-plus-migrations equal the current
snapshot?) needs a pinned baseline dump from an older release, the
migrations dated after it, and a pg_dump schema diff against a
schema.sql-built database. That is a separate change, designed separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
78a0a40c ci: run tabularPagination.supabase.test.ts in the stack workflow Amal 2026-08-05 ↗ GitHub
commit body
WHY THIS MATTERS

The whole point of this PR is to close a silent-skip gap: the Supabase
stack suites gate themselves on SUPABASE_TEST_* env vars and quietly
self-skip when those are absent, so plain CI never actually exercised
them. The new stack-tests workflow boots a real Supabase stack and runs
the suites with the env vars set - but its vitest invocation listed only
two of the three files that backend/scripts/test-stack.sh (the declared
source of truth) runs:

    # test-stack.sh runs:
    stack.supabase.test.ts
    access.supabase.test.ts
    tabularPagination.supabase.test.ts   # <-- missing from CI

So tabularPagination.supabase.test.ts kept doing in CI exactly what
this PR exists to stop: skipping silently. Worse, the workflow comment
("The exact suite test-stack.sh invokes") claimed parity that did not
exist, which is how this kind of drift survives review.

WHAT IS A SELF-SKIPPING (GATED) SUITE

A gated suite decides at load time whether to run, based on the
environment it finds:

    const url = process.env.SUPABASE_TEST_URL;
    const serviceKey = process.env.SUPABASE_TEST_SERVICE_ROLE_KEY;
    const maybeDescribe = url && serviceKey ? describe : describe.skip;

This is great for local ergonomics (checkout works without Docker), but
dangerous in CI: a skipped suite exits 0 and looks green. The only
defense is a workflow that provably sets the gate variables AND lists
every gated file - a list that must be kept in lockstep with the local
runner script, or files fall through the crack unnoticed.

HOW THE FIX WORKS

Add the missing file to the workflow's vitest invocation so the CI list
matches test-stack.sh file-for-file, making the "exact suite" comment
true. Nothing else needs enabling, verified on this branch:

- Gate variables: the suite gates only on SUPABASE_TEST_URL and
  SUPABASE_TEST_SERVICE_ROLE_KEY, both already exported to the job env
  by the "Export stack connection env" step.
- Schema: the suite touches only public.projects and
  public.tabular_reviews, both created by backend/schema.sql, which the
  "Load schema" step applies before tests run.

Verified: workflow YAML parses cleanly, and the exact three-file vitest
invocation loads all suites without error (they self-skip locally where
no stack is running, exit 0 - in CI the exported env vars flip them on).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-1309.md from inside the repo you want the changes in.

⬇ Download capture-thread-1309.md