# Права

У ключа интеграции **нет своего языка прав**. Ключ — такой же субъект, как
человек, и проверяет его та же функция, что и роль сотрудника.

Это решение (ADR-054) отменило отдельный список прав вида `users:read`,
который был в раннем проекте API. Причина простая: два языка прав — это
два места, где решают, можно ли действие, и они разойдутся. Разойдутся
молча и на чужой установке.

> **Проверка одна на продукт.** Админка, API, Telegram-бот и ИИ-агент
> спрашивают её же. Обойти проверку, зайдя с другой стороны, нельзя —
> другой стороны нет.

## Семь ролей

| Роль | Кто это |
|---|---|
| **владелец** | тот, чья школа. Может всё, включая то, что не может администратор |
| **администратор** | может в школе всё, кроме настроек школы, платёжных систем и агента — их владелец открывает поимённо |
| **менеджер** | продажи и общение: заказы, продукты, промокоды, рассылки |
| **куратор** | проверка работ — **только своих потоков** |
| **автор** | курсы и уроки, плюс отчёты по своим курсам |
| **партнёр** | свой кабинет со ссылками и начислениями |
| **ученик** | кабинет, курсы, свои заказы |

Роли складываются: человек может быть одновременно автором и куратором.

**В приглашении роль названа словами, а не списком прав** — кем зовут и что
человек будет делать: «куратором: проверять работы учеников и отвечать им».
Словарь один на продукт. Двухфакторная аутентификация (2FA) — по желанию любой роли;
владельцу, администратору и менеджеру её советуют, а включают её в своём профиле.

## Сорок девять прав

Право — это глагол, а не раздел интерфейса. Но у каждого раздела меню своё
право (ADR-180): по списку прав видно, какие экраны человек откроет.

### Школа и сотрудники

| Право | Что позволяет | Кому дано |
|---|---|---|
| `admin.access` | входить в админку вообще | всем сотрудникам |
| `staff.view` | видеть список сотрудников | администратор, менеджер |
| `staff.invite` | приглашать сотрудников | администратор |
| `staff.inviteTeam` | приглашать в свою команду — только своей ролью | администратор; старший куратор — кураторов, руководитель отдела продаж — менеджеров |
| `staff.updateRoles` | менять роли сотрудников | администратор — **кроме владельца** |
| `staff.revoke` | отзывать доступ | администратор — **кроме владельца** |

### Настройки и касса школы

| Право | Что позволяет | Кому дано |
|---|---|---|
| `settings.manage` | менять настройки школы — всё, кроме платёжных систем | **никому ролью** — владелец открывает поимённо |
| `payments.manage` | подключать и править платёжные системы | **никому ролью** — владелец открывает поимённо |

Администратор может в школе всё, **кроме этих двух прав и агента**. Так решил
владелец: настройки школы и касса открываются конкретному человеку, а не
должности. Платёжные системы отделены от остальных настроек: ключи кассы —
это доступ к деньгам.

### Учёба

| Право | Что позволяет | Кому дано |
|---|---|---|
| `course.edit` | создавать и править курсы | администратор, автор |
| `course.curators` | назначать и снимать кураторов курса, куратора потока и ученика, включать общую ленту | администратор, автор; куратор — ступенью «старший куратор» |
| `certificate.manage` | выдавать и отзывать сертификаты | администратор, автор |
| `submission.list` | открывать ленту проверки | администратор, куратор |
| `review.stats` | смотреть статистику кураторов: сводку команды и задания за период, выгрузку | администратор; куратор — ступенью «старший куратор» |
| `review.team` | вести ленту проверки всей команды: работы любого ученика видны и принимаются | администратор; куратор — ступенью «старший куратор» |
| `submission.review` | проверять работы | администратор; куратор — **только своих потоков**, старший куратор — любых |
| `quiz.results` | смотреть результаты тестов | администратор, менеджер, автор |
| `report.view` | смотреть отчёты | администратор, менеджер, автор |
| `webinar.manage` | проводить вебинары | администратор, автор |

