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

Permissions and Access

ScaiDNS uses a role-based access control model, scoped by platform / tenant / domain, with optional access grants for per-domain delegation. This page explains how authorization resolves when a request arrives.

Four scopes#

Every permission assignment is attached to exactly one of these scopes:

Scope Reach Who has it
platform Across all tenants Operators of the ScaiDNS instance
tenant Everything in one tenant Customer admins
domain One specific zone Users delegated individual zones
record Specific records within a zone Granular delegation via access grants

Higher scopes include lower ones. A platform admin automatically has tenant-admin rights on every tenant; a tenant admin automatically has domain admin rights on every zone in their tenant.

System roles#

ScaiDNS ships with six system roles. They're created in the database on first boot and can be assigned to users or groups at any applicable scope.

Role Typical scope Permissions
platform_admin platform Full platform control — tenant management, platform config, cross-tenant audit
tenant_admin tenant Full tenant control — all zones, records, users, roles, API keys, audit within one tenant
domain_admin domain Full control over one zone — records, DNSSEC, access grants for that zone
domain_manager domain Manage records; can't change DNSSEC or delegate further
record_editor domain Create and modify records; no delete
read_only any Read access only
validation_bypass tenant Create domains without going through validation (trusted internal use)

Custom roles can be created by tenant admins (POST /api/v1/roles/). They can only grant subsets of permissions that the creator has — you cannot create a role that grants more than you have.

How a request is authorized#

When a request arrives, ScaiDNS:

  1. Authenticates the caller (JWT or API key).
  2. Resolves the tenant context.
  3. Computes effective permissions for the caller within that tenant and (optionally) that specific domain.
  4. Checks whether the required permission for the requested action is present.

The EffectivePermissions object contains:

  • is_platform_admin — true if any platform-scoped assignment grants it
  • is_tenant_admin — true if any tenant-scoped assignment grants it
  • permissions — an object like {"domains": ["read", "create"], "records": ["read", "write"], ...}

Endpoints check these flags or specific permissions. For example, POST /api/v1/domains/{id}/records requires records:write on that domain.

Direct role assignment vs access grants#

Two mechanisms give a user (or group) access to a domain:

Role assignments#

Attach a role at a scope:

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Give a user tenant_admin for their tenant
curl -X POST https://scaidns.scailabs.ai/api/v1/roles/users/$USER_ID \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "role_id": "r_tenant_admin_uuid",
    "scope": "tenant"
  }'

# Give a user domain_manager for one zone
curl -X POST https://scaidns.scailabs.ai/api/v1/roles/users/$USER_ID \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "role_id": "r_domain_manager_uuid",
    "scope": "domain",
    "scope_resource_id": "d_zone_uuid"
  }'

Role assignments live in the user_roles table. They're coarse-grained and durable.

Access grants#

More granular. Grant a user (or group) a specific role on a specific domain, optionally limited to record types or name patterns, optionally expiring:

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
curl -X POST https://scaidns.scailabs.ai/api/v1/domains/$DOMAIN_ID/access-grants \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "user",
    "grantee_id": "u_abc123",
    "role_id": "r_record_editor_uuid",
    "record_types": ["A", "AAAA", "CNAME"],
    "record_pattern": "*.staging",
    "expires_at": "2026-12-31T23:59:59Z",
    "notes": "Staging delegation for Q4"
  }'

Access grants are scoped to a single domain. Use them when:

  • A contractor needs access to one zone for a bounded time.
  • A team should only touch records matching a pattern (*.dev, api.*).
  • An external service needs to manipulate only certain record types.

See Access Grants for the full surface.

Groups#

Groups simplify management at scale. Assign a role to the group, and all members inherit it:

bash
1
2
3
4
curl -X POST https://scaidns.scailabs.ai/api/v1/roles/groups/$GROUP_ID \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"role_id": "r_domain_manager_uuid", "scope": "tenant"}'

When a user is added to or removed from the group (managed in ScaiKey), their effective permissions update automatically.

Checking what a user can do#

bash
1
2
curl https://scaidns.scailabs.ai/api/v1/roles/users/$USER_ID/permissions \
  -H "Authorization: Bearer $JWT"

Returns:

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "is_platform_admin": false,
  "is_tenant_admin": true,
  "roles": [
    {"role_name": "tenant_admin", "scope": "tenant", "scope_resource_id": null}
  ],
  "permissions": {
    "domains": ["read", "create", "update", "delete"],
    "records": ["read", "create", "update", "delete"],
    "dnssec": ["read", "enable", "disable", "rotate"],
    "access_grants": ["read", "create", "update", "delete"]
  }
}

Add ?domain_id=<uuid> to factor in per-domain grants.

API key permissions#

API keys don't carry their own permissions — they inherit from a permission source, either a user or a group:

  • user — key inherits from the named user.
  • group — key inherits from the named group.

If you revoke the user's access, all their API keys lose that access too. Keys are effectively shadow sessions for their permission source.

Keys cannot be platform admins. Even if the owning user is a platform admin, API keys are treated as non-platform. This is a deliberate constraint — platform-admin actions must flow through a human session.

Permission categories#

What exists in the permissions object:

Category Actions
domains read, create, update, delete
records read, create, update, delete
dnssec read, enable, disable, rotate
access_grants read, create, update, delete
platform config, audit, bypass_validation, manage_tenants

Custom roles define their own mix of these.

What's next#

Updated 2026-05-17 02:38:19 View source (.md) rev 1