# Prisma + Supabase + PostgreSQL Complete Removal Plan

**Date:** 2026-03-28
**Goal:** Remove all Prisma, Supabase, and PostgreSQL code. Convex becomes the sole database.
**Current State:** Convex has 120+ tables, 453 functions, zero stubs. All 133 Prisma models have Convex equivalents.

---

## Pre-Conditions (Already Met)

- [x] All Convex schema tables mirror Prisma models (133/133 covered)
- [x] All Convex query/mutation functions implemented (453 functions, 0 stubs)
- [x] Convex adapter (`lib/prisma-convex-adapter.ts`) routes all `prisma.*` calls to Convex at runtime
- [x] Clerk auth integrated with Convex (`convex/auth.config.ts`)
- [x] Convex storage infrastructure exists (`convex/schema/storage.ts`, `convex/storage/`)
- [x] Nurture domain fully wired to Convex

---

## Phase 1: Kill the Dual-Write Layer (LOW RISK)

Remove the Supabase sync that fires after every Convex write. Since Convex is already the source of truth, these are redundant writes.

### 1.1 Remove `lib/dual-database.ts` (1,580 lines)

**What it does:** After every Convex write, fire-and-forget syncs data to Supabase tables.
**Why safe to remove:** Convex is the primary DB. Supabase is a read-only mirror that nobody reads from (except a few fallback paths fixed in 1.2).

**Files that import it (replace with direct Convex calls or remove sync):**
- [ ] `lib/services/knowledge-base.service.ts` — remove `syncToSupabase` calls
- [ ] `lib/services/booking.service.ts` — remove Supabase sync after demo booking create
- [ ] `lib/services/contact.service.ts` — remove `supabase: true` flag and dual-write
- [ ] `lib/services/conversation-tracker.service.ts` — remove sync comments/calls
- [ ] `lib/services/session-manager.ts` — remove sync call
- [ ] `lib/services/api-key-management.service.ts` — remove sync call
- [ ] `lib/services/interview-bookings.service.ts` — remove sync call
- [ ] `lib/services/whatsapp-knowledge-base.service.ts` — remove sync call
- [ ] `lib/services/gemini-rag.service.ts` — remove sync call
- [ ] `lib/services/whatsapp-ai-engine.service.ts` — remove sync call
- [ ] `lib/auth.ts` — remove "Sync user to Supabase" calls (~2 locations)
- [ ] `lib/stripe.ts` — remove "Sync subscription/billing to Supabase" calls
- [ ] `lib/utils/voice-agent-db.ts` — remove sync calls
- [ ] `app/api/auth/verify-signup-otp/route.ts` — remove dual-database sync
- [ ] `app/api/auth/verify-google-signup-otp/route.ts` — remove sync
- [ ] `app/api/signup/checkout/route.ts` — remove Supabase stripe_customer_id sync
- [ ] `app/api/signup/company-info/route.ts` — remove Supabase sync
- [ ] `app/api/signup/success/route.ts` — remove Supabase analytics sync
- [ ] `app/api/onboarding/company-info/route.ts` — remove Supabase users sync
- [ ] `app/api/organization/seats/add/route.ts` — remove Supabase sync
- [ ] `app/api/waitlists/route.ts` — remove dual-database sync
- [ ] `app/api/waitlists/[id]/route.ts` — remove dual-database sync
- [ ] `app/api/waitlists/[id]/signup/route.ts` — remove dual-database sync
- [ ] `app/api/waitlists/[id]/signups/route.ts` — remove dual-database sync
- [ ] `app/api/bookings/[id]/reschedule/route.ts` — remove Supabase sync
- [ ] `app/api/bookings/[id]/status/route.ts` — remove Supabase sync
- [ ] `app/api/bookings/[id]/verify-payment/route.ts` — remove sync
- [ ] `app/api/bookings/[id]/mark-paid/route.ts` — remove sync
- [ ] `app/api/staff/auth/change-password/route.ts` — remove sync
- [ ] `app/api/staff/dashboard/staff/create/route.ts` — remove sync
- [ ] `app/api/staff/dashboard/waitlists/route.ts` — remove sync
- [ ] `app/api/staff/dashboard/waitlists/[id]/signups/route.ts` — remove sync
- [ ] `app/api/careers/interview/book/route.ts` — remove sync
- [ ] Delete `lib/dual-database.ts`

