create table if not exists public.company_members ( id uuid default gen_random_uuid() primary key, company_id uuid references public.companies(id) on delete cascade not null, profile_id uuid references public.profiles(id) on delete cascade not null, created_at timestamptz default now() not null, unique(company_id, profile_id) ); alter table public.company_members enable row level security; insert into public.company_members (company_id, profile_id) select company_id, id from public.profiles where company_id is not null on conflict (company_id, profile_id) do nothing; create or replace function public.has_company_access(company uuid) returns boolean as $$ select exists ( select 1 from public.profiles p where p.id = auth.uid() and ( p.company_id = company or exists ( select 1 from public.company_members cm where cm.profile_id = auth.uid() and cm.company_id = company ) ) ); $$ language sql security definer stable; drop policy if exists "Team all company_members" on public.company_members; drop policy if exists "Users read own company memberships" on public.company_members; create policy "Team all company_members" on public.company_members for all using (get_my_role() = 'team') with check (get_my_role() = 'team'); create policy "Users read own company memberships" on public.company_members for select using (profile_id = auth.uid()); drop policy if exists "Client reads own company" on public.companies; drop policy if exists "Client updates own company" on public.companies; create policy "Client reads assigned companies" on public.companies for select using (has_company_access(id)); create policy "Client updates primary company" on public.companies for update using (id = get_my_company_id()) with check (id = get_my_company_id()); drop policy if exists "Client reads company projects" on public.projects; drop policy if exists "Client inserts company projects" on public.projects; drop policy if exists "Client updates own company projects" on public.projects; create policy "Client reads assigned company projects" on public.projects for select using (has_company_access(company_id)); create policy "Client inserts assigned company projects" on public.projects for insert with check (get_my_role() = 'client' and has_company_access(company_id)); create policy "Client updates assigned company projects" on public.projects for update using (get_my_role() = 'client' and has_company_access(company_id)) with check (get_my_role() = 'client' and has_company_access(company_id)); drop policy if exists "Client reads company tasks" on public.tasks; drop policy if exists "Client insert task" on public.tasks; drop policy if exists "Client updates company tasks" on public.tasks; create policy "Client reads assigned company tasks" on public.tasks for select using ( project_id in (select id from public.projects where has_company_access(company_id)) ); create policy "Client inserts assigned company tasks" on public.tasks for insert with check ( get_my_role() = 'client' and project_id in (select id from public.projects where has_company_access(company_id)) ); create policy "Client updates assigned company tasks" on public.tasks for update using ( get_my_role() = 'client' and project_id in (select id from public.projects where has_company_access(company_id)) ) with check ( get_my_role() = 'client' and project_id in (select id from public.projects where has_company_access(company_id)) ); drop policy if exists "Client reads company submissions" on public.submissions; drop policy if exists "Client inserts submissions" on public.submissions; create policy "Client reads assigned company submissions" on public.submissions for select using ( task_id in ( select t.id from public.tasks t join public.projects p on p.id = t.project_id where has_company_access(p.company_id) ) ); create policy "Client inserts assigned company submissions" on public.submissions for insert with check ( get_my_role() = 'client' and submitted_by = auth.uid() and task_id in ( select t.id from public.tasks t join public.projects p on p.id = t.project_id where has_company_access(p.company_id) ) ); drop policy if exists "Client reads company submission_files" on public.submission_files; drop policy if exists "Client inserts submission_files" on public.submission_files; create policy "Client reads assigned company submission_files" on public.submission_files for select using ( submission_id in ( select s.id from public.submissions s join public.tasks t on t.id = s.task_id join public.projects p on p.id = t.project_id where has_company_access(p.company_id) ) ); create policy "Client inserts assigned company submission_files" on public.submission_files for insert with check ( get_my_role() = 'client' and submission_id in ( select s.id from public.submissions s join public.tasks t on t.id = s.task_id join public.projects p on p.id = t.project_id where has_company_access(p.company_id) and s.submitted_by = auth.uid() ) ); drop policy if exists "Client reads company deliveries" on public.deliveries; create policy "Client reads assigned company deliveries" on public.deliveries for select using ( submission_id in ( select s.id from public.submissions s join public.tasks t on t.id = s.task_id join public.projects p on p.id = t.project_id where has_company_access(p.company_id) ) ); drop policy if exists "Client reads company delivery_files" on public.delivery_files; create policy "Client reads assigned company delivery_files" on public.delivery_files for select using ( delivery_id in ( select d.id from public.deliveries d join public.submissions s on s.id = d.submission_id join public.tasks t on t.id = s.task_id join public.projects p on p.id = t.project_id where has_company_access(p.company_id) ) ); drop policy if exists "Client reads own company prices" on public.company_prices; create policy "Client reads assigned company prices" on public.company_prices for select using (has_company_access(company_id)); drop policy if exists "Client reads company invoices" on public.invoices; create policy "Client reads assigned company invoices" on public.invoices for select using (has_company_access(company_id)); drop policy if exists "Client reads company invoice_items" on public.invoice_items; create policy "Client reads assigned company invoice_items" on public.invoice_items for select using ( invoice_id in (select id from public.invoices where has_company_access(company_id)) );