Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Multi-tenancy

ScaiVault has a three-level tenancy model inherited from the ScaiLabs platform: partners, tenants, identities. Every secret, every policy, every audit entry is scoped to a tenant. Every tenant belongs to one partner.

The three levels#

Partner. Top-level account. Usually a company, a platform operator, or a reseller. Has one or more tenants.

Tenant. A workspace within a partner. Typically corresponds to an environment (dev/staging/prod) or a customer (for platforms). Has its own secrets, policies, users.

Identity. A user, service account, or group within a tenant. Identities come from ScaiKey — ScaiVault does not manage users itself.

graph TB P[Partner: ptn_acme] T1[Tenant: tnt_acme_prod] T2[Tenant: tnt_acme_dev] T3[Tenant: tnt_acme_shared] U1[user: alice@acme.example] U2[user: bob@acme.example] SA[service_account: reporting-service] G[group: sre] S1[secret: environments/production/db/password] S2[secret: environments/production/salesforce/oauth] S3[secret: environments/dev/db/password] P --> T1 P --> T2 P --> T3 T1 --> U1 T1 --> U2 T1 --> SA T1 --> G T1 --> S1 T1 --> S2 T2 --> S3

Tenant resolution#

Every request is scoped to exactly one tenant. The tenant comes from one of three places, in priority order:

  1. Explicit path prefix/v1/t/{tenant_id}/.... Requires the caller's token to have partner-admin privileges and the target tenant to belong to the caller's partner.
  2. X-Tenant-ID header — equivalent to the path prefix. Same auth requirements.
  3. Token's tenant_id claim — the default. Your token is bound to one tenant; all your requests act as that tenant.

If the requested tenant doesn't belong to your partner, you get 403 access_denied. If the tenant doesn't exist, 404 tenant_not_found.

Tenant-scoped paths#

The common case. Your token's tenant_id claim determines scope automatically.

bash
1
GET /v1/secrets/app/db/password

Resolves to: "read app/db/password in the tenant identified by my token."

Tenants cannot see each other's secrets. A secret at app/db/password in tnt_acme_prod and one at the same path in tnt_acme_dev are entirely separate rows — same path, different tenants.

Partner-scoped paths#

Sometimes you want a secret visible to every tenant under a partner — a shared trust anchor, a partner-wide default config, a central webhook-signing key. Use the /v1/partner/secrets/* prefix:

bash
1
2
3
4
curl -X PUT https://scaivault.scailabs.ai/v1/partner/secrets/shared/webhook-signing-key \
  -H "Authorization: Bearer $PARTNER_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data": {"key": "..."}, "secret_type": "kv"}'

Every tenant under ptn_acme can read shared/webhook-signing-key, but only partner admins can write. Partner secrets show up in tenant-scoped lists with a "scope": "partner" marker.

Explicit tenant access#

Partner admins sometimes need to act as a specific tenant — debugging, bulk updates, automated provisioning. The /v1/t/{tenant_id}/ prefix does this:

bash
1
2
GET /v1/t/tnt_acme_prod/secrets/app/db/password
Authorization: Bearer $PARTNER_ADMIN_TOKEN

This reads from tnt_acme_prod as if you were a member. The audit log records the acting identity (the partner admin) and the target tenant. Use this for operator tasks, not for steady-state application traffic.

All endpoints (/v1/secrets/*, /v1/policies/*, /v1/audit/*, etc.) are available under the /v1/t/{tenant_id}/ prefix with identical semantics.

Roles#

ScaiKey defines a small set of admin roles that ScaiVault respects:

Role Scope What it can do
super_admin Platform Manage any partner or tenant. Reserved for ScaiLabs staff.
partner_admin Partner Manage tenants under the partner, read/write partner-scoped secrets, act cross-tenant.
tenant_admin Tenant Manage policies, service accounts, rotation policies within one tenant.

Roles are additive — a partner_admin is implicitly a tenant_admin for every tenant under their partner. A super_admin is everything.

Non-admin identities (regular users, service accounts, groups) get their access from policies, not roles. A tenant user doesn't "have tenant-admin access" unless the policies bound to them say so. See Policies and Permissions.

Cross-tenant sharing (what to do instead)#

Tenants cannot directly read each other's secrets. If you need two tenants to share a value:

  • Is it really tenant-specific? Probably yes. Store it twice.
  • Is it partner-wide? Use /v1/partner/secrets/*.
  • Is it a live copy that must stay in sync? Use Federation with one tenant as the source of truth.
  • Is this a one-off migration? Partner admin reads from tenant A, writes to tenant B, records the transfer in audit.

We deliberately don't provide "grant tenant B read access to tenant A's secret X" — it breaks the isolation contract that makes tenants meaningful.

Identity types#

Type Example ID When to use
user user:alice@acme.example A human in the admin UI or CLI
service_account sa:reporting-service A service making API calls
group group:sre A set of users, bound via policies

Policies bind to any of these. A binding on a group effectively grants access to every user in that group — group membership is resolved at request time from the cached ScaiKey data.

Impersonation and on-behalf-of#

Service accounts can be configured in ScaiKey to "act on behalf of" a user. When the service account authenticates, the token's act claim names the user; ScaiVault uses the service account's scopes but credits the user in the audit log. This is useful for user-facing services that proxy calls to ScaiVault — the audit log tells you which human triggered each read.

What's next#

Updated 2026-05-17 14:30:19 View source (.md) rev 5