Skip to content

feat(prisma): Prisma 7 config + DIRECT_URL fallback (Supabase Phase 1) - #764

Merged
LucasSantana-Dev merged 8 commits into
mainfrom
feature/supabase-phase1-direct-url
Apr 22, 2026
Merged

LucasSantana-Dev merged 8 commits into
mainfrom
feature/supabase-phase1-direct-url

Conversation

@LucasSantana-Dev

Copy link
Copy Markdown
Owner

Summary

Phase 1 of the Supabase migration — see full plan at
.claude/plans/supabase-migration-2026-04-21.md.

Prisma 7 removed the `url` and `directUrl` fields from `schema.prisma`'s
datasource block. Everything now lives in `prisma.config.ts`. This PR
migrates that config to the v7 `defineConfig` helper and adds a
`DIRECT_URL` fallback chain so local docker-compose dev keeps working.

What changed

  • `prisma/prisma.config.ts`: plain-object export → `defineConfig({ ... })`; datasource URL sourced from `DIRECT_URL ?? DATABASE_URL`.

What did not change

  • `prisma/schema.prisma` — already has only `provider` in its datasource block; nothing to do.
  • Runtime Prisma client (`packages/shared/src/utils/database/prismaClient.ts`) still uses `DATABASE_URL` via the `PrismaPg` adapter. Unchanged.

Deployment note

Supabase deployments must set both envs in prod / staging:

  • `DATABASE_URL` — Supabase Session pooler (5432, session mode) — long-lived bot connections.
  • `DIRECT_URL` — Supabase direct (non-pooled) connection — Prisma CLI / `migrate deploy`.

Local docker-compose devs don't need to change anything; the fallback picks `DATABASE_URL` when `DIRECT_URL` is unset.

Known follow-up

  • `.env.example` should document `DIRECT_URL` alongside `DATABASE_URL`. The local `protect-files.sh` hook blocks automated edits to `.env*` files, so that update needs a human pass. It is not required for this PR to merge — existing devs are unaffected.

Test plan

  • `prisma validate` passes on the schema (runtime unchanged).
  • CI: Quality Gates, SonarCloud, Security, portability.
  • After merge: provision `DIRECT_URL` for prod `lucky-prod` (ref `uhfpqqraxlicmquejkkz`, region `sa-east-1`) and staging `lucky-staging` (ref `cirywcaamzqbujrdsfvu`) projects that already exist but have no data.

🤖 Generated with Claude Code

…llback

Supabase migration Phase 1 (plan: .claude/plans/supabase-migration-2026-04-21.md).

Prisma 7 removed the `url` and `directUrl` fields from the schema's
datasource block — they now live in prisma.config.ts. Migrating the
existing config to the v7 defineConfig helper and teaching it to prefer
DIRECT_URL when present, falling back to DATABASE_URL so current local
docker-compose dev (single Postgres, single URL) keeps working.

Supabase deployments must set both:
- DATABASE_URL: Session pooler (5432, session mode) — runtime via
  PrismaPg adapter in packages/shared/src/utils/database/prismaClient.ts
- DIRECT_URL: direct non-pooled connection — Prisma CLI for migrations

Follow-up (blocked by local hook on .env*): add DIRECT_URL to
.env.example with the same documentation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Apr 22, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Apr 22, 2026 6:19am

Request Review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 56 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 15 minutes and 56 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: db9168f0-123c-4662-b5ca-147bb9d53a62

📥 Commits

Reviewing files that changed from the base of the PR and between a7d2422 and 22e2589.

