# Роли и права: встроенные и свои роли

Права в AGIL Calls — это **набор функций**, которые доступны участнику
(чат, файлы, экран, запись, знания, ассистент, настройки и т.д.). Компания
управляет ими гибко: меняет права трёх встроенных ролей, создаёт **свои роли**,
выдаёт индивидуальные права и фиксирует права в токене.

## 1. Встроенные роли

`host` (организатор), `moderator` (модератор), `guest` (гость). Их права по
умолчанию лежат в `security.accessPolicy.roleDefaults`, меняются через
`PUT /v1/admin/access-policy` и **не удаляются** (иначе некуда «падать» при
входе). У модераторов есть технические возможности (kick/lock/запись), они
проверяются сервером отдельно от `features`.

## 2. Свои роли (custom roles)

Своя роль = `id` + `name` + `baseRole` + набор `features` (+ `canModerate`,
`color`, `description`). Пример: «Стример», «Наблюдатель», «Преподаватель»,
«Внешний подрядчик».

```jsonc
// PUT /v1/admin/access-policy → policy (или через POST /v1/admin/roles)
{
  "customRoles": [
    {
      "id": "streamer",
      "name": "Стример",
      "description": "Ведёт трансляцию, без записи и файлов",
      "baseRole": "host",          // техническая роль (модерация/аудит)
      "features": ["chat", "screenShare", "fullscreen", "knowledgeAgent"],
      "canModerate": false,
      "color": "#8576ff"
    }
  ]
}
```

- `baseRole` — «технический» базовый тип (используется для модерации, аудита и
  как fallback, если роль удалили или токен выпущен без roleId).
- `id` — `[a-z0-9][a-z0-9_-]{0,39}`, максимум 30 ролей на тенант.
- `canModerate` — даёт модераторские действия (если также есть
  `participantList`), но **не повышает** техническую роль выше `baseRole`.
- `color` — для бейджа в UI (необязательно).

## 3. Как выдаётся роль

1. **Токен с ролью**: `POST /v1/tokens` `{participant:{name, role:'guest',
   roleId:'streamer'}}` → в токене `roleId`, в `welcome.self.roleName` —
   «Стример».
2. **Права в токене** (pin): `permissions:[...]` — заменяет набор роли/оверрайды
   (крайний случай, «выдать ровно это»).
3. **Индивидуально**: `userOverrides[userId]` — заменяет роль для конкретного
   пользователя.

Итоговые права (precedence, от сильного к слабому):
`token.permissions` → `userOverrides[userId]` → `customRoles[roleId].features` →
`roleDefaults[baseRole]` → затем вычитаются `deniedFeatures` → затем
пересекаются с включёнными `features.*` тенанта.

> Важно: `features.*` — глобальные выключатели тенанта («в компании нет
> записи»), они сильнее любой роли. `deniedFeatures` — глобальные запреты.

## 4. API ролей

| Метод | Путь | Кто | Назначение |
|---|---|---|---|
| GET | `/v1/admin/roles` | `x-api-key` | список: встроенные (`builtin:true`, features из roleDefaults) + свои (`builtin:false`, `assigned` — сколько в звонках) |
| POST | `/v1/admin/roles` | `x-api-key` | создать свою роль (409 — дубль id, 400 — зарезервированный id/валидация) |
| PUT | `/v1/admin/roles/:id` | `x-api-key` | изменить свою роль (встроенные — через access-policy) |
| DELETE | `/v1/admin/roles/:id` | `x-api-key` | удалить свою роль; ответ `{deleted, affectedParticipants}`; активные участники остаются, применяется `baseRole` |

Пример:
```bash
curl -X POST https://calls.guardify.ru/v1/admin/roles \
  -H 'content-type: application/json' -H 'x-api-key: <KEY>' \
  -d '{"id":"observer","name":"Наблюдатель","description":"Только смотреть и слушать","baseRole":"guest","features":["chat","participantList"],"canModerate":false}'

curl -X POST https://calls.guardify.ru/v1/tokens \
  -H 'content-type: application/json' -H 'x-api-key: <KEY>' \
  -d '{"tenantId":"demo","roomId":"<room>","participant":{"name":"Пётр","role":"guest","roleId":"observer"}}'
```

MCP: `agil_list_roles`, `agil_create_role`, `agil_update_role`,
`agil_delete_role`, `agil_explain_roles`.
Редактор/панель: «Доступы» → матрица roleDefaults + блок «Свои роли» +
генератор токена с выбором роли.

## 5. Удаление ролей

- Встроенные `host/moderator/guest` удалить нельзя — только изменить их права
  (`roleDefaults`).
- Свою роль можно удалить. Если она используется активными участниками:
  звонок не обрывается, у них продолжает действовать `baseRole`; сервер
  возвращает `affectedParticipants`, UI просит подтверждение.
- Если роль удалили, а токен с `roleId` ещё жив (до `exp`) — при входе roleId
  не найдётся, применяется `baseRole` токена.

## 6. Практические советы

- Начинайте с трёх встроенных ролей; свои создавайте, когда есть реальные
  различия (внешний подрядчик, оператор трансляции, преподаватель).
- Внешним/гостевым ролям не давайте `recording`, `knowledgeAgent`, `fileShare`
  без необходимости — это данные компании.
- Для вебинаров: роль «Стример» (`screenShare`,`fullscreen`, без `chat` при
  модерации) и «Зритель» (только `chat`/`reactions`).
- Права проверяются и в UI, и на сервере (403) — тестируйте оба уровня.
- Все изменения ролей пишутся в аудит; регулярно проверяйте
  `GET /v1/admin/access-policy` и матрицу в панели.

## 7. Ограничения MVP

- Роли плоские (нет иерархии наследования ролей), кроме единого `baseRole`.
- Нет UI-назначения роли пользователю «навсегда» — роль фиксируется в токене
  (или в `userOverrides`), т.е. решается на стороне каталога компании.
- `canModerate` не превращает роль в `host` для E2EE-ограничений/аудита.
- Роли тенант-локальны (нельзя переиспользовать между тенантами).
