---
summary: Hand a scope to a team or a service. Scope roles give access to one scope
  only, and a restricted scope is invisible to everyone else.
title: Scopes as realms
path: concepts/realms
status: published
---

A scope groups related queues. You can also hand it to a team or a service as its own **realm**: they manage their queues and messages there, without tenant-wide ScaiQueue rights and without seeing other teams' scopes.

Two things make this work:

- **Scope roles.** Give a user or a group a role in one scope. The role applies to that scope only.
- **Restricted scopes.** Mark a scope `restricted` and only its members and tenant admins can reach it. To everyone else it doesn't exist (`404`).

## Roles

| Role | Can |
|---|---|
| `owner` | Everything in the scope, including who has access (grants, queue ACL entries, trusted scopes) |
| `operator` | Create, delete, pause and resume queues; routing rules, schemas, HITL patterns, subscriptions; cancel messages; pause, resume and drain the scope; publish and consume |
| `producer` | View the scope and publish messages |
| `consumer` | View the scope; claim, complete, fail, release and extend messages; create subscriptions |
| `viewer` | Read the scope, its queues, messages, rules, schemas and audit log |

Tenant-level actions stay with tenant admins and holders of the tenant-wide `scaiqueue:manage` permission: creating scopes, archiving, unarchiving and deleting them, and making a scope restricted or unrestricted. An owner can't delete its own scope or open it up.

## Letting a service create its own realms

Give a user (typically a service user) the `scaiqueue:create_scopes` permission, and it can create scopes itself, for example one per customer:

- it becomes **owner** of every scope it creates, and can make it restricted at creation;
- it can archive, unarchive and delete the scopes it owns;
- it can't see or touch any other scope, and can't open a restricted scope up later.

Deleting a scope removes everything in it: queues, messages (including archived ones and their attachments), grants, queue ACL entries, trusts, routing rules, subscriptions, streams, schemas and HITL patterns. The scope's audit log is kept.

## Who can do what in a scope

A caller's rights in a scope come from three places, added together:

1. **Tenant level.** Tenant admins, partner admins and holders of tenant-wide `scaiqueue:manage` can do everything in every scope of the tenant, restricted or not.
2. **Tenant-wide permissions, unrestricted scopes only.** `scaiqueue:view`, `:publish` and `:consume` work as before on unrestricted scopes. They don't reach restricted scopes.
3. **Scope roles** on that scope.

On top of that, [per-queue ACL entries](../reference/api#acl) can still deny a specific action on one queue, for example to stop a service from approving its own review requests.

A caller with no rights in a scope gets `404`, so it can't tell whether the scope exists. A caller who can see the scope but lacks the right for an action gets `403`.

## Members

- **Users**, by ScaiGrid user id. For an API key, that's the key's owner.
- **Groups**, by ScaiKey group id (the local group id is accepted and converted). Members of the group get the role.
- Members must belong to the scope's tenant. A member has one role per scope: granting again replaces it.
- A grant can expire: pass `expires_at` (ISO 8601). Expired grants stop working at once.

## Reviewing through another application

Reviewers often work in another application's console, for example a code-review tool that shows human-in-the-loop requests from a ScaiQueue realm. The reviewers can claim and complete messages under their own identity, so the application never needs a key that can approve:

1. The reviewer signs in to the application with ScaiKey.
2. The application exchanges the reviewer's token for a ScaiGrid token, with the RFC 8693 token-exchange grant and `audience=scaigrid`. The application must be a confidential ScaiKey client that is allowed to exchange tokens.
3. The application calls ScaiQueue with the exchanged token.

ScaiQueue then decides access on the reviewer, who needs a role in the realm (`consumer` is enough to claim and complete), and records the reviewer as the one who claimed and completed the message, with the application as `via`. The same goes for the audit log. A token issued for the application itself is refused (`401`): ScaiGrid accepts only tokens addressed to ScaiGrid.

## Example: a realm for a service

A service runs as its own user with an API key. Give it a restricted scope and no tenant-wide ScaiQueue permissions:

```bash
# Tenant admin: create the realm
curl -X POST "$SCAIGRID_HOST/v1/modules/scaiqueue/scopes" \
  -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
  -d '{"slug": "ci-pipeline", "display_name": "CI pipeline", "restricted": true}'

# Tenant admin: make the service its operator
curl -X POST "$SCAIGRID_HOST/v1/modules/scaiqueue/scopes/$SCOPE_ID/acl/grants" \
  -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
  -d '{"actor_type": "user", "actor_id": "'$SERVICE_USER_ID'", "role": "operator"}'

# Give the reviewers' group the consumer role
curl -X POST "$SCAIGRID_HOST/v1/modules/scaiqueue/scopes/$SCOPE_ID/acl/grants" \
  -H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
  -d '{"actor_type": "group", "actor_id": "grp_reviewers", "role": "consumer"}'
```

The service can now create its own queues and publish and consume in `ci-pipeline`, and nothing else. `GET /scopes` shows it only that scope, with `my_role` and `capabilities`.

In the admin UI: **ScaiQueue → Create scope → Restricted**, then the scope's **Access** section → **Add Grant**.

## Compared with Scuttle realms

If you know Scuttle: a ScaiQueue scope is the counterpart of a Scuttle realm. `owner`, `operator` and `viewer` match Scuttle's realm admin, operator and viewer; `producer` and `consumer` are extra, because queues have a data side that databases don't.
