test(integration): DB-backed harness validating shipped SQL (045/042/044/043)
Root-cause fix for 'correctness depended on post-deploy manual audits'. Separate psql-driven suite (pnpm test:integration, own vitest config, integration/ outside __tests__ so the hermetic pnpm test gate is untouched; self-skips without a DB). 18 tests run against real Postgres: - 045 class_signup_tx/class_cancel_tx: RETURNS TABLE->array shape the actions destructure, capacity/waitlist/dedupe, and the per-session advisory lock under TWO concurrent connections (D11 proven, never over-enrolls). - 042 equipment exclusion constraint (overlap 23P01; cancelled/adjacent ok). 044 self-change trigger (role + payment cols blocked; service bypass). 043 members_update WITH CHECK (cross-space move blocked). Disproves the pass-52 flagged risk (signup rpc-shape). Non-runtime; default pnpm test still 532/26 hermetic; build clean.
This commit is contained in:
@@ -4,6 +4,26 @@ Append-only. Newest entries on top. Keep each entry to one screen.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-19 (pass 53) — DB-backed integration harness; shipped SQL now functionally validated (LOCAL, non-runtime)
|
||||
|
||||
Branch `main`. Assessment chose "integration test harness" to fix the root cause (correctness depending on post-deploy manual audits). Built + RAN it against the local Supabase Postgres. Default `pnpm test` still 532/26, hermetic; build clean.
|
||||
|
||||
### Delivered
|
||||
- **F1 foundation:** `vitest.integration.config.ts` (separate runner; `integration/` is OUTSIDE `__tests__/` so `pnpm test` never touches a DB), `integration/db.ts` psql-driven helpers (service path vs `role authenticated`+`request.jwt.claims.sub` user path; throwing seed helpers), `pnpm test:integration` script. Self-skips when no DB.
|
||||
- **F2 tests (18, all green on real Postgres):** 045 `class_signup_tx`/`class_cancel_tx` — RETURNS TABLE→array shape the actions destructure, capacity/waitlist/dedupe/no_session, and the per-session advisory lock under TWO genuinely concurrent psql connections (exactly one registered — D11 proven); 042 exclusion constraint (overlap rejected 23P01, cancelled/adjacent allowed); 044 trigger (member self-edit of role + payment columns blocked, service path bypasses) + 043 WITH CHECK (cross-space move blocked).
|
||||
- Applying `scripts/schema.sql` to the local DB also validated the "idempotent, runnable top-to-bottom" invariant in practice (it was stale at 041; applied cleanly to 045).
|
||||
- Harness bug found+fixed during bring-up: `space_members.user_id` FKs `auth.users` (my earlier FK introspection was wrong) — seeds now create the auth user first; seed helpers throw on failure.
|
||||
- Docs: LOCAL_DEV "Integration tests" section.
|
||||
|
||||
### Significance
|
||||
The concrete prod risk flagged in the pass-52 assessment — signup/cancel possibly broken because the action assumes `supabase.rpc()` returns an array for a RETURNS TABLE function — is **disproven**: the shape + behavior + concurrency are correct. Correctness of the riskiest shipped SQL no longer depends on me manually auditing after deploy.
|
||||
|
||||
### State
|
||||
- **Non-runtime** (tests, vitest config, a package.json script, docs). No app code, no migration. Nothing to validate in prod; a push would only redeploy unchanged runtime. Held local pending the deploy decision (consistent with the docs-only hold pattern).
|
||||
- Backlog now: deferred SECURITY DEFINER status-gate (own session, rationale in pass-52); owner product question (forms attribution); ARCHITECTURE limitation #2 doc drift ("Stripe not integrated" — stale). Natural next: extend the harness to the Stripe webhook + key server actions; or owner provisioning + end-to-end spine validation.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-19 (pass 52) — Backlog hardening E1-E3 + evidence-based deferral (LOCAL, NEEDS deploy)
|
||||
|
||||
Branch `main`. Worked the pass-51 small backlog. Suite 532, build clean. NOT deployed.
|
||||
|
||||
@@ -170,6 +170,31 @@ SELECT public.expire_proposals();
|
||||
|
||||
In production you'd schedule this via pg_cron (the schema's migration 019 sets this up automatically when pg_cron is available) or via a Next.js cron endpoint guarded by a `CRON_SECRET`.
|
||||
|
||||
## Integration tests (DB-backed)
|
||||
|
||||
`pnpm test` is hermetic (pure logic, jsdom, no DB) and is the gate. The
|
||||
separate **`pnpm test:integration`** suite (`integration/`, its own
|
||||
`vitest.integration.config.ts`) exercises the shipped SQL — the
|
||||
`class_signup_tx`/`class_cancel_tx` RPCs (045) including the advisory lock
|
||||
under real concurrency, the `equipment_reservations_no_overlap` exclusion
|
||||
constraint (042), and the self-change trigger / `members_update` WITH CHECK
|
||||
(044/043) — against a real Postgres through `psql` (no extra npm dep). It
|
||||
drives both access paths the app uses: the service path (no JWT) and a
|
||||
logged-in member (`role authenticated` + `request.jwt.claims.sub`).
|
||||
|
||||
Prereqs: the Supabase CLI stack running (`supabase start`) with the schema
|
||||
applied (`psql "$DB_URL" -f scripts/schema.sql`). It connects to
|
||||
`INTEGRATION_DATABASE_URL` (default the local stack
|
||||
`postgresql://postgres:[email protected]:54322/postgres`) and **self-skips
|
||||
cleanly** when no DB is reachable, so it never blocks contributors/CI
|
||||
without one. It is intentionally NOT part of `pnpm test` or the deploy gate.
|
||||
|
||||
```bash
|
||||
supabase start
|
||||
psql "postgresql://postgres:[email protected]:54322/postgres" -f scripts/schema.sql
|
||||
pnpm test:integration
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `supabase start` hangs or fails
|
||||
|
||||
Reference in New Issue
Block a user