### 1.2 Remove Direct Supabase Reads/Writes (bypass dual-database)

These API routes import `supabaseAdmin` directly and do Supabase queries — replace with Convex calls:

- [ ] `app/api/staff/dashboard/demos/route.ts` — replace Supabase fallback with Convex-only
- [ ] `app/api/staff/dashboard/demos/update/route.ts` — replace Supabase fallback
- [ ] `app/api/staff/dashboard/careers/interviews/route.ts` — replace Supabase import
- [ ] `app/api/staff/dashboard/careers/interviews/[id]/route.ts` — replace Supabase import
- [ ] `app/api/staff/jobs/route.ts` — remove Supabase fallback
- [ ] `app/api/staff/jobs/[id]/route.ts` — remove Supabase fallback
- [ ] `app/api/staff/applications/route.ts` — remove Supabase fallback
- [ ] `app/api/staff/applications/[id]/route.ts` — remove Supabase fallback
- [ ] `app/api/staff/users/[id]/billing/email/route.ts` — replace `supabase.from("billing_emails")` with Convex
- [ ] `app/api/staff/users/[id]/notes/route.ts` — replace `supabase.from("admin_notes")` with Convex
- [ ] `app/api/staff/users/[id]/status/route.ts` — replace `supabase.from("users")` with Convex
- [ ] `app/api/staff/users/[id]/extend-trial/route.ts` — replace Supabase with Convex
- [ ] `app/api/staff/dashboard/analytics/route.ts` — remove `fetchSupabaseStats`
- [ ] `app/api/staff/dashboard/careers/applications/[id]/send-invite/route.ts` — remove Supabase
- [ ] `lib/adapters/content.ts` — remove Supabase blog_posts CRUD, use Convex only
- [ ] `lib/queue/workers/analytics.worker.ts` — replace Supabase analytics_events write with Convex
- [ ] `lib/services/deposit-reminder.service.ts` — remove Supabase fallback
- [ ] `lib/services/demo-reminder.service.ts` — remove Supabase fallback
- [ ] `lib/services/drift-detection.service.ts` — remove Supabase comparison reads
- [ ] `components/staff/AnalyticsDashboardServer.tsx` — replace Supabase queries with Convex

### 1.3 Remove Supabase Infrastructure

- [ ] Delete `lib/supabase.ts` (conditional client init)
- [ ] Delete `lib/resilience.ts` supabaseCircuit (or remove Supabase from it)
- [ ] Remove `supabaseCircuit` from `lib/circuit-breaker.ts`
- [ ] Remove Supabase from `lib/graceful-degradation.ts`
- [ ] Remove `checkSupabaseHealth()` from `lib/health-checks.ts`
- [ ] Remove Supabase helpers from `lib/external-service-client.ts`
- [ ] Remove Supabase from `lib/staff-dashboard/demo-bookings/` (types, queries, mappers, errors, constants)
- [ ] Remove `*.supabase.co` from CSP in `middleware.ts` and `nginx/mawidi.conf`
- [ ] Remove `@supabase/supabase-js` from `package.json`
- [ ] Remove `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY` from `.env.local` and `.env.example`
- [ ] Remove `SupabaseContactSubmission` and `supabase: boolean` from `lib/types/contact.types.ts`
- [ ] Remove `SupabaseError` type from `lib/careers/types.ts`
- [ ] Remove Supabase from `lib/types/admin-panel.ts`
- [ ] Remove Supabase health display from `components/staff/dashboard/IntegrationHealthCard.tsx`
- [ ] Remove Supabase from `components/admin/AdminPanelClient.tsx` and `SystemHealthClient.tsx`
- [ ] Delete deprecated no-op service stubs (already empty): `billing-emails.service.ts` sync, `admin-notes.service.ts` sync, `user-management.service.ts` sync

