diff --git a/supabase/migrations/20260807002000_reporting_view_fixes.sql b/supabase/migrations/20260807002000_reporting_view_fixes.sql index d9f9511..297fd65 100644 --- a/supabase/migrations/20260807002000_reporting_view_fixes.sql +++ b/supabase/migrations/20260807002000_reporting_view_fixes.sql @@ -4,28 +4,17 @@ -- fact when it is really an absence. None of them widens what anyone may see. -- ============================================================================ --- 1. A billing administrator could not read their own receivables report +-- 0. Recognising a caller that bypasses RLS -- ============================================================================ -- --- v_billing_detail joined public.students purely to build a display name, but --- can_access_student() admits org admins, auditors, parents, a student's own --- teacher and campus staff — and NOT billing admins, even though the invoices --- policy grants them every invoice in the organisation. The inner join then --- dropped every row, so the receivables report came back empty for exactly the --- role that exists to run it, with no error to explain why. --- --- The tempting fix is to add is_billing_admin() to can_access_student(). That --- would also hand finance staff allergies, chronic_conditions, special_needs, --- disciplinary_history, custody_agreement and primary_physician, which they --- have no business reading. So the name is resolved on its own instead, and --- student row access is left exactly as it was. --- True for callers that bypass RLS outright: the service role used by --- server-side code, and a direct superuser psql session (role unset). +-- True for the service role used by server-side code, and for a direct +-- superuser psql session (where `role` is unset). -- -- This MUST read the `role` GUC rather than current_user. Inside a -- SECURITY DEFINER function current_user is the function's owner, so -- pg_has_role(current_user, 'service_role', ...) is true for every caller and --- silently turns an entitlement check into a no-op. +-- silently turns an entitlement check into a no-op — which is exactly the trap +-- the checks below would otherwise fall into. CREATE OR REPLACE FUNCTION public.is_service_context() RETURNS BOOLEAN LANGUAGE sql STABLE AS $$