-- QA-027 follow-up: task_attachments storage writes were open to the `public` -- role, i.e. UNAUTHENTICATED users could upload, overwrite, and delete task -- attachments (worse than the it_service_attachments delete hole). The bucket -- stays public for reads (bucket.public = true, unchanged); lock down writes: -- * INSERT: any authenticated user (uploads happen while signed in) -- * UPDATE/DELETE: the uploader (objects.owner) or a task-privileged role -- The read policy ("task attachments policy 6srt2u_0") is left untouched. DROP POLICY IF EXISTS "task attachments policy 6srt2u_1" ON storage.objects; -- was INSERT/public CREATE POLICY "task_attachments_insert" ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'task_attachments'); DROP POLICY IF EXISTS "task attachments policy 6srt2u_2" ON storage.objects; -- was UPDATE/public CREATE POLICY "task_attachments_update" ON storage.objects FOR UPDATE TO authenticated USING ( bucket_id = 'task_attachments' AND ( owner = auth.uid() OR EXISTS (SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin', 'programmer', 'dispatcher', 'it_staff')) ) ) WITH CHECK ( bucket_id = 'task_attachments' AND ( owner = auth.uid() OR EXISTS (SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin', 'programmer', 'dispatcher', 'it_staff')) ) ); DROP POLICY IF EXISTS "task attachments policy 6srt2u_3" ON storage.objects; -- was DELETE/public CREATE POLICY "task_attachments_delete" ON storage.objects FOR DELETE TO authenticated USING ( bucket_id = 'task_attachments' AND ( owner = auth.uid() OR EXISTS (SELECT 1 FROM public.profiles p WHERE p.id = auth.uid() AND p.role IN ('admin', 'programmer', 'dispatcher', 'it_staff')) ) );