fix(edge-fn): use user.id instead of claims.sub; fixes 500s and false cert_required fix(migrations): drop broad reservations SELECT policy; add reservation_slots view with security_invoker=false fix(tests): correct weekSlot() keys from start/end to start_time/end_time fix(tests): spread overlap test slots across separate ISO weeks fix(tests): update e2e assertion to match actual authenticated home text fix(app): hide IonMenu before user is authenticated feat(dx): add test:all script running unit, integration, and e2e in sequence docs(claude-md): document SELinux fix, Edge Function auth pattern, security_invoker behaviour
102 lines
8.7 KiB
Markdown
102 lines
8.7 KiB
Markdown
# Session Handoff: Integration Test Debugging
|
|
**Date:** 2026-04-20
|
|
**Session Duration:** ~1.5 hours
|
|
**Session Focus:** Debug and fix failing integration tests for auth and booking-constraints suites; fix Edge Function boot failure; fix members RLS infinite recursion
|
|
**Context Usage at Handoff:** High
|
|
|
|
## What Was Accomplished
|
|
|
|
1. **Fixed `verifyOtp` API misuse in both test files** — `token` param is for 6-digit OTP codes; `token_hash` param is for hashed magic link tokens. Changed in both test files.
|
|
- `tests/integration/auth-session.test.ts` (2 call sites)
|
|
- `tests/integration/booking-constraints.test.ts` (1 call site in `getSessionToken`)
|
|
|
|
2. **Fixed `futureSlot()` key mismatch** in booking-constraints test — returned `{ start, end }` but `callCreateReservation` expected `{ start_time, end_time }`. Renamed keys in `futureSlot()` return value; updated 2 `directInsertReservation` call sites that used `slot.start`/`slot.end`.
|
|
|
|
3. **Added `@types/node` and test tsconfig** — Nuxt-generated tsconfig has `"types": []`, causing `process` to be unresolved in test files.
|
|
- Added `@types/node` as dev dependency
|
|
- Created `tests/tsconfig.json` extending root with `"types": ["node", "vitest/globals"]`
|
|
- Added `typecheck: { tsconfig: './tests/tsconfig.json' }` to `vitest.integration.config.ts`
|
|
|
|
4. **Fixed members RLS infinite recursion (42P17)** — Policies "Admins can read all members" and "Admins can manage all members" queried `members` from within a `members` RLS policy, causing infinite recursion. Created new migration with two `SECURITY DEFINER` helper functions:
|
|
- `public.current_user_role() → text`
|
|
- `public.current_user_has_role(roles text[]) → boolean`
|
|
- Replaced all inline `EXISTS (SELECT 1 FROM members WHERE ...)` admin checks in ALL tables with `public.current_user_has_role(...)` calls
|
|
- Migration: `supabase/migrations/20260420170418_fix_members_rls_recursion.sql`
|
|
|
|
5. **Removed broken import from Edge Function** — `import "@supabase/functions-js/edge-runtime.d.ts"` is not a valid Deno runtime import. Removed it. Also tried `/// <reference types="..." />` which also failed.
|
|
|
|
6. **Switched Edge Function import from `jsr:` to `npm:`** — `jsr:@supabase/supabase-js@2` cache is lost on container restart in the podman-based local dev setup. Changed to `npm:@supabase/supabase-js@2`.
|
|
|
|
7. **Removed `entrypoint` from config.toml** — `entrypoint` field may not be supported/correctly handled by supabase-edge-runtime 1.73.3 (podman variant). Removed it; function now relies on default `index.ts` convention.
|
|
|
|
8. **Set `verify_jwt = false` in config.toml** — Edge runtime 1.73.3 `verifyHybridJWT` fails with `TypeError: Invalid Token or Protected Header formatting` on ES256 JWTs (new `sb_publishable_*` / `sb_secret_*` key format). Disabled edge-level JWT verification; the function handles auth itself via `userClient.auth.getUser()`.
|
|
|
|
## Exact State of Work in Progress
|
|
|
|
- **Edge Function still returns BOOT_ERROR** — Even after all the above changes, the edge runtime container still fails with `worker boot error: failed to bootstrap runtime: failed to determine entrypoint`. Investigation showed the function source files are NOT mounted inside the container (`find / -name index.ts` inside the container showed only Deno npm cache, no project files). Root cause: likely a podman volume mount issue specific to this host environment. Session was interrupted before resolving this.
|
|
|
|
- **Integration tests NOT yet passing** — All 15 booking-constraints tests still fail with 503 (Edge Function BOOT_ERROR). The auth-session tests (5 tests) status is unknown for this session.
|
|
|
|
## Decisions Made This Session
|
|
|
|
- **`verify_jwt = false` for create-reservation** BECAUSE: edge-runtime 1.73.3 with podman does not correctly verify ES256 JWTs from new `sb_publishable_*` key format; function verifies auth internally via `auth.getUser()` anyway — STATUS: confirmed
|
|
- **`npm:` over `jsr:` for supabase-js import** BECAUSE: JSR cache is not persistent across podman container restarts in this local dev setup — STATUS: confirmed
|
|
- **SECURITY DEFINER functions for role checks** BECAUSE: inline `EXISTS (SELECT 1 FROM members ...)` in members RLS policies causes infinite recursion — STATUS: confirmed, migration applied
|
|
|
|
## Key Numbers Generated or Discovered This Session
|
|
|
|
- supabase-js SDK version installed: **2.100.0**
|
|
- Supabase CLI version: **2.92.1**
|
|
- supabase-edge-runtime version: **1.73.3** (compatible with Deno v2.1.4)
|
|
- Publishable key prefix: `sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH`
|
|
- Secret key prefix: `sb_secret_N7UND0UgjKTVK-Uodkm0Hg_xSvEMPvz`
|
|
- Access tokens are **ES256** (not HS256) — `eyJhbGciOiJFUzI1NiIs...`
|
|
- New migration timestamp: **20260420170418**
|
|
|
|
## Files Created or Modified
|
|
|
|
| File Path | Action | Description |
|
|
|-----------|--------|-------------|
|
|
| `tests/integration/auth-session.test.ts` | Modified | Fixed `verifyOtp` to use `token_hash` (2 call sites) |
|
|
| `tests/integration/booking-constraints.test.ts` | Modified | Fixed `verifyOtp` to use `token_hash`; renamed `futureSlot` keys to `start_time`/`end_time`; removed unused `beforeEach` import |
|
|
| `tests/tsconfig.json` | Created | Test-scoped tsconfig adding `node` + `vitest/globals` types |
|
|
| `vitest.integration.config.ts` | Modified | Added `typecheck.tsconfig` pointing to `tests/tsconfig.json` |
|
|
| `supabase/migrations/20260420170418_fix_members_rls_recursion.sql` | Created | SECURITY DEFINER helpers + fixed RLS policies for all tables |
|
|
| `supabase/functions/create-reservation/index.ts` | Modified | Removed bad `import`; changed `jsr:` → `npm:` for supabase-js |
|
|
| `supabase/functions/create-reservation/deno.json` | Modified | Updated import map to `npm:@supabase/supabase-js@^2` |
|
|
| `supabase/config.toml` | Modified | `verify_jwt = false`; removed `entrypoint` field |
|
|
|
|
## What the NEXT Session Should Do
|
|
|
|
1. **Diagnose Edge Function mount issue first** — Run `podman inspect supabase_edge_runtime_oysqn.app` and check the `Mounts` array. The function source files (`supabase/functions/`) must be visible inside the container. If they are not mounted, this is likely a podman rootless socket or SELinux label issue on the host. Try `npx supabase stop && npx supabase start` to re-create the container with correct mounts.
|
|
|
|
2. **If supabase restart doesn't fix mounts** — Try `npx supabase functions serve` in a separate terminal (it spins up its own Deno process outside Docker, bypassing the container). Then run `yarn test:integration` — this tests the exact same function code via the same URL. If this works, the issue is confirmed as a container mount problem, not a code problem.
|
|
|
|
3. **After Edge Function works** — Run `yarn test:integration` and expect all 15 booking-constraints tests + all auth-session tests to pass. Fix any remaining failures (expected to be minor after the above fixes).
|
|
|
|
4. **Then**: build `/admin/reservations` view — list all upcoming reservations with boat/time/member/status; ability to confirm, cancel, or modify
|
|
|
|
5. **Then**: test full member booking flow in browser (`yarn dev`, create test intervals via admin, attempt booking as member, verify Edge Function error messages surface correctly)
|
|
|
|
## Open Questions Requiring User Input
|
|
|
|
- [ ] **Why are supabase function files not mounted in podman container?** — May require `--security-opt label=disable` or `:z` volume label for SELinux compatibility. Impacts all Edge Function development.
|
|
- [ ] **Adjacent-session double-booking (Rule 6)** — exact logic needed (carried over from previous session)
|
|
- [ ] **`useSupabaseClient` typing** — all admin pages use `as any` cast (carried over)
|
|
- [ ] **Crew requirement (Rule 8)** — not implemented (carried over)
|
|
- [ ] **PCOC / cert code strings** — values for `boats.required_certs` not defined (carried over)
|
|
|
|
## Assumptions That Need Validation
|
|
|
|
- ASSUMED: `npm:@supabase/supabase-js@2` is resolvable in the podman edge runtime container (npm cache may also be missing) — validate by getting the function to boot
|
|
- ASSUMED: `verify_jwt = false` is acceptable for production deployment (auth is validated in function code) — validate with security review before prod
|
|
- ASSUMED: `tests/tsconfig.json` approach for `@types/node` is the right fix and doesn't break other test types — validate by running full test suite
|
|
- All assumptions from previous session still apply (half-open interval semantics, ISO week definition, 2026-01-05 period epoch)
|
|
|
|
## Files to Load Next Session
|
|
|
|
- `supabase/functions/create-reservation/index.ts` — to debug boot issue or extend
|
|
- `supabase/config.toml` — to review/revert `verify_jwt` setting after boot is fixed
|
|
- `supabase/migrations/20260420170418_fix_members_rls_recursion.sql` — if RLS issues resurface
|
|
- `tests/integration/booking-constraints.test.ts` — to run and review after boot fix
|