**Verification:** `grep -r "supabase" --include="*.ts" --include="*.tsx" lib/ app/ components/` returns 0 results.

---

## Phase 2: Kill the Prisma Adapter Layer (MEDIUM RISK)

The adapter (`lib/prisma-convex-adapter.ts`) intercepts `prisma.*` calls and routes to Convex. We want to remove this indirection and call Convex directly.

### 2.1 Remove `lib/data-source.ts`

**What it does:** Routes domains to "prisma" or "convex" via env vars.
**Why remove:** Everything is Convex now. No routing needed.

- [ ] Delete `lib/data-source.ts`
- [ ] Remove all `getDataSource()` conditionals from any routes that check it
- [ ] Remove `DS_*` env vars from `.env.local` and `.env.example`

### 2.2 Fix Prisma Adapter Bypasses (BUGS — fix before removing adapter)

These files bypass the Convex adapter and hit real Postgres:

- [ ] **`lib/stripe.ts` lines 555, 719, 911** — 3 dynamic `import('@/lib/generated/prisma')` calls. Replace with imports from `@/lib/db` (goes through adapter) or direct Convex calls
- [ ] **`lib/db-read-replica.ts`** — creates `new PrismaClient()` for read replicas. Delete entire file (Convex handles reads)
- [ ] **`lib/services/social-inbox.service.ts` line 52** — `$queryRaw` returns `[]` (silently broken). Rewrite as Convex query
- [ ] **`lib/startup-warmup.ts` lines 89, 212, 310** — `$queryRaw SELECT 1` is a no-op. Remove or replace with Convex health check
- [ ] **`app/api/signup/success/route.ts` lines 156-175** — debug `$queryRaw` block. Remove dead code

### 2.3 Convert High-Traffic Routes from Adapter to Direct Convex (Incremental)

This is the biggest phase. 100+ API routes and 53+ services call `prisma.*` through the adapter. Convert them to call Convex directly.

**Strategy:** Work domain-by-domain, in order of risk (lowest first):

#### Wave A — Read-heavy, low-write domains (LOW RISK)
- [ ] `lib/adapters/content.ts` (26 adapters) → direct Convex calls
- [ ] `lib/adapters/reviews.ts` → direct Convex
- [ ] `lib/adapters/analytics.ts` → direct Convex
- [ ] `lib/services/blog-management.service.ts` → direct Convex
- [ ] All `app/api/` routes for content, reviews, analytics

#### Wave B — Isolated domains (LOW RISK)
- [ ] `lib/adapters/careers.ts` → direct Convex
- [ ] `lib/adapters/expenses.ts` → direct Convex
- [ ] `lib/services/expenses.service.ts` → direct Convex
- [ ] `lib/careers/queries.ts` → direct Convex
- [ ] All `app/api/` routes for careers, expenses

#### Wave C — CRM core (MEDIUM RISK)
- [ ] `lib/adapters/leads.ts` → direct Convex
- [ ] `lib/adapters/social.ts` → direct Convex
- [ ] `lib/adapters/customers.ts` → direct Convex
- [ ] `lib/services/lead-crm.service.ts` and related lead services → direct Convex
- [ ] `lib/services/contact.service.ts` → direct Convex
- [ ] All `app/api/` routes for leads, social, customers

#### Wave D — Active features (MEDIUM RISK)
- [ ] `lib/adapters/support.ts` → direct Convex
- [ ] `lib/adapters/real-estate.ts` → direct Convex
- [ ] `lib/adapters/whatsapp.ts` → direct Convex
- [ ] `lib/adapters/voice-agents.ts` → direct Convex
- [ ] `lib/adapters/workflows.ts` → direct Convex
- [ ] All `app/api/` routes for support, real-estate, whatsapp, voice-agents, workflows

#### Wave E — Core business (HIGH RISK)
- [ ] `lib/adapters/bookings.ts` → direct Convex
- [ ] `lib/adapters/notifications.ts` → direct Convex
- [ ] `lib/adapters/quotations.ts` → direct Convex
- [ ] `lib/services/booking.service.ts` → direct Convex
- [ ] `lib/services/quotations.service.ts` → direct Convex
- [ ] All `app/api/bookings/`, `app/api/dashboard/` routes

#### Wave F — Payments & Identity (CRITICAL — most careful)
- [ ] `lib/adapters/billing.ts` → direct Convex
- [ ] `lib/adapters/organizations.ts` → direct Convex
- [ ] `lib/adapters/auth.ts` → direct Convex
- [ ] `lib/stripe.ts` — replace all `prisma.*` calls with direct Convex
- [ ] `lib/auth.ts` — replace all `prisma.*` calls with direct Convex
- [ ] `lib/clerk-user-bridge.ts` → direct Convex
- [ ] `lib/otp-helper.ts` → direct Convex
- [ ] `lib/staff-session.ts` → direct Convex
- [ ] `lib/services/billing-service.ts` → direct Convex
- [ ] `lib/services/organization.service.ts` → direct Convex
- [ ] All `app/api/auth/`, `app/api/billing/`, `app/api/stripe/` routes

### 2.4 Delete the Adapter

After all waves complete:
- [ ] Delete `lib/prisma-convex-adapter.ts` (1,253 lines)
- [ ] Delete `lib/db.ts` (re-create as a simple Convex client export if needed)
- [ ] Delete `lib/db-read-replica.ts`
- [ ] Delete entire `lib/adapters/` directory (26 files)

**Verification:** `grep -r "from.*@/lib/db" --include="*.ts" --include="*.tsx" lib/ app/` returns 0 results for prisma imports.

---

## Phase 3: Remove Prisma Entirely (LOW RISK after Phase 2)

### 3.1 Delete Prisma Files
- [ ] Delete `prisma/schema.prisma` (119KB)
- [ ] Delete `prisma/prisma.config.ts`
- [ ] Delete `prisma/migrations/` (all migration SQL files)
- [ ] Delete `lib/generated/prisma/` (entire generated client directory)

### 3.2 Remove Prisma Dependencies
- [ ] Remove `prisma` from `package.json` devDependencies
- [ ] Remove `@prisma/client` from `package.json` dependencies
- [ ] Remove `prisma generate` from any build scripts
- [ ] Run `npm install` to clean `package-lock.json`

### 3.3 Clean Up Type Imports
Files that import types from `lib/generated/prisma` — replace with Convex types or inline:
- [ ] `lib/services/notifications.service.ts` — `Prisma`, `NotificationType`
- [ ] `lib/services/lead-nurture.service.ts` — `Prisma`
- [ ] `lib/services/social-calendar.service.ts` — `type { Prisma }`
- [ ] `lib/services/dlq-management.service.ts` — `type { Prisma }`
- [ ] `lib/services/lead-crm.service.ts` — `Prisma`
- [ ] `lib/services/deals.service.ts` — `Prisma`
- [ ] `lib/services/lead-capture.service.ts` — `Prisma`
- [ ] `lib/services/lead-qualification.service.ts` — `Prisma`
- [ ] `lib/services/lead-scoring.service.ts` — `Prisma`
- [ ] `lib/utils/auth-helpers.util.ts` — `type { Prisma }`
- [ ] `lib/cache/redis-cache.ts` — `type { users }`

### 3.4 Remove `prismaId` References (Convex schema migration artifact)

