---
summary: ScaiSpeak module permissions and which roles get them by default.
title: Permissions
path: reference/permissions
status: published
---

ScaiSpeak defines five module-permission keys, mapped onto ScaiGrid's RBAC system. Every endpoint enforces one of them.

## Permission keys

| Key | What it grants |
|---|---|
| `scaispeak:synthesize` | Call `/speak`, `/speak/jobs/*`, the WebSocket stream, the WebRTC session endpoints, and the ScaiDrive destination-picker proxy. Read tenant policy. |
| `scaispeak:voice.read` | List voices, fetch one voice, run previews, inspect warm state. |
| `scaispeak:voice.write` | Clone voices, update metadata, delete voices, warm + evict voices, repromote, live-record intake. |
| `scaispeak:voice.share` | Promote a private voice to tenant-shared scope. Separate from `voice.write` so cloning and promotion can be granted independently. |
| `scaispeak:admin` | Write tenant policy, manage the blocklist, read the erasure audit. Lifecycle hooks (install / upgrade / uninstall / tenant enable / disable) and the global-voices endpoints additionally require SuperAdmin. |

## Default role mapping

Built-in roles auto-grant module permissions via ScaiGrid's catch-all in `CurrentUser.has_module_permission`:

| Role | Auto-grants |
|---|---|
| `super_admin` | All of the above, plus the SuperAdmin-only endpoints (global voices, lifecycle hooks). |
| `partner_admin` | All of the above for tenants under the partner. |
| `tenant_admin` | All of the above for the tenant. |
| `tenant_user` | None by default. |
| `tenant_viewer` | `scaispeak:voice.read`. |

`tenant_user` gets nothing automatically because TTS spends tokens against the tenant budget — you want explicit opt-in.

## Granting selectively

Most tenants use a small custom role for engineers building TTS into a product:

```bash
curl -X POST "$SCAIGRID_HOST/v1/iam/custom-roles" \
  -H "Authorization: Bearer $SCAIGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "TTS developers",
    "module_permissions": [
      "scaispeak:synthesize",
      "scaispeak:voice.read"
    ]
  }'
```

A separate "Voice operators" role with `voice.write` + `voice.share` is usually held by fewer people — sharing affects everyone in the tenant.

## Audit

Every permission-gated call is logged with `actor_user_id`, `action`, `resource_id`. Voice deletions additionally write an `erasure_audit` row (queryable via `GET /admin/erasure/audit`) with the warm-replicas-evicted count, blob-bytes-deleted count, and any partial-failure summary.
