fix(#929): let the monolithic migration provision a newly-created Supabase project - #930
Merged
Merged
Conversation
…abase project
Applying supabase/migrations/20251006_complete_monolithic_setup.sql to a project
created today aborted with
42501: permission denied for schema auth
and, because the file is one BEGIN;...COMMIT;, left ZERO tables. Forking is
supposed to end with the fork pointing at its own Supabase project, so this broke
the one path every fork must take.
One statement needed CREATE on schema auth:
CREATE OR REPLACE FUNCTION auth.jwt() ...
It exists only to forward-fill a stub for the LOCAL supabase/postgres image, where
GoTrue has not booted and CREATE POLICY would otherwise fail at parse time. That
reasoning is correct and still applies, so the statement is guarded rather than
removed -- it now runs only where auth.jwt() is genuinely absent. Identical local
behaviour; a no-op on Cloud, where the function already exists and is owned by
supabase_auth_admin.
Not the cause, though it looks like it: the on_auth_user_created trigger on
auth.users is fine. postgres holds TRIGGER on that table, verified by a create/drop
probe on a fresh project, and the trigger is present there after the fix.
Verified end to end on a genuinely new project (us-east-1): 19 tables and 75
policies, identical counts to this repo's production project, plus 25 functions and
13 triggers.
Also adds scripts/__tests__/migration-provisions-a-new-cloud-project.test.js, which
splits the file into real top-level statements -- dollar-quote aware, comments
stripped -- and fails if any of them creates or alters an object inside the auth
schema. It carries its own falsifiers: auth.uid() in a policy body and a trigger ON
auth.users must NOT trip it, a commented-out copy of the old statement must NOT trip
it, and an unguarded CREATE ... auth.jwt() MUST. Mutation-tested against the real
file: reverting the guard fails the suite, restoring it passes byte-identical.
Closes #929
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #929.
The one path every fork must take was the one path nothing tested
Applying
supabase/migrations/20251006_complete_monolithic_setup.sqlto a project created today aborts with42501: permission denied for schema auth, and because the file is a singleBEGIN; … COMMIT;, leaves zero tables. Forking is supposed to end with the fork pointing at its own Supabase project; it could not.Found while giving
TortoiseWolfe/geolarpits own backend (geolarp PR #20).Cause: one statement, needed only by the local profile
It forward-fills a stub for the local
supabase/postgresimage, where GoTrue has not booted andCREATE POLICYwould fail at parse time — that reasoning is still correct, so the statement is guarded, not removed. It now runs only whereauth.jwt()is genuinely absent: identical locally, no-op on Cloud.auth.jwt()existssupabase_auth_admin)postgreshasUSAGEon authpostgreshasCREATEon authpostgrescannot work around it: not a superuser, andSET ROLE supabase_auth_adminis denied.Not the cause, though it looks like it: the
on_auth_user_createdtrigger onauth.usersis fine —postgresholdsTRIGGERthere (verified with a create/drop probe), and it is present on the new project after the fix.Verified on a genuinely new project
The regression guard, and why it is trustworthy
scripts/__tests__/migration-provisions-a-new-cloud-project.test.jssplits the file into real top-level statements — dollar-quote aware, comments stripped — and fails if one creates or alters an object inside theauthschema.It ships with its own falsifiers, because a guard that greps source has bitten this repo repeatedly:
CREATE … auth.jwt()must be caught ✅auth.uid()in aCREATE POLICYbody must not trip it (97 mentions) ✅CREATE TRIGGER … ON auth.usersmust not trip it ✅Mutation-tested against the real file, not just synthetic strings: reverting the guard fails the suite, restoring it passes, file byte-identical.
What this does not fix
Nothing here provisions a throwaway project in CI — that would cost a slot on a two-project account. The failure is fully determined by the SQL text, so the text is what is checked. If a future statement needs a Cloud privilege
postgreslacks in some other schema, this test will not see it.