-- 010_challenge_files_bucket.sql -- Supabase Storage bucket for AI-generated challenge files -- (the fileToGenerate payload some generators return). The Python backend -- uploads the file and returns the public URL in the training payload, -- so NOTHING is ever written to the backend's local filesystem. BEGIN; INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types) VALUES ( 'challenge-files', 'challenge-files', true, 5242880, -- 5 MB max ARRAY[ 'text/plain', 'text/x-log', 'text/csv', 'text/html', 'text/xml', 'application/json', 'application/octet-stream', 'image/png', 'image/jpeg', 'image/gif', 'image/svg+xml', 'application/x-pem-file', 'application/x-sh', 'application/x-yaml' ] ) ON CONFLICT (id) DO UPDATE SET public = EXCLUDED.public, file_size_limit = EXCLUDED.file_size_limit, allowed_mime_types = EXCLUDED.allowed_mime_types; -- Public read for everyone (same posture as log-analysis-files) DROP POLICY IF EXISTS "Public read challenge-files" ON storage.objects; CREATE POLICY "Public read challenge-files" ON storage.objects FOR SELECT USING (bucket_id = 'challenge-files'); -- Backend can upload (service-role key bypasses RLS anyway, but we -- allow anon INSERT for the SUPABASE_ANON_KEY path too). DROP POLICY IF EXISTS "Service role upload challenge-files" ON storage.objects; CREATE POLICY "Service role upload challenge-files" ON storage.objects FOR INSERT WITH CHECK (bucket_id = 'challenge-files'); DROP POLICY IF EXISTS "Service role delete challenge-files" ON storage.objects; CREATE POLICY "Service role delete challenge-files" ON storage.objects FOR DELETE USING (bucket_id = 'challenge-files'); COMMIT;