Автор видит отчёты: доходимость его курса — его работа. Куратор не видит:
у него своя лента проверки, а сводка по школе к его обязанностям
не относится. По той же причине куратор видит в **статистике кураторов** только
свои числа («Моя статистика» в «Проверке работ»): лента и свои проверки — его работа,
сравнение с коллегами и выгрузка — управление, это право `review.stats`.

### Люди

| Право | Что позволяет | Кому дано |
|---|---|---|
| `user.view` | видеть карточки людей | администратор, менеджер |
| `user.edit` | править имя человека | администратор, менеджер |
| `user.editContact` | менять почту и телефон | администратор — **кроме владельца** |
| `user.delete` | удалять людей навсегда | администратор — **кроме владельца** |
| `user.impersonate` | входить под другими людьми | администратор — **кроме владельца** |
| `segment.manage` | работать с сегментами | администратор, менеджер |

**Контакт отделён от имени намеренно.** Почта — это вход в аккаунт: сменить
её равно сменить владельца аккаунта. Имя правится одним действием и видно
одному человеку; это самая частая просьба поддержки — «Аня» вместо «Анна»
в сертификате. Контакт владельца не меняет никто, кроме него самого: иначе
смена его почты была бы захватом школы через восстановление пароля.

### Деньги

| Право | Что позволяет | Кому дано |
|---|---|---|
| `order.view` | видеть заказы | администратор, менеджер |
| `order.cancel` | отменять **чужие** заказы | администратор, менеджер |
| `order.markPaid` | отмечать оплату заказа вручную — деньги мимо кассы | менеджер; администратор — галочкой владельца «Отмечать оплату вручную» |
| `order.refund` | возвращать деньги | администратор |
| `product.manage` | заводить продукты и тарифы | администратор, менеджер |
| `promo.manage` | заводить промокоды | администратор, менеджер |
| `deal.manage` | вести сделки | администратор, менеджер |
| `pipeline.manage` | настраивать воронки и этапы сделок: заводить, переименовывать, порядок, нормы, перенос пачкой | администратор; менеджер — ступенью «руководитель отдела продаж» |
| `task.work` | работать с задачами менеджеров: очередь, исходы разговора, «Взять следующую» | администратор, менеджер |
| `task.manageAll` | вести задачи всех менеджеров: очередь любого и общая, исход в чужой задаче | администратор; менеджер — ступенью «руководитель отдела продаж» |
| `partner.manage` | вести партнёров и выплаты | администратор, менеджер |
| `spend.manage` | вписывать расход на рекламу | администратор, менеджер |
| `analytics.view` | смотреть сквозную аналитику | администратор, менеджер, автор |

Свой неоплаченный заказ человек отменяет сам, безо всякого права: это его
намерение, и просить разрешения передумать не у кого.

**Возврат отделён от отмены,** и это не формальность. Отмена закрывает
намерение, которое передумали; возврат **отдаёт деньги** и отзывает доступ.
Менеджер, у которого продажи в KPI, такого права не имеет.

**Расход на рекламу денег школы не двигает, но двигает решения:** по
окупаемости канала его выключают. Смотреть аналитику может и автор курса —
вписывать бюджет школы нет.

### Связь

| Право | Что позволяет | Кому дано |
|---|---|---|
| `mailing.manage` | отправлять рассылки | администратор, менеджер |
| `scenario.manage` | настраивать сценарии | администратор, менеджер |
| `support.answer` | отвечать на обращения учеников | администратор, менеджер, **куратор** |

**Куратор отвечает на обращения, но не трогает рассылки и заказы.**
Половина обращений — «не открывается урок» и «не пришла проверка»: это его
поток и его ответ. Автор курса не отвечает: он пишет курс, а не разговаривает
с учениками.

### Сайт школы

| Право | Что позволяет | Кому дано |
|---|---|---|
| `page.manage` | делать страницы школы | администратор, автор |
| `widget.manage` | делать виджеты | администратор, автор |
| `form.view` | смотреть заявки с форм | администратор, автор |
| `page.code` | вставлять свой код на страницы, в виджеты и уроки | администратор; автору — **поимённо** |

Свой код на странице школы — самый прямой путь к чужому браузеру: скрипт
исполняется на домене школы от имени каждого, кто откроет страницу. Поэтому
ролью он открыт только администратору, а автору — галочкой владельца,
конкретному человеку.

