chore(supabase): full purge — remove all Supabase references from codebase

- Delete supabase/ directory (config.toml, push-migrations.js,
  ADMIN_CREATE_STOP_FIX.sql, 137 archived migration files)
- Remove @supabase/ssr and @supabase/supabase-js from package.json
- Strip *.supabase.co from next.config.ts image hostnames
- Strip https://*.supabase.co from vercel.json CSP connect-src
- Remove 'supabase/**' ignore from eslint.config.mjs
- Clean supabase references from src/lib/db.ts, vitest.config.ts,
  db/seeds/2026-tuxedo-tour-stops.sql, src/actions/storefront.ts,
  scripts/import-tuxedo-stops.ts comments
- Rewrite env-var docs in README, ENVIRONMENT, PRODUCTION_SETUP,
  PRODUCTION_DEPLOYMENT_CHECKLIST, LAUNCH_CHECKLIST, CLAUDE,
  MEMORY, REPORT to drop NEXT_PUBLIC_SUPABASE_URL /
  SUPABASE_SERVICE_ROLE_KEY / supabase link / supabase CLI references

The canonical migration runner is now scripts/migrate.js (uses pg
directly via DATABASE_URL). Migrations live in db/migrations/. The
Supabase CLI is no longer in the codebase. The only remaining
'@supabase/*' in the dep tree is @supabase/auth-js as a transitive
of @neondatabase/auth (Neon Auth / Better Auth).

