b20145c215
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
36 lines
1.6 KiB
SQL
36 lines
1.6 KiB
SQL
-- ---------------------------------------------------------------
|
|
-- 022 — public_profiles (A1 Session 10, public ledger profiles v1).
|
|
--
|
|
-- Stage-3 seed: a user may claim a handle and publish their ENTIRE settled
|
|
-- ledger record on a public page — wins and misses. Strava for betting.
|
|
--
|
|
-- PRIVACY: PRIVATE BY DEFAULT. `published` defaults false and only flips
|
|
-- via one explicit toggle in Settings. The profile API returns the SAME
|
|
-- 404 for an unknown handle and an unpublished one (no existence leak).
|
|
--
|
|
-- All writes go through the service role (the /api/profiles/me route).
|
|
-- Clients only read: published rows (anyone) + their own row (owner).
|
|
-- ---------------------------------------------------------------
|
|
|
|
CREATE TABLE IF NOT EXISTS public.public_profiles (
|
|
user_id uuid PRIMARY KEY REFERENCES auth.users (id) ON DELETE CASCADE,
|
|
handle text UNIQUE NOT NULL CHECK (handle ~ '^[a-z0-9_]{3,20}$'),
|
|
published boolean NOT NULL DEFAULT false,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.public_profiles ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Anyone (anon + authenticated) reads PUBLISHED profiles only.
|
|
CREATE POLICY public_profiles_select_published ON public.public_profiles
|
|
FOR SELECT TO anon, authenticated
|
|
USING (published = true);
|
|
|
|
-- The owner reads their own row (published or not).
|
|
CREATE POLICY public_profiles_select_own ON public.public_profiles
|
|
FOR SELECT TO authenticated
|
|
USING (user_id = auth.uid());
|
|
|
|
-- No INSERT/UPDATE/DELETE policies: client-side writes are impossible.
|
|
-- The API writes via the service role, which bypasses RLS.
|