-- Follow guardrails: prevent self-follow and block-based follows create or replace function request_follow(target_id uuid) returns text language plpgsql security definer as $$ declare existing_status text; target_private boolean; target_official boolean; new_status text; begin if auth.uid() is null then raise exception 'Not authenticated'; end if; if target_id is null then raise exception 'Target profile not found'; end if; if auth.uid() = target_id then raise exception 'Cannot follow yourself'; end if; select status into existing_status from follows where follower_id = auth.uid() and following_id = target_id; if existing_status is not null then return existing_status; end if; select is_private, is_official into target_private, target_official from profiles where id = target_id; if target_private is null then raise exception 'Target profile not found'; end if; if target_official or target_private = false then new_status := 'accepted'; else new_status := 'pending'; end if; insert into follows (follower_id, following_id, status) values (auth.uid(), target_id, new_status); return new_status; end; $$;