### Файлы

| Право | Что позволяет | Кому дано |
|---|---|---|
| `files.read` | открывать библиотеку | сотрудникам |
| `files.upload` | загружать файлы | сотрудникам |
| `files.delete` | удалять файлы | администратор, менеджер |

Удаление отделено: файл выбивает видео из десятков уроков у сотен людей.

### Подкапотка

| Право | Что позволяет | Кому дано |
|---|---|---|
| `events.manage` | разбирать журнал событий | администратор |
| `queues.manage` | разбирать очереди | администратор |

## Личные выдачи

Пять прав живут сверх ролей и выдаются галочкой конкретному человеку —
во вкладке «Права» его карточки, в блоке «Права сверх роли»:

| Галочка | Что открывает | Кому может быть выдана |
|---|---|---|
| Настраивать школу | `settings.manage` — всё в «Настройках», кроме платёжных систем | администратору, менеджеру |
| Подключать платёжные системы | `payments.manage` — касса и ключи магазина | администратору, менеджеру |
| Отмечать оплату вручную | `order.markPaid` — деньги мимо кассы | администратору; менеджеру открыто ролью |
| Вставлять свой код | `page.code` | автору; администратору код открыт ролью |
| Писать агенту | разговор с [ИИ-агентом школы](/guide/agent/) | сотруднику |

Роль дала бы это **всем** её носителям, включая тех, кого наймут завтра:
решение за них принималось бы заранее и вслепую.

- **Ставит и снимает только владелец** и только из своего аккаунта: ключ
  интеграции человеком не является и не откроет право — в том числе себе.
- **Выдача действует, пока у человека есть роль, под которую её давали.**
  Роль сверяется при каждом обращении: переведённый в ученики администратор
  с галочкой «платёжные системы» ключи кассы не поменяет. Карточка показывает
  такую галочку словами — «не действует, пока роли нет».
- **У ключа интеграции выдач нет:** права ключа — права роли.

## Ступени ролей: старший куратор и руководитель отдела продаж

У двух ролей есть старшая ступень — **подгалочка под самой ролью** во вкладке «Права» карточки.
Она видна, когда роль отмечена:

| Подгалочка | Под ролью | Что добавляет |
|---|---|---|
| Старший куратор | Куратор | лента проверки всей команды (`review.team`): видит и проверяет работы любого ученика, выбирает куратора в фильтре ленты; статистика всех кураторов и выгрузка CSV (`review.stats`); приглашает кураторов (`staff.inviteTeam`); назначает кураторов курсам и потокам, включает общую ленту (`course.curators`) |
| Руководитель отдела продаж | Менеджер | задачи всех менеджеров (`task.manageAll`): очередь любого менеджера и общая, исход в чужой задаче, статистика менеджеров и выгрузка; воронки и этапы сделок (`pipeline.manage`); приглашает менеджеров (`staff.inviteTeam`) |

- **Ставит и снимает тот, кто меняет роли человека** — владелец или администратор (владельца
  администратор не повышает). Ступень — часть роли, а не право сверх неё, поэтому решает тот же,
  кто выдаёт саму роль. Каждое включение и снятие — в журнале школы: «Сотрудник сделан старшим куратором».
- **Снимается вместе с ролью.** Сняли роль «куратор» — «старший куратор» снимается молча, без отдельного
  вопроса; вернули роль — ступень ставят заново (правка 20 сентября, по кадрам «Заход 24, отчёт 1»).
  «Отозвать доступ» снимает и ступени.
- **Во вкладке «Права»** роли — карточкой «Роли в школе», ступень — вложенной строкой под отмеченной ролью,
  у неотмеченной — подсказка «ступень появится здесь, если отметить роль». Каждая галочка сохраняется
  сразу; отказ сервера — словами у своей строки и кнопкой «Повторить». Справа — «Что может, коротко»:
  права, пришедшие от ступени, помечены серым «старший куратор»; «Кого видит» — строками: ученики,
  карточки людей, деньги и заказы.
- **Администратору ступени не нужны:** всё это у него есть ролью — подгалочка стоит отмеченной
  и не переключается.
