Each analysis run now creates a dedicated folder in Supabase Storage:
clinics/{domain}/{reportId}/
├── scrape_data.json (discover-channels: website scrape + Perplexity)
├── channel_data.json (collect-channel-data: all channel API results)
└── report.json (generate-report: final AI-generated report)
Screenshots also moved from {reportId}/{id}.png to:
clinics/{domain}/{reportId}/screenshots/{id}.png
Migration: 20260407_clinic_data_storage.sql creates 'clinic-data' bucket
(private, 10MB/file, JSON only). All writes are non-fatal — pipeline
continues even if Storage upload fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
37 lines
1.2 KiB
SQL
37 lines
1.2 KiB
SQL
-- clinic-data bucket: JSON text data per clinic URL analysis run
|
|
-- Structure: clinics/{domain}/{reportId}/
|
|
-- ├── scrape_data.json (discover-channels output)
|
|
-- ├── channel_data.json (collect-channel-data output)
|
|
-- └── report.json (generate-report output)
|
|
|
|
INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
|
VALUES (
|
|
'clinic-data',
|
|
'clinic-data',
|
|
false, -- private: requires service_role key
|
|
10485760, -- 10 MB per file
|
|
ARRAY['application/json']
|
|
)
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- RLS: only service_role can read/write (backend-to-backend)
|
|
CREATE POLICY "service_role read clinic-data"
|
|
ON storage.objects FOR SELECT
|
|
TO service_role
|
|
USING (bucket_id = 'clinic-data');
|
|
|
|
CREATE POLICY "service_role insert clinic-data"
|
|
ON storage.objects FOR INSERT
|
|
TO service_role
|
|
WITH CHECK (bucket_id = 'clinic-data');
|
|
|
|
CREATE POLICY "service_role update clinic-data"
|
|
ON storage.objects FOR UPDATE
|
|
TO service_role
|
|
USING (bucket_id = 'clinic-data');
|
|
|
|
-- screenshots bucket: update allowed_mime_types to include PNG/JPEG/WebP (idempotent)
|
|
UPDATE storage.buckets
|
|
SET allowed_mime_types = ARRAY['image/png', 'image/jpeg', 'image/webp']
|
|
WHERE id = 'screenshots';
|