BEGIN; ALTER TABLE public.push_dispatch_attempts ADD COLUMN actor_kind text NOT NULL DEFAULT 'user' CHECK (actor_kind IN ('user', 'system')); ALTER TABLE public.push_dispatch_attempts ALTER COLUMN caller_id DROP NOT NULL, ADD CONSTRAINT push_dispatch_attempt_actor_check CHECK ( (actor_kind = 'user' AND caller_id IS NOT NULL) OR (actor_kind = 'system' AND caller_id IS NULL) ); CREATE INDEX idx_push_dispatch_attempts_system_event ON public.push_dispatch_attempts(event_type, resource_id, created_at DESC) WHERE actor_kind = 'system'; CREATE OR REPLACE FUNCTION public.reserve_system_push_dispatch( push_event_type text, push_resource_id uuid ) RETURNS jsonb LANGUAGE plpgsql SECURITY DEFINER SET search_path = '' AS $$ DECLARE normalized_event_type text := lower(btrim(push_event_type)); existing_attempt_id uuid; created_attempt_id uuid; BEGIN IF auth.role() <> 'service_role' THEN RAISE EXCEPTION 'service_role_required' USING ERRCODE = '42501'; END IF; IF push_resource_id IS NULL OR normalized_event_type NOT IN ( 'transcription.completed', 'team.invite.created', 'billing.status.changed' ) THEN RAISE EXCEPTION 'invalid_push_event' USING ERRCODE = '22023'; END IF; PERFORM pg_advisory_xact_lock( hashtextextended(normalized_event_type || ':' || push_resource_id::text, 73049) ); SELECT attempt.id INTO existing_attempt_id FROM public.push_dispatch_attempts AS attempt WHERE attempt.actor_kind = 'system' AND attempt.event_type = normalized_event_type AND attempt.resource_id = push_resource_id AND attempt.created_at > now() - interval '30 seconds' ORDER BY attempt.created_at DESC LIMIT 1; IF existing_attempt_id IS NOT NULL THEN RETURN jsonb_build_object( 'reserved', false, 'duplicate', true, 'attempt_id', existing_attempt_id ); END IF; INSERT INTO public.push_dispatch_attempts ( caller_id, actor_kind, event_type, resource_id ) VALUES ( NULL, 'system', normalized_event_type, push_resource_id ) RETURNING id INTO created_attempt_id; RETURN jsonb_build_object( 'reserved', true, 'duplicate', false, 'attempt_id', created_attempt_id ); END; $$; REVOKE ALL ON FUNCTION public.reserve_system_push_dispatch(text, uuid) FROM PUBLIC, anon, authenticated; GRANT EXECUTE ON FUNCTION public.reserve_system_push_dispatch(text, uuid) TO service_role; COMMIT;