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:
@@ -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.
|
||||
Reference in New Issue
Block a user