- **Агент ступени не ставит.** Маршрут подгалочек принимает только сессию человека: ключ интеграции
  и агент человеком не являются. Сделать сотрудника старшим можно только в его карточке.

**Приглашение в свою команду.** Старший куратор открывает «Сотрудники» из «Проверки работ → Кураторы» кнопкой
«Пригласить куратора» и видит там **«Кураторы школы»**: свой список команды — куратор, сколько у него курсов,
сколько работ ждёт в его очереди, состояние («работает», «ждёт входа», «письмо не ушло»), поиск по имени и почте.
Имена без ссылок на карточки: карточка человека показывает заказы и деньги, а они куратору не открыты;
«Отозвать доступ» здесь не нарисован — доступ снимает администратор или владелец. Справа — «Что получит куратор»
(считается из таблицы прав) и форма приглашения: одно поле почты, роль подставлена. Приглашение уходит с ролью
«куратор» — другую роль ступень не выдаёт. Руководитель отдела продаж видит весь список сотрудников, а приглашает
только менеджеров. Роли уже работающих людей и ступени меняют владелец и администратор.

**Исход приглашения называется словами** (правка 20 сентября, кадр 3 «Заход 24, отчёт 1»):

| Что произошло | Что видно |
|---|---|
| Письмо ушло | «Приглашение ушло на адрес. Адрес появится в списке с пометкой „ждёт входа“» и кнопка «Пригласить ещё» |
| Почта школы не отправила письмо | «Письмо не ушло — причина. Приглашение сохранено, попробуйте отправить снова»; в списке у строки — «письмо не ушло», а не «ждёт входа» |
| Такой человек уже сотрудник | «Этот человек уже сотрудник школы — имя, роль»; имя показывается только тому, кто этого человека и так видит |

**Письмо доходит и на новую почту.** Раньше приглашение человеку, которого в школе ещё нет, никуда
не отправлялось: ссылка уходила в журнал сервера, а в списке появлялась строка «ждёт входа». Теперь письмо
уходит тем же текстом каталога («Приглашение сотрудника») и в том же оформлении школы, а отметка об отправке
хранится в самом приглашении.

**Воронки настраивает руководитель отдела продаж.** Менеджер ведёт сделки на доске, а «Настройки → Воронки
и этапы» — у администратора и РОПа: этапы доски одни на весь отдел.

**Кураторы курсов — у старшего куратора.** Кнопка «Кураторы курса» в «Проверке работ → Кураторы» (с выбранным
курсом) и «Снять с курса» в карточке куратора открывают вкладку «Кураторы» курса — без остального редактора: назначить
и снять куратора, куратор потока, куда деть учеников снятого, общая лента. Правило назначения — во вкладке
«Прохождение», её меняет тот, кто правит курс.

Что старшим добавится дальше — общие шаблоны ответов проверки у старшего куратора — в плане разработки,
пункт C10.11.

## Что видит человек без права

Кнопок и пунктов меню, которые откажут, у человека нет: их прячут те же правила, что проверяют действие.
Если он всё же откроет закрытую страницу по старой ссылке или набрав адрес, увидит страницу **«Нет доступа»**
(код 403): у его роли нет такого права, права выдают владелец и администратор. Это не ошибка и в отчёты
об ошибках не попадает. Запрос к API без права получает 403 с названием права словами.

## Что видит владелец, чего не видит администратор

История по конкретному человеку в журнале действий — только владельцу.
Администратор видит журнал школы, но не «всё, что делали с Петровым».

Настройки школы, платёжные системы и агент — пока владелец не откроет их
администратору поимённо. И контакт самого владельца: его почту и телефон
администратор не меняет.

## Как это спрашивают

Один вызов, и он одинаков для человека, ключа и агента:

```
can(субъект, "order.cancel")       // → да / нет
```

У некоторых прав есть **предмет**: куратор проверяет работу, только если
закреплён за потоком этого ученика. Тогда предмет передаётся тем же вызовом.

## У ИИ-агента прав нет

Агент действует правами того, кто с ним разговаривает. Список того, что он
вообще умеет предложить, отбирается по правам собеседника — а не прячется
в тексте подсказки.

Подсказка — не защита: модель не отличает данные от указаний, и присланный
ей файл может содержать «а теперь сделай вот это».
