ci(#265): wire pnpm test:rls into CI — RLS + dual-provider conformance gate#324
Merged
Conversation
… gate) pnpm test:rls ran in ZERO workflows: ci.yml's `pnpm test --run` excludes tests/rls/** and both messaging-provider contract runners (vitest.config.ts), so neither the Supabase RLS policies nor the .NET/Supabase providers were gated in CI. The new `Conformance` workflow closes that gap. It stands up a LOCAL, ephemeral dual-provider stack (local Supabase + the .NET messaging server) and runs the full test:rls config against it: - tests/rls/** (9 suites — the RLS policies) - messaging-provider.supabase.test.ts (C7-C14 [supabase]) - messaging-provider.dotnet.test.ts (C7-C14 [dotnet], live ASP.NET) Verified 107/107 green locally before wiring. Design notes: - No e2e-supabase mutex: unlike e2e.yml (one shared cloud project that concurrent runs race), each run owns its own ephemeral Postgres, so runs can't race. Per-ref cancel-in-progress is all that's warranted. - test:rls runs on the runner (CI-native, like ci.yml); the compose stack provides backends on localhost. Only the services test:rls needs are started (db/kong/auth/rest + dotnet), not scripthammer/studio/mail/etc. - Uses the public Supabase self-hosting demo keys (already in docker-compose.yml). - Path-filtered on PRs (migrations/messaging/dotnet/tests/compose); full run on push to main. Not yet a required check — prove it stable across a few runs first, then add it to branch protection. Refs #265, #280. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GitHub Actions runs `run:` steps with `bash -eo pipefail`. The wait loop's `rest=$(curl ...)` probes exit non-zero while the services are still starting, and under set -e that aborted the whole step on iteration 1 (~6s in) instead of retrying — the run read as a 5-min timeout but the loop never actually ran. (The supabase-db "FATAL: terminating background worker TimescaleDB" line is just the image's normal init restart, unrelated.) Add `set +e` in the wait step so the probes fail-and-retry as designed, and read the anon key directly from process env. Validated the probe codes (db=ok, rest/auth/dotnet=200) against a live local stack before pushing. Refs #265. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What & why
pnpm test:rlsran in zero workflows.ci.yml'spnpm test --runuses the defaultvitest.config.ts, which excludestests/rls/**and bothmessaging-provider.*.test.tscontract runners — so until now neither the Supabase RLS policies nor the .NET/Supabase messaging providers were gated in CI. The #265 scoping called this out as core Phase-1 work: the anti-drift alarm was off.This adds a
Conformanceworkflow that closes the gap.How it works
It stands up a local, ephemeral dual-provider stack (local Supabase + the .NET messaging server) and runs the full
test:rlsconfig against it:tests/rls/**— 9 suites, the RLS policies (user isolation, group isolation, the Security: a 1:1 recipient can rewrite the sender's message ciphertext (column-blind UPDATE RLS) #281 column-guard, GDPR, audit immutability, payment RLS, …)messaging-provider.supabase.test.ts— C7–C14[supabase]messaging-provider.dotnet.test.ts— C7–C14[dotnet], against the live ASP.NET serverVerified 107/107 green locally before wiring.
Design notes
e2e-supabasemutex.e2e.ymlneeds a repo-wide mutex because every E2E run shares one cloud Supabase project and races the others' cleanup hooks. This job spins up its own per-runner ephemeral Postgres, so concurrent runs cannot race — a per-refcancel-in-progressgroup is all that's warranted.test:rlsruns on the runner (CI-native, likeci.yml); the compose stack provides backends onlocalhost. Only the services the suite needs start (db/kong/auth/rest+dotnet-messaging) — notscripthammer/studio/mail/etc.docker-compose.yml'sx-supabase-envanchor). The.NETserver boots inDevelopment, so the fix(#265): .NET messaging conformance 12/12 + JWT hardening + C11 doc-truth #322 fail-closed demo-secret guard correctly permits it.main.Self-validating
This PR edits
conformance.yml, which is in the workflow's own path filter — so theConformancecheck runs on this PR. Its green (or red) result is the proof the wiring works end-to-end in real CI.Follow-ups (not this PR)
FLAKY_GATE_MODE=block(separate, e2e.yml).Refs #265, #280.
🤖 Generated with Claude Code