The `prismaId` field exists in 50+ Convex tables and is used for backward-compatible ID lookups. Plan:
- [ ] **Keep `prismaId` in Convex schema for now** — it's a Convex-internal field, costs nothing, and some Convex queries still use it for lookups
- [ ] After all routes are on direct Convex calls and using Convex `_id` natively, create a cleanup task to remove `prismaId` fields (separate PR, low priority)

### 3.5 Remove `DATABASE_URL`
- [ ] Remove `DATABASE_URL` from `.env.local`
- [ ] Remove `DATABASE_URL` from `.env.example`
- [ ] Remove `DATABASE_URL` from `.env.docker` and `.env.docker.example`
- [ ] Remove `DATABASE_URL` from `docker-compose.yml` app service environment
- [ ] Remove `DATABASE_URL` validation from `__tests__/infrastructure/env-validation.test.ts`
- [ ] Remove `DATABASE_URL` mock from `jest.setup.js`

---

## Phase 4: Remove Docker PostgreSQL (LOW RISK after Phase 3)

### 4.1 Docker Compose
- [ ] Remove `postgres` service from `docker-compose.yml` (lines 2-13)
- [ ] Remove `postgres_data` volume from `docker-compose.yml`
- [ ] Remove `pg_isready` healthcheck
- [ ] Remove `postgres` service from `docker-compose.preview.yml`
- [ ] Remove `depends_on: postgres` from app service

### 4.2 Docker Entrypoint
- [ ] Remove `require('pg')` connectivity test from `docker-entrypoint.sh`
- [ ] Remove `npx prisma migrate deploy` from `docker-entrypoint.sh`
- [ ] Remove `DATABASE_URL` check from `docker-entrypoint.sh`
- [ ] Remove Supabase table init from `docker-entrypoint.sh`

### 4.3 Remove `pg` Package
- [ ] Remove `pg` from `package.json` dependencies
- [ ] Run `npm install`

---

## Phase 5: Clean Up Dead Code (LOW RISK)

### 5.1 Delete Dead Scripts (~40 files)
All scripts that use `new PrismaClient()`, `psql`, `pg_dump`, or direct Supabase:

**Migration scripts (one-time, already executed):**
- [ ] `scripts/migrate-wave1-to-convex.ts`
- [ ] `scripts/backfill-auth-org-billing-to-convex.ts`
- [ ] `scripts/migrate-users-to-clerk.ts`
- [ ] `scripts/migrate-to-organizations.ts`
- [ ] `scripts/migrate-storage-to-convex.ts`
- [ ] `scripts/migrate-blog-posts.ts`
- [ ] `scripts/run-migration.ts`
- [ ] `scripts/apply-company-profiles-migration.ts`
- [ ] `scripts/create-company-profiles-table.ts`

**Seed scripts (replace with Convex seeders if needed):**
- [ ] `scripts/seed-all.ts`
- [ ] `scripts/seed-nurture-sequences.ts`
- [ ] `scripts/seed-database.ts`
- [ ] `scripts/seed-test-jobs.ts`
- [ ] `scripts/seed-demo-bookings.ts`
- [ ] `scripts/seed-blog-posts.ts`
- [ ] `scripts/seed-sample-jobs.sql`

