Appearance
Public Supabase bucket posture review
What happened
Jackson asked publicly in #product-eng (2026-05-11 09:18 ET) who owns these 8 public Supabase Storage buckets and why they're public:
service-experts-assetsvoice-samples— Christian: "can be private, just need to fix the one screen that reads from it"technician-portraitsbackground-souund(sic)public-client-assets— Ankur: hosts hold music for Vapi warm transfers; Vapi requires public URLs to download/play audio; no PIImr-handyman-northern-st-joseph-1066-assetscompliance-screenshots— Aditya: used to share with Twilio for A2P compliance; no sensitive PII; can move to signed URLs since assets are already wrapped in Bitlydel-air-assets
Jackson's framing: even non-PII public storage carries risk (anonymous upload = $ risk; anonymous read = customer enumeration risk) and we lose access observability. Direction is to consolidate per-customer buckets, then proxy reads through a signed-URL endpoint.
Why we care
This is not a direct incident on our work. It's the security thread to watch if our work ever touches Supabase Storage:
- If we add test-phone assets, voice samples, or any customer-specific media for the EAS engagement, the precedent is now "private bucket + signed-URL proxy", not "public bucket + direct URL".
- If we read existing hold-music for Vapi warm transfers from
public-client-assetsin any code we author, that fetch path will change when the signed-URL proxy lands. Worth watching for the API contract change.
The direction (no code change yet)
Jackson is pushing for a proxy pattern: a route like app.avoca.ai/public-client-assets/teamId/hold-music.mp4 302s to a signed URL on a private bucket. Benefits cited:
- Closes anonymous upload + read attack surface.
- Gives observability on asset access.
- Consolidates per-customer buckets to
public-client-assets/team_id/{asset}.
Open question Ankur raised: whether Vapi's hold-music fetcher works correctly with a 302 to a signed URL (worth a manual test before migrating).
Per Ankur's offer, the consolidation effort owns reducing per-customer buckets (del-air-assets, technician-portraits, mr-handyman-northern-st-joseph-1066-assets, etc.) into the consolidated bucket.
What we should mirror
- If we add any Supabase Storage usage for the EAS engagement, default to private bucket + signed-URL access via a server endpoint. No new public buckets.
- For Vapi-driven media (hold music, voice samples), confirm the playback client tolerates 302 redirects to signed URLs before assuming the proxy pattern is drop-in.
- Per-customer bucket proliferation is the antipattern; one consolidated bucket with
team_idpath segmentation is the preferred shape.
Related links
- Slack thread:
#product-eng, 2026-05-11 09:18 ET. Jackson opened; owners (Aditya, Ankur, Esteban, Christian) responded. - Vapi hold-music context: see also
[upload hold audio url using signed urls for warm transfers](https://github.com/AvocaAI/avoca-next/commit/edfa3029ce)(edfa3029ce), an earlier commit on the same theme. - Related incident: none in this set; this is a governance thread, not a defect.