The rule lives in the database
A private record has an owner; a shared record has a home. Reading the home goes through a function that checks whether you are an active member right now. Leaving the home cuts access at once. The tests take on the identity of two people in sequence and plant personal "canaries" to check they stay private after those people join the same home.
create function public.is_own_active_house_member(p_house_id uuid)
returns boolean language sql stable security definer set search_path = '' as $$
select exists (
select 1 from public.house_members as member
where member.house_id = p_house_id
and member.user_id = auth.uid()
and member.left_at is null);
$$;
create policy house_tasks_select_active_member on public.house_tasks
for select to authenticated
using (public.is_own_active_house_member(house_id));