**Diagnostic/verification scripts:**
- [ ] `scripts/verify-session-sync.mjs`
- [ ] `scripts/test-session-creation.mjs`
- [ ] `scripts/check-user-subscription.mjs`
- [ ] `scripts/sync-queue-stats.mjs`
- [ ] `scripts/create-super-admin.ts`
- [ ] `scripts/create-stripe-products-and-save.js`
- [ ] `scripts/verify-organization-migration.ts`
- [ ] `scripts/verify-user-data.ts`
- [ ] `scripts/verify-signup-database.ts`
- [ ] `scripts/test-dual-database-save.ts`
- [ ] `scripts/test-otp-table.ts`
- [ ] `scripts/test-demo-confirmation-email.ts`
- [ ] `scripts/check-database-users.ts`
- [ ] `scripts/check-database-health.sh`
- [ ] `scripts/backup-database.sh`
- [ ] `scripts/diagnose-account.sh`
- [ ] `scripts/test-api-database-save.sh`
- [ ] `scripts/run-all-database-tests.sh`
- [ ] `scripts/quick-db-validation.sh`
- [ ] `scripts/verify-fix.sh`
- [ ] `scripts/start-dev-environment.sh`
- [ ] `scripts/apply-all-migrations.sh`
- [ ] `scripts/test-careers-staff-dashboard.sh`
- [ ] `scripts/test-contact-form.sh`
- [ ] `scripts/validate-docker-separation.sh`
- [ ] `scripts/migrate-to-separated-docker.sh`
- [ ] `scripts/init-all-supabase-tables.sh`
- [ ] `scripts/create-remaining-supabase-tables.ts`
- [ ] `scripts/create-job-cvs-bucket.ts`
- [ ] `scripts/check-supabase-schema.mjs`
- [ ] `scripts/validate-careers-setup.mjs`
- [ ] `scripts/check-blog-images.ts`
- [ ] `scripts/test-rls-policies.ts`
- [ ] `scripts/test-cv-upload.ts`
- [ ] `scripts/test-company-info-api.js`
- [ ] `scripts/test-company-info-with-session.js`
- [ ] `scripts/test-google-oauth.sh`
- [ ] `scripts/add-subscription-composite-index.sql`
- [ ] `scripts/verify-rls-policies.sql`
- [ ] Various `scripts/fix-*.mjs`, `scripts/recover-*.mjs`, `scripts/process-*.mjs`, `scripts/diagnose-*.mjs`

### 5.2 Update/Delete Tests

**Tests using `pg` directly (delete or rewrite for Convex):**
- [ ] `tests/contact-form-regression.spec.ts`
- [ ] `tests/staff-contacts-dashboard.spec.ts`
- [ ] `tests/contact-to-dashboard-flow.spec.ts`
- [ ] `tests/contact-form-integration.spec.ts`
- [ ] `tests/e2e/signup-session-creation.spec.ts`
- [ ] `tests/e2e/test-real-signup-e2e.spec.ts`
- [ ] `tests/e2e/database-sync.spec.ts`
- [ ] `tests/signup-package-flow.spec.ts`
- [ ] `__tests__/database/data-sync-verification.test.ts`
- [ ] `__tests__/database/supabase-schema-integrity.test.ts`
- [ ] `__tests__/database/signup-data-flow.test.ts`
- [ ] `__tests__/database/relationships.test.ts`
- [ ] `__tests__/database/outbox-crash-recovery.test.ts`
- [ ] `__tests__/database/signup-data-persistence.test.ts`
- [ ] `__tests__/database/schema-validation.test.ts`
- [ ] `__tests__/database/company-info-constraints.test.ts`

**Test helpers/mocks to delete:**
- [ ] `tests/helpers/database-helpers.ts` (references `$executeRawUnsafe`, `$queryRaw`)
- [ ] `tests/helpers/supabase-test-utils.ts`
- [ ] `tests/e2e/test-helpers.ts` (Supabase client creation)
- [ ] `__mocks__/lib/supabase.js`
- [ ] `__mocks__/lib/db.js`

**Test config to update:**
- [ ] `jest.config.js` — remove Supabase module alias, remove `DATABASE_URL` mock
- [ ] `jest.setup.js` — remove `DATABASE_URL` mock
- [ ] `.github/workflows/database-tests.yml` — remove Postgres service, update for Convex

**Tests with Supabase mocks (update mocks to remove Supabase refs):**
- [ ] ~25 test files in `__tests__/` that mock `supabaseAdmin` — remove mock setup

### 5.3 Fix Misleading Comments

