Rendered from the repository — the file stays the source of truth.
Session A7 — chore/test-postgres (D-9: real Postgres for DB-backed tests)
Date: 2026-08-18 · PR: #33 · Spec: product/feasibility.md D-9
Goal and outcome
Implement D-9: retire PGlite (exit-99 under Bun, cold-WASM-init CI flakes, found by B2) and run database-backed tests against a real Postgres with real pgvector, locally and in CI, removing both INTERIM CI workarounds.
Done. 143/143 tests green (18 files), exit code 0, on both backends; zero
test files edited; PGlite dependencies removed; CI runs plain bun test
against a pgvector/pgvector:pg17 service container.
The choices D-9 left open, and how they were resolved
- Plain pgvector image vs
supabase startstack → both, each where it’s strongest. Locally tests default to the Supabase stack’s Postgres on:54322(supabase startis already the required local-dev setup — zero new commands, closest to hosted; verified the non-superuserpostgresrole can CREATE DATABASE and install pgvector 0.8.2). CI provisionspgvector/pgvector:pg17as a service container: measured 12.1 s pull (~150 MB compressed) + 3.8 s topg_isready, vs ~8 GB / 13 containers for the Supabase stack on an uncached runner. Same factory code either way;TEST_DATABASE_URLoverrides the server. - Isolation → one throwaway database per test file
(
marginalia_test_<pid>_<n>; bun runs files sequentially in one process, pid separates parallel invocations). Leftovers are swept at the start of the next run with plainDROP DATABASE(no FORCE — an in-use database from a concurrent run is skipped, not killed). Verified: 11 leftovers from a full run were all swept by the next run. - Fidelity improved, not just preserved: the factory now applies the
hand-written
enable_pgvectormigration verbatim (recreating theextensionsschema + Supabase’ssearch_pathfirst), then the Drizzle journal — PGlite had installed the extension intopublic. RLS/storage migrations stay intentionally unapplied (app-layer authz under test), unchanged.
Verification evidence
bun testvs Supabase stack: 143 pass, 0 fail, exit 0, 6.4 s.TEST_DATABASE_URL=…54329… bun testvs the CI image: 143 pass, 0 fail, exit 0, 5.8 s.bun run buildgreen,tsc --noEmitgreen.- Real-engine payoff already visible: pgvector itself rejects the
wrong-dimensionality write in
ingestion-service.test.ts(expected 2000 dimensions, not 3— that error in test output is an intentional error-path test, not a failure).
⚠️ Open item for the foreman: pre-existing lint failure gates green CI
Main’s CI has been red at the Lint step since the #28/#29 merges
(before this session): 2 × react-hooks/set-state-in-effect in
src/components/studio/audio-overview-dialog.tsx:53 and
src/components/studio/studio-panel.tsx:178, plus one unused
eslint-disable warning. Reproduced on a clean main checkout. Components
are hard out-of-bounds for A7, so PR #33’s CI stops at Lint and the Test
step never executes there — the proof of the restored exit-code contract is
the two local full-suite runs above. Once lint is fixed (owning lane, or a
two-line foreman-authorized fix), re-run CI on #33 to see the Test step
green with the service container. No workaround was reintroduced.
Boundary deviations (all flagged in the PR)
apps/webapp/package.json+bun.lock: removal of the two PGlite dev-deps (no additions).- Correct-the-record edits outside the listed files:
product/architecture/development.md(living doc, updated in place),product/history/{supabase,infrastructure}.mdand handovers A1/B2 (dated annotation blockquotes) — all described the PGlite era as current. TEST_DATABASE_URLis read with a safe default but not declared in.env.schema(file out of boundary); consider adding it as optional.
Gotchas for future sessions
- Test databases (
marginalia_test_*) linger on the local Supabase Postgres between runs by design; anybun testsweeps them, and they’re safe to drop manually.supabase db resetdoesn’t remove them. - The factory needs a role with CREATEDB on the target server; both default backends satisfy this.
- If Docker/
supabase startisn’t running, DB-backed tests fail fast with an actionable error naming the one-command fix; pure-logic tests are unaffected.