Skip to main content

max / makenotwork

sando: grant PUBLIC usage/create on scratch public schema after reset migration_dry_run restores the prod backup (tables owned by makenotwork) into sando_scratch, then runs pending migrations. reset_scratch recreates `public` owned by the connecting role (sando) with no grant to anyone else. An INSERT whose FK check Postgres runs as the *referencing table's* owner (makenotwork) then fails with "permission denied for schema public" (surfaced by migration 165's sync_app_usage_current backfill). Granting USAGE, CREATE to PUBLIC on the freshly-created scratch schema restores the pre-PG15 default the app migrations assume — safe: the DB is disposable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-08 20:33 UTC
Commit: 2139df659493d9c81119e320e8694f7b8c2de410
Parent: 463e2a5
1 file changed, +9 insertions, -0 deletions
@@ -358,6 +358,15 @@ pub(crate) async fn reset_scratch(db_url: &str) -> Result<()> {
358 358 EXECUTE format('DROP SCHEMA IF EXISTS %I CASCADE', s);
359 359 END LOOP;
360 360 EXECUTE 'CREATE SCHEMA public';
361 + -- Restore the pre-PG15 public-schema default on the throwaway
362 + -- scratch DB. Without this, the freshly-created public is owned by
363 + -- the connecting role (sando) with no grant to anyone else, so a
364 + -- migration's FK/trigger check that Postgres runs as a *restored*
365 + -- prod-owned table's owner (e.g. makenotwork from the backup dump)
366 + -- fails with "permission denied for schema public". Granting to
367 + -- PUBLIC is role-agnostic and safe here — this DB is disposable and
368 + -- exists only to dry-run migrations.
369 + EXECUTE 'GRANT USAGE, CREATE ON SCHEMA public TO PUBLIC';
361 370 END $$;
362 371 "#,
363 372 )