- [ ] `app/api/onboarding/dismiss/route.ts` — remove "Update in PostgreSQL" comment
- [ ] `app/api/onboarding/complete/route.ts` — remove "Update in PostgreSQL" comment
- [ ] `app/api/onboarding/company-info/route.ts` — remove "Update user record... in Prisma (PostgreSQL)" comment
- [ ] `app/api/demo/book/route.ts` — remove "Prisma/PostgreSQL is the PRIMARY database" comment
- [ ] Search for all "PostgreSQL", "Postgres", "Supabase", "Prisma" in comments and clean up

### 5.4 Remove Supabase from Git Hooks and CI

- [ ] `.husky/pre-commit` — remove Supabase migration checks, schema integrity test
- [ ] `.husky/pre-push` — remove Supabase running check
- [ ] `.github/workflows/database-tests.yml` — rewrite for Convex-only testing

### 5.5 Delete Backup Files

- [ ] `backups/database/` — old `pg_dump` outputs (keep archive elsewhere if needed)

### 5.6 Remove Unused Config

- [ ] Remove `prisma generate` / `prisma migrate` from any npm scripts in `package.json`
- [ ] Remove Prisma-related entries from `next.config.mjs`
- [ ] Remove `lib/generated/` from `.gitignore` entries related to Prisma
- [ ] Remove `instrumentation.ts` `prismaMs` startup metric reference

---

## Phase 6: Final Verification

- [ ] `npx tsc --noEmit` — zero TypeScript errors
- [ ] `npm run lint` — zero lint errors
- [ ] `npm run test` — all tests pass
- [ ] `grep -ri "prisma" --include="*.ts" --include="*.tsx" --include="*.js" lib/ app/ components/` — 0 results (except `prismaId` in Convex)
- [ ] `grep -ri "supabase" --include="*.ts" --include="*.tsx" --include="*.js" lib/ app/ components/` — 0 results
- [ ] `grep -ri "DATABASE_URL" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.sh" --include="*.yml"` — 0 results
- [ ] `grep -ri "import.*pg" --include="*.ts" --include="*.tsx" --include="*.js" lib/ app/` — 0 results
- [ ] Dev server starts cleanly on port 9000
- [ ] Staff dashboard loads at `/staff/dashboard`
- [ ] User signup flow works end-to-end
- [ ] Stripe webhook processes correctly
- [ ] `npx convex deploy --dry-run` succeeds

---

## Execution Summary

| Phase | Description | Files Changed | Lines Removed (est.) | Risk |
|-------|-------------|---------------|---------------------|------|
| 1 | Kill dual-write + Supabase | ~60 files | ~3,000 | Low |
| 2 | Remove Prisma adapter layer | ~180 files | ~5,000 | Medium |
| 3 | Delete Prisma files/deps | ~15 files | ~120,000 (generated) | Low |
| 4 | Remove Docker PostgreSQL | ~5 files | ~100 | Low |
| 5 | Clean dead code | ~80 files | ~8,000 | Low |
| 6 | Verification | 0 files | 0 | N/A |
| **Total** | | **~340 files** | **~136,000 lines** | |

---

## Parallelization Strategy

**Can run simultaneously:**
- Phase 1.1 (dual-write removal) + Phase 5.1 (delete dead scripts)
- Within Phase 2.3, Waves A-B can run in parallel (independent domains)
- Phase 3 + Phase 4 can run together (after Phase 2)

**Must be sequential:**
- Phase 1 before Phase 2 (Supabase removal before adapter removal)
- Phase 2 waves E-F must be last (critical business logic)
- Phase 6 after everything else

---

## Rollback Plan

If issues arise after deployment:
1. **Phase 1 rollback:** Re-enable Supabase env vars. The dual-write code can be reverted from git.
2. **Phase 2 rollback:** The Prisma adapter is a shim — reverting to it requires restoring `lib/db.ts` and `lib/prisma-convex-adapter.ts` from git.
3. **No Postgres data loss:** Convex has been the source of truth throughout. Postgres/Supabase were mirrors.
4. **Git tags:** Create a git tag `pre-prisma-removal` before starting Phase 1.
