Multi-tenancy
ScaiDrive is multi-tenant. Every resource — user, group, share, file, folder, ACL, quota, audit event — belongs to a tenant, and tenants cannot see each other. This page covers the tenancy model, how it shows up in the API, and what happens at the edges.
The three levels#
- Partner — an optional outer layer. A consulting firm that runs ScaiDrive for five customers is a Partner; each customer is a Tenant. If you're running ScaiDrive for a single organization, there's still a Partner record, but you'll rarely interact with it.
- Tenant — an organization. The practical boundary for data isolation, administration, and billing.
- User — a person or service account inside a tenant. Identified by
usr_.... Users have roles, quotas, and group memberships. - Group — a collection of users inside a tenant. Can be share members and ACL principals.
- Share — a collaboration namespace inside a tenant. The container for files and folders.
Resource IDs are globally unique strings, but they resolve within their tenant. There's no "cross-tenant file" — accessing a file always implies "this tenant's file with this ID."
How tenancy is enforced#
Tenancy is checked in three places:
- Token. The JWT's
tenant_idclaim pins every request to one tenant. You cannot present a token for Tenant A and access Tenant B's data. - Query layer. Every database query filters by
tenant_id. The service layer takescurrent_user.tenant_idas a hard requirement; it's not possible to ask "give me this file regardless of tenant." - ACL layer. ACEs grant rights to principals (users, groups) that belong to the same tenant as the resource. Cross-tenant principals are rejected at write time.
Result: a request authenticated as a Tenant A user cannot access Tenant B resources, even if they know the IDs.
Resolving a user's tenant#
Clients rarely need to think about tenants — the JWT pins it automatically. To verify:
1 2 | |
1 2 3 4 5 6 | |
1 2 3 4 5 | |
Users in multiple tenants#
A human can have multiple ScaiKey accounts, one per tenant. They log in to each separately and get a different JWT for each. From the server's perspective, these are entirely separate principals — there's no cross-tenant linking.
If you're building a UI that lets a user switch tenants, the switch is a re-login against ScaiKey with a different tenant context, not an in-app operation.
Partner and super admin operations#
Most tenant-level operations are scoped to the tenant in the JWT. A few are cross-tenant:
Partner admin (partner:admin scope) can view and manage quotas for every tenant under their partner — see Quotas. They cannot view content, only quotas and metadata.
Super admin (* or platform:admin scope) can do anything on any tenant. Reserved for platform operators. Super-admin actions are recorded in the audit log of every affected tenant.
Neither role bypasses ACLs on file contents — you cannot read a file you don't have READ permission on, even as super admin, unless you first grant yourself that permission (which is auditable).
Quotas across the hierarchy#
Quotas apply at every level:
- Partner quota — total storage for all tenants under a partner.
- Tenant quota — total storage for one tenant.
- User quota — per-user allocation within a tenant.
- Group quota — aggregate allocation for a group.
- Share quota — per-share cap.
Any request that would push usage above any applicable quota fails with 507 QUOTA_EXCEEDED. The error identifies which quota was exceeded.
See Quotas for configuration.
Tenant isolation at the audit level#
Every audit event is tagged with its tenant. The audit log of Tenant A does not contain events from Tenant B, even if a partner admin performed them. Partner-admin cross-tenant actions appear in both the tenant's log (as "performed by [partner admin]") and a separate cross-tenant log available only to partner and super admins.
What's next#
- Shares and Ownership — the collaboration unit within a tenant.
- Permissions and ACLs — how access is resolved.
- Quotas Reference — quota endpoints.