Access, links and delivery
Who can upload, download and delete: bucket rules and their fields, public and signed URLs and how long links last, caching and bandwidth, what image transformations do today, and files in HIPAA projects.
Bucket rules
Each bucket's Policies tab holds its rules (access policies named [bucket:<name>] …). Presets cover the usual cases; you can write your own with these fields (Policy language (SPL)):
| Field | Value |
|---|---|
ctx.action | READ (download), LIST, WRITE (upload, replace, move in), DELETE |
ctx.resource.name | The bucket |
ctx.storage.path | The file's path in the bucket |
ctx.storage.folder | The path's first folder |
ctx.storage.in_own_folder | True when that folder is the caller's user id |
ctx.actor.* | Who is calling (How access is decided) |
# Signed-in users manage their own folder; anyone signed in may read "shared/"
ALLOW IF ctx.resource.name == "documents" AND ctx.storage.in_own_folder == True
ALLOW IF ctx.resource.name == "documents" AND ctx.action IN ["READ", "LIST"] AND ctx.storage.folder == "shared" AND ctx.actor.is_anonymous == False- With no rule for a bucket, only the public flag decides: anyone may read a public bucket; app users get nothing from a private one.
- Creating, deleting a bucket, making it public or changing its limits is administration: app users need the
adminapp role for it, whatever the file rules say. - The Security advisor flags buckets without rules (Security advisor).
Public URLs
Files in a public bucket have a permanent URL anyone can open, without a key:
const url = sovaria.storage.publicUrl('product-images', 'shoes/runner-01.webp')
// https://<project-ref>.sovarias.in/api/v1/store/public/<project-id>/product-images/shoes/runner-01.webpUse public buckets only for files meant for everyone (product images, logos). Anyone who knows or guesses a path can download it.
Signed URLs
A signed URL lets anyone holding it download (or upload) one file until it expires — without signing in. Create it on behalf of a user who is allowed to read the file; it carries no other access.
// Share a private file for 10 minutes
const { url, expires_at } = await sovaria.storage.signDownload('invoices', `${user.id}/2026-10.pdf`, 600)
// Let the browser upload directly (create this on your server)
const upload = await sovaria.storage.signUpload('uploads', `${user.id}/video.mp4`, 900)
await fetch(upload.url, { method: 'PUT', body: file })| Lifetime | expires_in seconds, from 1 second to 1 day (86,400). The SDKs default to 1 hour; the API defaults to 15 minutes when you leave it out. |
| Scope | One file, one method (download or upload). |
| Revoking | A signed URL can't be withdrawn before it expires — keep lifetimes short. Deleting or moving the file makes it stop working. |
Caching and bandwidth
- Files are served with their stored content type; set
contentTypewhen uploading so browsers display them correctly. - Downloads count toward the monthly bandwidth allowance (Plan limits); public files that can be cached by browsers and CDNs save bandwidth.
- Signed URLs are unique per signing, so caches can't share them — prefer public buckets for popular public files.
| Free | Pro | Ultra | Team | Enterprise | |
|---|---|---|---|---|---|
| Storage CDN tier | Standard | Standard | Standard | Premium | Premium |
| Monthly bandwidth | 5,368,709,120 | 107,374,182,400 | 322,122,547,200 | 1,099,511,627,776 | 5,497,558,138,880 |
Image transformations
Files in HIPAA projects
In a project with HIPAA mode on, buckets can't be public (PHI_PUBLIC_BUCKET_DISABLED); share files with short-lived signed URLs instead (HIPAA mode and PHI projects).
Not supported
- File versioning or a trash: replaced and deleted files are gone.
- Per-file metadata beyond the content type, size and timestamps.