-- Pinned messages: each conversation gets up to 5 anchored references to its -- own messages. Any accepted member can pin/unpin. RLS mirrors conversation -- membership; the cap is enforced by a BEFORE INSERT trigger because partial -- unique indexes can't express "at most N rows per group". create table if not exists public.pinned_messages ( conversation_id uuid not null references public.conversations(id) on delete cascade, message_id uuid not null references public.messages(id) on delete cascade, pinned_by uuid not null references auth.users(id) on delete set null, pinned_at timestamptz not null default now(), primary key (conversation_id, message_id) ); create index if not exists pinned_messages_conv_idx on public.pinned_messages(conversation_id, pinned_at desc); alter table public.pinned_messages enable row level security; drop policy if exists pinned_messages_select_member on public.pinned_messages; create policy pinned_messages_select_member on public.pinned_messages for select to authenticated using (public.is_conversation_member(conversation_id)); drop policy if exists pinned_messages_insert_member on public.pinned_messages; create policy pinned_messages_insert_member on public.pinned_messages for insert to authenticated with check ( public.is_conversation_member(conversation_id) and pinned_by = auth.uid() ); drop policy if exists pinned_messages_delete_member on public.pinned_messages; create policy pinned_messages_delete_member on public.pinned_messages for delete to authenticated using (public.is_conversation_member(conversation_id)); -- Enforce the per-conversation cap. Trigger-based so cross-row counts work. create or replace function public.pinned_messages_enforce_cap() returns trigger language plpgsql as $$ begin if (select count(*) from public.pinned_messages where conversation_id = new.conversation_id) >= 5 then raise exception 'pinned_messages_cap_reached: at most 5 pins per conversation'; end if; return new; end; $$; drop trigger if exists pinned_messages_cap on public.pinned_messages; create trigger pinned_messages_cap before insert on public.pinned_messages for each row execute function public.pinned_messages_enforce_cap(); alter publication supabase_realtime add table public.pinned_messages;