Final source scan: grep -rln '@supabase\|rest/v1\|supabase\.co'
src/ tests/ db/ scripts/ next.config.ts vercel.json eslint.config.mjs
package.json returns zero. Verification: npm install clean
(11 added, 21 removed, 12 changed), tsc shows same 17 pre-existing
errors (Stripe dahlia API version + fetch preconnect mocks),
vitest 172/175 (3 pre-existing failures in getAdminUser.test.ts),
lint shows same 14 pre-existing errors. Live-tested: dev server
boots in 248ms, public storefronts (/) (/login) (/pricing) (/tuxedo)
(/indian-river-direct) all return 200; /admin/v2?demo=1 reaches 200
after dev_session redirect; storefront renders real brand content.
This commit is contained in:
Nora
2026-06-25 17:48:32 -06:00
parent 68a749f7af
commit 49b8e27219
171 changed files with 136 additions and 28594 deletions
+20 -25
View File
@@ -2,7 +2,7 @@
**Platform Version:** 1.6
**Last Updated:** 2026-05-13
**Environment:** Next.js 16 (App Router) · Supabase · Stripe · Square · Resend · FedEx
**Environment:** Next.js 16 (App Router) · Postgres (direct via `pg`) · Neon Auth (Better Auth) · Stripe · Square · Resend · FedEx
---
@@ -11,14 +11,14 @@
Apply migrations in number order. All numbered `001``092` are required.
```bash
# Push all migrations (sequential)
# Push all migrations (sequential, no Supabase CLI required)
npm run migrate:one 001
npm run migrate:one 002
# ... through ...
npm run migrate:one 092
# Or push all at once via Supabase CLI
supabase db push
# Or push all at once
npm run migrate
```
**Key migrations (last 15):**
@@ -53,10 +53,11 @@ Copy `.env.local.example` to `.env.local` and fill in all values.
| Variable | Required | Description |
|---|---|---|
| `NEXT_PUBLIC_SUPABASE_URL` | Yes | Supabase project URL (e.g., `https://xxx.supabase.co`) |
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Yes | Supabase anon/public key (safe to expose in browser) |
| `SUPABASE_SERVICE_ROLE_KEY` | Yes | Supabase service role key — **never expose in browser**, server-side only |
| `SUPABASE_PAT` | Yes | Supabase Personal Access Token for migrations CLI |
| `DATABASE_URL` | Yes | Postgres connection string (e.g., `postgresql://user:pass@host:5432/dbname?sslmode=require`) |
| `DATABASE_ADMIN_URL` | No | Direct (non-pooled) Postgres connection with elevated perms. Only used by `scripts/migrate.js` for DDL — falls back to `DATABASE_URL` if unset. |
| `NEON_AUTH_BASE_URL` | Yes | Neon Auth (Better Auth) base URL |
| `NEON_AUTH_COOKIE_SECRET` | Yes | Neon Auth session cookie signing secret (min 32 chars) |
| `NEXT_PUBLIC_SITE_URL` | Yes | Public site URL used for auth redirects and Origin header |
### Payments
@@ -198,17 +199,13 @@ For scheduled tasks (stop reminders, campaign sends), add to `vercel.json` or co
}
```
**Note:** Stop reminder emails are triggered by a Supabase time-based trigger (`send_stop_reminder_email`). Verify the trigger is active:
```sql
SELECT * FROM pg_publication_tables WHERE tablename = 'stops';
```
If not, recreate: `ALTER PUBLICATION supabase_realtime PUBLISH INSERT, UPDATE ON TABLE stops;`
**Note:** Stop reminder emails are fired by Vercel cron jobs (`/api/cron/send-stop-reminders`), not by a database trigger. Verify the cron is configured in `vercel.json` (or Vercel Dashboard → Project → Cron Jobs).
---
## 5. Feature Flag Enablement (Post-Deploy)
After deployment, enable add-ons per brand via the admin UI or Supabase SQL:
After deployment, enable add-ons per brand via the admin UI or direct Postgres:
```sql
-- Enable Harvest Reach for a brand
@@ -302,13 +299,13 @@ Vercel keeps 10 recent deployments. For critical regressions, promote the previo
### Database Rollback
```bash
# Revert last migration via Supabase
supabase db reset --backup-id <backup-before-migration>
# Revert last migration via Postgres
# (Restore from a `pg_dump` snapshot taken before the migration was applied)
# Or manually revert (example for migration 090)
psql $DATABASE_URL -c "ALTER TABLE brand_settings DROP COLUMN IF EXISTS schedule_pdf_notes;"
```
> **Important:** Only use `supabase db reset` on staging. In production, manually revert individual migrations to avoid data loss.
> **Important:** Always restore from a known-good backup. In production, manually revert individual migrations to avoid data loss.
### Environment Variable Rollback
Environment variables are version-controlled in Vercel. Restore a previous version in **Vercel Dashboard → Project → Environment Variables → History**.
@@ -318,16 +315,16 @@ Environment variables are version-controlled in Vercel. Restore a previous versi
## 8. Known Limitations & Future Work
### Known Issues
- **`dev_session` auth**: The `dev_session` cookie bypasses real Supabase auth. In production, ensure no `dev_session` cookie exists for regular users. The auth bypass only works when `NODE_ENV !== "production"`.
- **`dev_session` auth**: The `dev_session` cookie bypasses real Neon Auth (Better Auth). In production, ensure no `dev_session` cookie exists for regular users. The auth bypass only works when `NODE_ENV !== "production"`.
- **Water Log visible to all brand admins**: Currently Tuxedo-only by brand ID check. If another brand admin needs access, the check needs to be made configurable.
- **Communications tables (no RLS)**: `communication_campaigns`, `communication_templates`, `communication_contacts`, `communication_message_logs` have RLS disabled. All data access is through SECURITY DEFINER RPCs. Do not expose these tables via direct Supabase queries.
- **Communications tables (no RLS)**: `communication_campaigns`, `communication_templates`, `communication_contacts`, `communication_message_logs` have no row-level policies. All data access is through SECURITY DEFINER RPCs. Do not expose these tables via direct SQL from client-side code.
- **`event_id` not populated in message logs**: `send_campaign` and `send_stop_blast` do not set `event_id`. The Resend webhook looks up logs by `customer_email + subject` instead. This is a known limitation — if Resend events are delayed, the lookup may fail to match.
- **Square sync is one-directional**: Products import from Square → Route Commerce, but product edits in Route Commerce do not push back to Square.
- **SMS opt-in defaults to `FALSE`**: `communication_contacts.sms_opt_in` defaults to `false`. Users must explicitly opt in for SMS campaigns.
- **`brand_id: null` for platform admins**: `getAdminUser()` returns `brand_id: null` for `platform_admin` role. Always pass explicit `brandId` to server action functions.
- **Square webhook signature mismatch**: The Square webhook handler uses `crypto.createHmac("sha256", signatureKey)` but Square sends the signature as base64-encoded. Verify signature encoding matches Square's documentation before enabling Square webhooks in production.
- **Stripe webhook reliability**: Stripe webhook delivery is not guaranteed to be in-order or immediate. The webhook handler is idempotent — it can safely receive duplicate events. Consider implementing a webhook event log table to track processed event IDs for deduplication.
- **`NO_RLS` communications tables**: All communications data is accessible via SECURITY DEFINER RPCs only — never expose direct Supabase queries to these tables in client-side code.
- **`NO_RLS` communications tables**: All communications data is accessible via SECURITY DEFINER RPCs only — never expose direct SQL to these tables in client-side code.
### Future Work (Non-Blocking)
- **Cursor-based pagination**: Replace offset-based pagination (`page * limit`) with cursor-based pagination for large datasets (orders, contacts)
@@ -344,11 +341,9 @@ Environment variables are version-controlled in Vercel. Restore a previous versi
| Role | Contact |
|------|---------|
| Platform Admin | Set via Supabase Auth dashboard |
| Platform Admin | First Neon Auth user becomes the platform admin via `provision-admin.ts` |
| Kyle Martinez | Primary contact — Route Commerce owner |
| Supabase Support | supabase.com/support |
| Neon Support | neon.tech/support |
| Vercel Support | vercel.com/support |
For Vercel production incidents: **vercel.com/deployments** → find deployment → "Support" button.
For Supabase production incidents: **supabase.com/dashboard** → project → "Support" tab.
For Vercel production incidents: **vercel.com/deployments** → find deployment → "Support" button.