Access Rules
Define who can upload, download, and delete files in your storage buckets. Rules are TypeScript functions declared in edgebase.config.ts that return true (allow) or false (deny).
Rules are evaluated on every Client SDK request — Admin SDK and App Functions bypass rules entirely.
That storage bypass applies to all Admin SDKs.
Quick Start
// edgebase.config.ts
export default defineConfig({
storage: {
buckets: {
photos: {
access: {
read(auth, file) {
return true
},
write(auth, file) {
return auth !== null
},
delete(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
},
},
},
},
});
Each rule function receives auth (the current user) and file (file metadata), and returns a boolean.
Default Policy
| Rule | Result |
|---|---|
| No access rules defined | All operations denied (403) |
Returns true | Allow |
Returns false | Deny |
When release: false (the default), operations on configured buckets are allowed even without rules — so you can start building immediately. Set release: true before production deployment to enforce deny-by-default.
Examples
Public bucket — anyone can read, authenticated users upload
avatars: {
access: {
read(auth, file) {
return true
},
write(auth, file) {
return auth !== null
},
delete(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
},
},
Private bucket — owner only
documents: {
access: {
read(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
write(auth, file) {
return auth !== null
},
delete(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
},
},
Admin-managed bucket — admins can delete, users can upload
uploads: {
access: {
read(auth, file) {
return true
},
write(auth, file) {
return auth !== null
},
delete(auth, file) {
return auth !== null && auth.role === 'admin'
},
},
},
Size-restricted uploads
attachments: {
access: {
read(auth, file) {
return auth !== null
},
write(auth, file) {
return auth !== null && file.size <= 10 * 1024 * 1024 // 10 MB max
},
delete(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
},
},
Reference
Operations
| Operation | When | file argument? |
|---|---|---|
read | Download, get metadata, list files | Yes |
write | Upload (single or multipart), update metadata | Yes |
delete | Delete a file | Yes |
Function Arguments
| Argument | Type | Description | Available in |
|---|---|---|---|
auth | AuthContext | null | Current user (null if unauthenticated). Properties: id, email, role, isAnonymous, custom, meta | All operations |
file | R2FileMeta / WriteFileMeta | File metadata (e.g., file.uploadedBy, file.size) | All operations |
Null Safety
Since auth can be null (unauthenticated request), always check before accessing properties:
// Good: null check before property access
read(auth, file) {
return auth !== null && auth.id === file.uploadedBy
},
// Bad: will throw if auth is null
read(auth, file) {
return auth.id === file.uploadedBy
},
Multipart Upload Security
For multipart uploads, the write rule is re-evaluated on every request — create, upload-part, complete, and abort. The uploadId is not treated as a session token. This ensures that a revoked user cannot complete an in-progress upload.
Service Key Bypass
Requests authenticated with a Service Key bypass all storage access rules:
import { createAdminClient } from '@edgebase/admin';
const admin = createAdminClient('https://api.example.com', {
serviceKey: process.env.EDGEBASE_SERVICE_KEY,
});
// All storage operations bypass rules
See Service Keys for configuration and scoped keys (storage:bucket:photos:read, storage:bucket:*:write, etc.).
- Access Rules Reference — Full reference for all access rules
- Upload & Download — File upload and download guide
- Signed URLs — Time-limited pre-signed URLs
- Service Keys — Server-side rule bypass