Harden public.profiles and bootstrap it for fresh databases - #177
Conversation
- Reject role changes and non-default roles on insert unless the caller is already an admin; previously any signed-in user could promote themselves. - Stop exposing profiles.email to anon and authenticated; admins keep reading it through get_admin_users_list(). - Recreate public.profiles, guarded, in the first migration that references it, so migrations apply to a database built from the repo alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Updates to Preview Branch (fix/profiles-hardening) ↗︎
Tasks are run on every commit but only new migration files are pushed.
View logs for this Workflow Run ↗︎. |
Summary
Reading the production definition of
public.profiles(to close task 2 indev-plans/supabase-pending-work-2026-08.md) showed two holes. Both are already fixed in production (applied 2026-09-16 and recorded as version20260916000000); this PR brings the repo in line.roletoadmin.update_profiles_combinedallows updating your own row, and the API roles held UPDATE on every column. The INSERT policy had the same gap.BEFORE INSERT OR UPDATE OF roletrigger rejects any non-default role unless the caller is already an admin. Onlyanon/authenticatedare checked, so the dashboard,service_roleand security definer functions are unaffected.anoncould read every user's e-mail (Public profilesisusing (true)).email. Admins still get e-mail fromget_admin_users_list()(security definer).Supabase Previewfailed on every PR touchingsupabase/, becauseprofileswas never defined in the migrations.20260613000001mirrors the production table, constraints, RLS and policies. It is a no-op where the table exists.The admin dashboard's fallback query no longer selects
email. The currently deployed bundle still does; it only logs an error, and the users list still loads from the RPC.The audit log shows no role changes, and role counts are as expected.
Verification
emailis blocked foranonandauthenticated.select=email→ 401,select=*→ 401;PATCH role→ 401.pnpm typecheckpasses.Note:
select('*')onprofilesnow fails for clients, so name the columns. No current code does this.🤖 Generated with Claude Code