-- Products, services, availability schedule, bookings, inquiries, and the -- public booked_slots mirror. See docs/superpowers/specs/2026-08-08-phase2-backend-foundation-supabase-design.md. create table public.products ( id text primary key, name text not null, category text not null check (category in ('hair-care', 'extensions', 'tools', 'accessories')), price numeric not null, image text not null, description text not null, in_stock boolean not null default true ); create table public.services ( id text primary key, name text not null, duration_minutes integer not null, price_from numeric not null, description text not null, image text not null ); create table public.schedule_template ( id text primary key default 'default', working_days integer[] not null, start_time time not null, end_time time not null, slot_minutes integer not null ); create table public.schedule_exceptions ( date date primary key, closed boolean not null, note text ); create table public.bookings ( id uuid primary key default gen_random_uuid(), service_id text not null references public.services(id), date date not null, time text not null, contact_name text not null, contact_phone text not null, contact_email text not null, contact_notes text not null default '', status text not null default 'confirmed' check (status in ('confirmed', 'cancelled')), created_at timestamptz not null default now() ); create index bookings_service_id_idx on public.bookings (service_id); create table public.booked_slots ( date date not null, time text not null, primary key (date, time) ); create table public.inquiries ( id uuid primary key default gen_random_uuid(), product_id text not null references public.products(id), contact_name text not null, contact_email text not null, contact_notes text not null default '', status text not null default 'new' check (status in ('new', 'read')), created_at timestamptz not null default now() ); create index inquiries_product_id_idx on public.inquiries (product_id); -- Row Level Security alter table public.products enable row level security; alter table public.services enable row level security; alter table public.schedule_template enable row level security; alter table public.schedule_exceptions enable row level security; alter table public.bookings enable row level security; alter table public.booked_slots enable row level security; alter table public.inquiries enable row level security; -- products: public read, admin write create policy "products_public_read" on public.products for select using (true); create policy "products_admin_write" on public.products for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- services: public read, admin write create policy "services_public_read" on public.services for select using (true); create policy "services_admin_write" on public.services for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- schedule_template: public read, admin write create policy "schedule_template_public_read" on public.schedule_template for select using (true); create policy "schedule_template_admin_write" on public.schedule_template for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- schedule_exceptions: public read, admin write create policy "schedule_exceptions_public_read" on public.schedule_exceptions for select using (true); create policy "schedule_exceptions_admin_write" on public.schedule_exceptions for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- bookings: anyone can insert (submit a booking); only admin can read/update/delete create policy "bookings_public_insert" on public.bookings for insert with check (true); create policy "bookings_admin_all" on public.bookings for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- booked_slots: public read; only admin policy exists for writes (in practice only -- the security-definer trigger in the next migration ever writes here) create policy "booked_slots_public_read" on public.booked_slots for select using (true); create policy "booked_slots_admin_write" on public.booked_slots for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid); -- inquiries: anyone can insert; only admin can read/update/delete create policy "inquiries_public_insert" on public.inquiries for insert with check (true); create policy "inquiries_admin_all" on public.inquiries for all using ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid) with check ((select auth.uid()) = '21c90224-e0b2-412e-a431-8e7f097c1cef'::uuid);