-- Align backend owner-roster access with granular feature permissions while preserving admin/manager access. CREATE OR REPLACE FUNCTION public.has_feature_permission(_user_id uuid, _feature_area text, _action text) RETURNS boolean LANGUAGE sql STABLE SECURITY DEFINER SET search_path = public AS $$ SELECT public.has_role(_user_id, 'admin'::public.app_role) OR public.has_role(_user_id, 'manager'::public.app_role) OR EXISTS ( SELECT 1 FROM public.user_roles ur JOIN public.role_permissions rp ON rp.role = ur.role::text WHERE ur.user_id = _user_id AND rp.feature_area = _feature_area AND CASE _action WHEN 'read' THEN rp.can_read WHEN 'create' THEN rp.can_create WHEN 'edit' THEN rp.can_edit WHEN 'delete' THEN rp.can_delete ELSE false END ); $$; CREATE POLICY "Authorized users can create owners" ON public.owners FOR INSERT TO authenticated WITH CHECK (public.has_feature_permission(auth.uid(), 'Owners & Units', 'create')); CREATE POLICY "Authorized users can update owners" ON public.owners FOR UPDATE TO authenticated USING (public.has_feature_permission(auth.uid(), 'Owners & Units', 'edit')) WITH CHECK (public.has_feature_permission(auth.uid(), 'Owners & Units', 'edit')); CREATE POLICY "Authorized users can delete owners" ON public.owners FOR DELETE TO authenticated USING (public.has_feature_permission(auth.uid(), 'Owners & Units', 'delete'));