October 27, 2026
Private CDN buckets and organization files, with signed delivery through /cdn
Uploads can stay private. Organization files get staging, access scopes, and cleanup. Private downloads go through an HMAC /cdn proxy so the response can set nosniff — something raw R2 signed URLs cannot do.
- Bucket visibility is public or private. Private buckets have no publicUrl. getFileUrl fails for them on purpose.
- organizationFiles is an internal module features call after their own scope checks. It owns staging keys, TTLs, locks, and content-type allowlists — not GraphQL and not scopes.
- Private R2 downloads use the HMAC /cdn proxy with CDN_SIGNED_URL_SECRET so X-Content-Type-Options: nosniff lands on the response. Production smoke asserts it.