📒 Files selected for processing (1)
  • prisma/prisma.config.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/supabase-phase1-direct-url

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit ee2f05f into main Apr 22, 2026
12 checks passed
LucasSantana-Dev added a commit that referenced this pull request Apr 22, 2026
Cites five MIT-licensed patterns from garrytan/gstack@54d4cde
(RLS-first client auth, progressive RLS tightening, column-level GRANT,
edge-function cached reads, deploy-time RLS smoke test) as reference
material for the in-flight Supabase migration (PR #764).

Reference only — no code ported. Full attribution in footer.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request Apr 22, 2026
… 2) (#768)

* feat(prisma): flatten migration history into single baseline (Supabase Phase 2)

Supabase migration Phase 2 (plan: .claude/plans/supabase-migration-2026-04-21.md;
preview: .claude/plans/supabase-phase2-preview-2026-04-22.md).

## Why

`prisma migrate deploy` against a fresh Postgres fails on migration #1
(20250128120000_add_twitch_notifications) because it assumes `guilds`
and 20+ other tables already exist. Those tables were originally
created by `prisma db push` in the pre-2025 era and never captured as
a migration. Self-hosted prod has them; a fresh Supabase project
doesn't.

Two paths to fix: (A) add a baseline migration that creates the
pre-existing tables, keeping the 18 historical migrations as later
steps, or (B) flatten everything into one baseline and drop the 18.

## What this PR does — option B, flatten

- Generates `prisma/migrations/20250101000000_baseline/migration.sql`
  via `prisma migrate diff --from-empty --to-schema=prisma/schema.prisma`.
  864 lines of DDL: 1 schema, 1 enum, all tables in schema.prisma,
  every index, every FK constraint.
- Deletes the 18 historical migration folders. Their schema state is
  entirely subsumed by the baseline.

## Deployment note — self-hosted prod needs one `migrate resolve`

After merge, on the self-hosted prod DB (not on Supabase which has no
data yet):

```
DIRECT_URL=<self-hosted-prod> npx prisma migrate resolve \
  --applied 20250101000000_baseline
```

This inserts a single row into `_prisma_migrations` marking the
baseline as applied without running the SQL (which would collide with
existing tables). The 18 orphaned historical rows stay but are
harmless — Prisma ignores entries without corresponding folders.

## Deployment note — Supabase

On fresh `lucky-prod` / `lucky-staging`:

```
DIRECT_URL=<supabase-direct> npx prisma migrate deploy
```

Single baseline applies, schema matches `schema.prisma`. Done.

## Test plan

- [x] `prisma migrate diff` ran clean against schema.prisma.
- [x] Generated SQL scanned for credentials — none found (only column
      names like `accessToken` / `refreshToken` — Spotify link table).
- [ ] CI: Quality Gates, SonarCloud, Security.
- [ ] Merge blocker: depends on PR #764 (Prisma 7 `prisma.config.ts`)
      being merged first so Prisma CLI knows to use `DIRECT_URL`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(prisma): enable RLS on all public tables (no policies = default-deny)

Supabase exposes the public schema via PostgREST's anon / authenticated
roles by default, which tripped 39 ERROR-level `rls_disabled_in_public`
advisor lints. Enable RLS on every table; don't add policies. Bot and
backend use the postgres role which bypasses RLS, so behavior is
unchanged. PostgREST traffic (anon/authenticated) is now default-deny.

On non-Supabase self-hosted Postgres this is still safe: ENABLE RLS
without any policies means only the owning role (our single DB user)
can read/write, which matches current behavior.

Applied live via Supabase MCP to both lucky-prod (uhfpqqraxlicmquejkkz)
and lucky-staging (cirywcaamzqbujrdsfvu) this session. Advisor lints
now INFO-level (`rls_enabled_no_policy`) instead of ERROR.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request Apr 22, 2026
PR #764 introduces DIRECT_URL for Prisma CLI (migrate / db push). On
Supabase, DATABASE_URL points at the Session pooler for the runtime
Prisma client, while DIRECT_URL is the non-pooled host used by the
CLI (the pooler cannot open shadow DBs). Document both with inline
examples so new contributors know which URL goes where.

Does not change any runtime behavior. Does not touch real secrets.
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
…llback (#764)

Supabase migration Phase 1 (plan: .claude/plans/supabase-migration-2026-04-21.md).

Prisma 7 removed the `url` and `directUrl` fields from the schema's
datasource block — they now live in prisma.config.ts. Migrating the
existing config to the v7 defineConfig helper and teaching it to prefer
DIRECT_URL when present, falling back to DATABASE_URL so current local
docker-compose dev (single Postgres, single URL) keeps working.

Supabase deployments must set both:
- DATABASE_URL: Session pooler (5432, session mode) — runtime via
  PrismaPg adapter in packages/shared/src/utils/database/prismaClient.ts
- DIRECT_URL: direct non-pooled connection — Prisma CLI for migrations

Follow-up (blocked by local hook on .env*): add DIRECT_URL to
.env.example with the same documentation.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
Cites five MIT-licensed patterns from garrytan/gstack@54d4cde
(RLS-first client auth, progressive RLS tightening, column-level GRANT,
edge-function cached reads, deploy-time RLS smoke test) as reference
material for the in-flight Supabase migration (PR #764).

Reference only — no code ported. Full attribution in footer.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
… 2) (#768)

* feat(prisma): flatten migration history into single baseline (Supabase Phase 2)

Supabase migration Phase 2 (plan: .claude/plans/supabase-migration-2026-04-21.md;
preview: .claude/plans/supabase-phase2-preview-2026-04-22.md).

## Why

`prisma migrate deploy` against a fresh Postgres fails on migration #1
(20250128120000_add_twitch_notifications) because it assumes `guilds`
and 20+ other tables already exist. Those tables were originally
created by `prisma db push` in the pre-2025 era and never captured as
a migration. Self-hosted prod has them; a fresh Supabase project
doesn't.

Two paths to fix: (A) add a baseline migration that creates the
pre-existing tables, keeping the 18 historical migrations as later
steps, or (B) flatten everything into one baseline and drop the 18.

## What this PR does — option B, flatten

- Generates `prisma/migrations/20250101000000_baseline/migration.sql`
  via `prisma migrate diff --from-empty --to-schema=prisma/schema.prisma`.
  864 lines of DDL: 1 schema, 1 enum, all tables in schema.prisma,
  every index, every FK constraint.
- Deletes the 18 historical migration folders. Their schema state is
  entirely subsumed by the baseline.

## Deployment note — self-hosted prod needs one `migrate resolve`

After merge, on the self-hosted prod DB (not on Supabase which has no
data yet):

```
DIRECT_URL=<self-hosted-prod> npx prisma migrate resolve \
  --applied 20250101000000_baseline
```

This inserts a single row into `_prisma_migrations` marking the
baseline as applied without running the SQL (which would collide with
existing tables). The 18 orphaned historical rows stay but are
harmless — Prisma ignores entries without corresponding folders.

## Deployment note — Supabase

On fresh `lucky-prod` / `lucky-staging`:

```
DIRECT_URL=<supabase-direct> npx prisma migrate deploy
```

Single baseline applies, schema matches `schema.prisma`. Done.

## Test plan

- [x] `prisma migrate diff` ran clean against schema.prisma.
- [x] Generated SQL scanned for credentials — none found (only column
      names like `accessToken` / `refreshToken` — Spotify link table).
- [ ] CI: Quality Gates, SonarCloud, Security.
- [ ] Merge blocker: depends on PR #764 (Prisma 7 `prisma.config.ts`)
      being merged first so Prisma CLI knows to use `DIRECT_URL`.

* feat(prisma): enable RLS on all public tables (no policies = default-deny)

Supabase exposes the public schema via PostgREST's anon / authenticated
roles by default, which tripped 39 ERROR-level `rls_disabled_in_public`
advisor lints. Enable RLS on every table; don't add policies. Bot and
backend use the postgres role which bypasses RLS, so behavior is
unchanged. PostgREST traffic (anon/authenticated) is now default-deny.

On non-Supabase self-hosted Postgres this is still safe: ENABLE RLS
without any policies means only the owning role (our single DB user)
can read/write, which matches current behavior.

Applied live via Supabase MCP to both lucky-prod (uhfpqqraxlicmquejkkz)
and lucky-staging (cirywcaamzqbujrdsfvu) this session. Advisor lints
now INFO-level (`rls_enabled_no_policy`) instead of ERROR.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
PR #764 introduces DIRECT_URL for Prisma CLI (migrate / db push). On
Supabase, DATABASE_URL points at the Session pooler for the runtime
Prisma client, while DIRECT_URL is the non-pooled host used by the
CLI (the pooler cannot open shadow DBs). Document both with inline
examples so new contributors know which URL goes where.

Does not change any runtime behavior. Does not touch real secrets.
@LucasSantana-Dev
LucasSantana-Dev deleted the feature/supabase-phase1-direct-url branch May 14, 2026 02:02

This branch was successfully deployed

1 active deployment
Preview — 22e2589c Deployed Apr 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant