fix(deploy): add health/db-schema guard + curl gate; ship migration assets; document prod bootstrap (executed per systematic-debugging plan)
Deploy to route.crispygoat.com / deploy (push) Has been cancelled
Deploy to route.crispygoat.com / deploy (push) Has been cancelled
This commit is contained in:
@@ -101,6 +101,33 @@ The app connects to **Postgres directly** — no Supabase platform, JS client, o
|
||||
- A single shared `pg` `Pool` is exported from `src/lib/db.ts` (TBD — to be created/confirmed during the migration). Server actions and API routes import it and call `pool.query(...)` against RPC names.
|
||||
- No `NEXT_PUBLIC_SUPABASE_URL` / `SUPABASE_SERVICE_ROLE_KEY` / `@supabase/*` imports — these are being purged from the codebase.
|
||||
|
||||
#### First production deploy / new prod DB bootstrap (critical for admin access)
|
||||
|
||||
The `admin_users` + `admin_user_brands` tables (and the rest of the schema) come **only** from `db/migrations/0001_init.sql`.
|
||||
|
||||
If the prod `DATABASE_URL` has never had the migrations applied, `getAdminUser()` will fail with "relation \"admin_users\" does not exist", the layout will show "Access Denied", and even a signed-in Neon Auth user will be blocked.
|
||||
|
||||
**Correct bootstrap sequence (do this from a machine with the full source tree before the first push that exercises /admin):**
|
||||
|
||||
1. Ensure the Gitea secret `DATABASE_URL` points at the real prod Neon Postgres (the one with `neon_auth.user` already present).
|
||||
2. Sign in once at the live prod URL (`/login`) with the email you want as the first `platform_admin`. This creates the row in `neon_auth.user`.
|
||||
3. From your laptop (or any box with the checkout):
|
||||
|
||||
```bash
|
||||
# Paste the real prod connection string (get it from Gitea secrets or the target's .env.production)
|
||||
DATABASE_URL="postgresql://...prod-full-string..." node scripts/migrate.js
|
||||
|
||||
# Then provision (the script will link to the first brand it finds)
|
||||
DATABASE_URL="postgresql://...prod-full-string..." \
|
||||
npx tsx scripts/provision-admin.ts you@real.com platform_admin
|
||||
```
|
||||
|
||||
4. Push to main. The deploy workflow now has a hard gate (see `.gitea/workflows/deploy.yml` "Run migrations" + verification query for `admin_users`) and ships the migrate runner + SQL files, so future deploys and server-side recovery are protected.
|
||||
|
||||
See the full root-cause + plan: `docs/superpowers/plans/2026-06-prod-db-schema-migration-reliability.md`
|
||||
|
||||
The old `|| echo` masking around `npm run migrate:one` has been removed; a missing critical table will now fail the CI job with a clear message.
|
||||
|
||||
#### SECURITY DEFINER RPCs + Brand Scoping
|
||||
|
||||
The app uses **PostgreSQL SECURITY DEFINER functions** for all data access. These run with the function owner's privileges and bypass any future RLS. This means:
|
||||
|
||||
Reference in New Issue
Block a user