Роли и права доступа¶
Кто что может в Axon: семь канонических ролей, их permissions, scope (instance vs project) и как они назначаются. Плюс — персона
engineer/«architect», которой нет в RBAC. Источник истины —core/models/auth.py; при расхождении этого мануала с кодом — код главнее.
1. Что это и зачем¶
Каждая write-команда (CommandEnvelope) в Axon гейтится четырьмя проверками до любого side effect (инвариант 4 «безопасность до выполнения»):
- permission — есть ли у роли актора право на это действие (таблица
ROLE_PERMISSIONSвcore/models/auth.py); - object-scope — относится ли целевой объект к зоне, которой актору можно касаться;
- project-scope — у проектных ролей: входит ли
project_idобъекта вactor.project_scopes; - policy pre-check — Policy Engine; для side-effect'ов ещё и budget check.
Роль определяет что можно делать; scope — в каких проектах. Семь ролей: owner, admin, manager, operator, reviewer, read_only, system.
engineer / «architect» (программист) — не RBAC-роль: её нет в core/models/auth.py. Это персона, которая работает в коде (modules/, git) и при деплое. Для действий через Console/API (например publish_definition, create_credential) ей нужна обычная роль manager+. В мануалах, описывающих работу программиста, есть отдельный раздел «что делается в коде, а что в Console» (пример — Connectors-Credentials.md §2.1).
2. Роли и доступ¶
2.1 Роли и scope¶
| Роль | Тип | Scope | Кто это |
|---|---|---|---|
owner |
instance-scoped | все проекты инстанса | владелец инстанса; единственная роль с breakglass |
admin |
instance-scoped | все проекты инстанса | администратор инстанса; всё то же, что owner, минус breakglass |
manager |
project-scoped | только проекты из project_scopes |
настраивает и ведёт проект: коннекторы, креденшiалы, binding profiles, публикация workflow, бюджеты, approvals, кейсы |
operator |
project-scoped | только проекты из project_scopes |
запускает процессы, ведёт задачи/конверсации, использует креденшiалы (но не создаёт их) |
reviewer |
project-scoped | только проекты из project_scopes |
согласования (approve/reject); читает остальное |
read_only |
project-scoped | только проекты из project_scopes |
только чтение |
system |
служебный актор (actor_type=system) |
любой проект (is_system() → доступ есть) |
auto-refresh OAuth, health snapshots, retention sweepers, pre-dispatch хуки; людям не назначается (инвариант I-9) |
INSTANCE_SCOPED_ROLES = {owner, admin}. PROJECT_SCOPED_ROLES = {manager, operator, reviewer, read_only}. У instance-scoped ролей project_scopes равно «все» (в ActorContext это project_scopes=None); has_project_access(project_id) для них всегда True. Для project-scoped ролей — True только если project_id ∈ project_scopes.
actor_type ∈ {user, system, service}: user — человек; system — внутренние процессы платформы; service — внешние интеграции (если используются). is_system() даёт сквозной доступ к проектам (но всё равно гейтится permission'ами роли system + handler-level allowlist (command_type, actor_id, source) для чувствительных команд).
2.2 Матрица «permission × роль»¶
Из core/models/auth.py. owner = все «человеческие» permissions (HUMAN_PERMISSIONS); admin = то же минус breakglass. ✅ — есть, ❌ — нет, — — не применимо.
Проекты
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Создать проект | create_project |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Редактировать проект | edit_project |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Архивировать проект | archive_project |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Suspend / resume проект | suspend_project / resume_project |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
edit_projectтакже используется как permission внутренней командыupdate_connector_health(диспатчится только internal/system-актором).
Workflow
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Создать / редактировать workflow | create_workflow / edit_workflow |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Запустить workflow | start_workflow |
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | — |
| Pause / resume / cancel workflow | pause_workflow / resume_workflow / cancel_workflow |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Retry / replan workflow | retry_workflow / replan_workflow |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Опубликовать определение | publish_definition |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Настроить binding profile | workflow:configure_bindings |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Классификация (collections/labels — UI-навигация) | manage_workflow_classification |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Пиннинг binding snapshot run'а | workflow_run:pin_bindings |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅* |
| Инвалидация bindings | workflow_binding:invalidate |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅* |
* system-only (в
SYSTEM_ONLY_PERMISSIONS).pin_workflow_run_bindingsисполняется как sub-stepstart_workflow(акторworkflow_start_dispatcher).workflow_binding:invalidateзарезервирован (команды пока нет).
Задачи / конверсации
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Создать / редактировать задачу | create_task / edit_task |
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Отменить задачу | cancel_task |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Создать конверсацию | create_conversation |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Отправить сообщение | send_message |
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
Approvals
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Approve / reject | approve / reject_approval |
✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ |
Кейсы (case registry)
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Создать / редактировать / архивировать кейс | create_case / edit_case / archive_case |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Привязать external ref | attach_case_external_ref |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Удалить external ref | delete_case_external_ref |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
Менеджер может создавать/редактировать/архивировать кейсы и привязывать external refs, но не удалять их — это admin/owner.
Определения, агенты, промпты, шаблоны, каталог
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Управлять agent definitions | agent_definition:manage |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅† |
| Управлять промптами | prompt:manage |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅† |
| Управлять шаблонами | manage_templates |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Catalog: publish/archive | catalog:manage |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Catalog: install в проект | catalog:install |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
†
systemимеетagent_definition:manageиprompt:manageдля публикации built-in определений/промптов (origin='system'/'code'); handler-level scope-проверки всё равно гейтят конкретное действие.
Чтение, админ, replay
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Чтение (дашборды, статусы, аудит) | read |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Управлять пользователями | manage_users |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Breakglass | breakglass |
✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Replay | replay |
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
breakglass— толькоowner(admin = owner − breakglass). Это аварийный обход; каждое использование пишется вaudit.audit_log.
Креденшiалы и коннекторы (детали — Connectors-Credentials.md §2)
| Действие | Permission | owner | admin | manager | operator | reviewer | read_only | system |
|---|---|---|---|---|---|---|---|---|
| Видеть креденшiалы (redacted) | credential:read |
✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — |
| Создать / обновить / revoke креденшiал | credential:create / credential:update / credential:revoke |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Test connection | credential:test |
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Использовать в run'е | credential:use |
✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Rotate / OAuth refresh-reauthorize | credential:rotate |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ |
| Maintain (auto-healing) | credential:maintain |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅* |
| Purge (hard GDPR-erasure) | credential:purge |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌‡ |
| Allowlist toggle | project_connector:manage |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Connector instance CRUD | connector:manage |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Webhook ingress verifier upsert/disable | ingress_verifier:manage |
❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅* |
* в
SYSTEM_ONLY_PERMISSIONS— людям не выдаётся (I-9). ‡credential:purgeзарезервирован: его нет ни у одной роли вROLE_PERMISSIONS(включаяsystem) — это контрактная поверхность для Stage 3 retention sweepers, которые получают право специальным грантом.delete_credential/purge_credentialкоманд пока нет (см. Connectors-Credentials.md §6.4).
2.3 System-only permissions (инвариант I-9)¶
SYSTEM_ONLY_PERMISSIONS = {credential:maintain, credential:purge, ingress_verifier:manage, workflow_binding:invalidate, workflow_run:pin_bindings}. HUMAN_PERMISSIONS = все Permission − SYSTEM_ONLY_PERMISSIONS. Инвариант: HUMAN ∩ SYSTEM_ONLY = ∅ (есть блокирующий pytest). То есть owner/admin, даже имея «всё человеческое», эти права не получают — auto-healing и hard-purge по дизайну исполняются только системными акторами.
3. Где это в Console¶
Раздел сайдбара Users (под группой Administration; instance-level + per-project view). Доступен owner/admin (manage_users).
| Элемент | Что делает |
|---|---|
| Список пользователей | actor_id, имя/email, роль, project_scopes (или «все проекты» для owner/admin), статус (active/deactivated) |
Invite / New user |
завести пользователя, назначить роль и (для project-scoped ролей) project scopes |
Edit role |
сменить роль пользователю |
Edit project scopes |
для manager/operator/reviewer/read_only — список проектов, к которым есть доступ |
Deactivate |
отключить пользователя (pending-команды/approvals от него больше не принимаются) |
| Индикатор роли в шапке | у текущего пользователя видна его роль (например «Administrator owner») |
Операционная сторона (как именно завести/назначить, breakglass-флоу) — Users-And-Access-Management.md.
4. Концепции (mental model)¶
ActorContext (пробрасывается через все слои)
├─ actor_id — стабильный id актора
├─ actor_type — user | system | service
├─ actor_role — owner | admin | manager | operator | reviewer | read_only | system
└─ project_scopes — list[str] ИЛИ None (= все проекты, instance-scoped)
has_project_access(project_id):
instance-scoped role → True
actor_type == system → True
project_scopes is None → False (project-scoped без явных scopes — доступа нет)
else → project_id in project_scopes
Permission — StrEnum (~45 значений), сгруппированы по доменам (см. §2.2)
ROLE_PERMISSIONS: dict[Role, frozenset[Permission]]
owner = HUMAN_PERMISSIONS (включая breakglass)
admin = HUMAN_PERMISSIONS − {breakglass}
manager = <явный набор> | _CREDENTIAL_MANAGER_PERMISSIONS
operator/reviewer/read_only/system = <явные узкие наборы>
SYSTEM_ONLY_PERMISSIONS ⊂ Permission — никогда не у людей (I-9)
HUMAN_PERMISSIONS = Permission − SYSTEM_ONLY_PERMISSIONS
Ключевые идеи:
- instance-scoped vs project-scoped — owner/admin видят/трогают все проекты; остальные ограничены project_scopes. Это ортогонально роли-permission'ам: даже если у роли есть edit_workflow, project-scoped актор может редактировать только в своих проектах.
- system отделён от людей — system-актор имеет узкий набор прав (rotate/maintain/ingress/agent/prompt + pin/invalidate) и дополнительно гейтится handler-level allowlist'ом (command_type, actor_id, source) для чувствительных команд. Люди эти системные права не получают вовсе.
- credential:use ≠ право расшифровать — это «capability членства в проекте»; plaintext секретов расшифровывается только в worker.
- breakglass ≠ обход аудита — это аварийный owner-only override, который сам пишется в audit (инвариант 9: прозрачность).
5. Флоу: пошаговые сценарии¶
Флоу 1 — Завести менеджера для проекта (owner/admin)¶
- Console → Users →
Invite/New user. - Указать
actor_id/email, имя. - Роль =
manager. - Project scopes =
[<project_id>](один или несколько проектов). - Сохранить → пользователь может настраивать эти проекты (коннекторы, креденшiалы, binding profiles, публиковать workflow, бюджеты, approvals, кейсы). Доступа к
manage_users,create_project, шаблонам, agent/prompt definitions, classification у него нет.
Флоу 2 — Дать оператору ещё один проект (owner/admin)¶
- Console → Users → выбрать пользователя (
operator) →Edit project scopes. - Добавить
<new_project_id>в список. - Сохранить → оператор может запускать workflow / вести задачи / использовать креденшiалы в новом проекте (но не создавать креды/инстансы и не трогать allowlist — это
manager+).
Флоу 3 — Аварийный breakglass (owner только)¶
- Используется, когда штатный путь заблокирован (инцидент). Доступен только
owner(breakglass). - Каждое использование автоматически фиксируется в
audit.audit_log— это не «тихий root», а аудируемый override (инвариант 9). Подробнее — Security-And-Audit.md.
Флоу 4 — Деактивировать пользователя (owner/admin)¶
- Console → Users → выбрать пользователя →
Deactivate. - Эффект: новые команды/approvals от него не принимаются. Уже выполненные действия остаются в аудите. Если на нём висели pending approvals — их нужно переназначить другому approver'у с доступом.
6. Справочник опций¶
6.1 Роли (Role enum)¶
| Роль | Scope | Базовый набор permissions |
|---|---|---|
owner |
instance | HUMAN_PERMISSIONS (всё человеческое, включая breakglass) |
admin |
instance | HUMAN_PERMISSIONS − {breakglass} |
manager |
project | явный набор (workflow CRUD/lifecycle кроме retry/replan, publish_definition, tasks create/edit, approve/reject, conversations, read, cases create/edit/archive/attach, project_connector:manage, connector:manage, workflow:configure_bindings, catalog:install) + _CREDENTIAL_MANAGER_PERMISSIONS (credential read/create/update/rotate/revoke/test/use) |
operator |
project | create_task, edit_task, send_message, start_workflow, read, credential:read, credential:test, credential:use |
reviewer |
project | approve, reject_approval, read, credential:read |
read_only |
project | read, credential:read |
system |
actor_type=system | rotate_credential, maintain_credential, ingress_verifier:manage, workflow_binding:invalidate, workflow_run:pin_bindings, agent_definition:manage, prompt:manage |
6.2 ActorContext (поля)¶
| Поле | Тип | Что делает |
|---|---|---|
actor_id |
str | стабильный идентификатор актора (попадает в audit) |
actor_type |
user / system / service |
тип; system даёт сквозной project access |
actor_role |
Role |
определяет набор permissions |
project_scopes |
list[str] | None |
проекты, к которым есть доступ; None = все (instance-scoped) |
6.3 Полный список Permission¶
См. §2.2 (сгруппировано по доменам) и core/models/auth.py. Каждая write-команда мапится на один Permission (_COMMAND_PERMISSION_MAP в core/api/commands/execution_paths.py).
7. Жизненный цикл и обслуживание¶
- Смена роли —
Edit roleв Console (через CommandEnvelope, пишется в audit). Pending-действия пользователя остаются как есть; новые гейтятся уже новой ролью. - Деактивация — пользователь больше не может выполнять команды; данные/аудит сохраняются. Pending approvals на нём — переназначить.
- Ротация admin'ов / owner'а — операционная процедура; owner единственный с
breakglass, поэтому смена owner'а требует особой аккуратности (обычно: новый owner назначается действующим owner'ом). - Аудит изменений доступа — все изменения ролей/scopes/деактивации — в
audit.audit_log. credential:purge(зарезервировано) — появится у retention-sweeper-актора в beyond-Stage-3 (GDPR hard-purge); сейчас ни у одной роли нет.
8. Траблшутинг¶
| Симптом | Причина | Что делать |
|---|---|---|
403 / «permission denied» на команду |
у роли актора нет соответствующего Permission |
Свериться с §2.2; при необходимости — повысить роль (owner/admin) или дать право через ту роль, у которой оно есть. Не «выдумывать» новые permissions. |
| «Нет доступа к проекту» / объект не виден | project-scoped роль, и project_id не в project_scopes |
Edit project scopes (owner/admin) — добавить проект. |
Owner не находит breakglass у admin'а |
by design: admin = owner − breakglass |
breakglass есть только у owner. |
system-актор «не может» выполнить команду, хотя роль system |
команда не в его permission-наборе, либо не прошёл handler-level allowlist (command_type, actor_id, source) |
Проверить, что это действие вообще делается системным актором (не все); для чувствительных команд — нужен правильный actor_id/source. |
| Менеджер не может удалить external ref / опубликовать промпт / создать проект | manager этих прав не имеет (см. §2.2) |
Эти действия — admin/owner (а prompt:manage / agent_definition:manage — owner/admin/system). |
9. Ограничения и инварианты¶
HUMAN ∩ SYSTEM_ONLY = ∅(I-9).credential:maintain,credential:purge,ingress_verifier:manage,workflow_binding:invalidate,workflow_run:pin_bindings— никогда у людей; есть блокирующий тест.admin = owner − breakglass. Admin не получаетbreakglassни при каких условиях.- Безопасность до выполнения (инвариант 4): permission + object-scope + project-scope + policy pre-check (+ budget) — до side effect, не после.
- Все мутации — через CommandEnvelope. RBAC проверяется на сервере (server-side), не в UI. UI лишь скрывает недоступные действия — но не является границей безопасности.
- Optimistic concurrency. Где есть
version— мутирующие команды требуютexpected_version. - Прозрачность (инвариант 9): любое изменение доступа и любое использование
breakglass— вaudit.audit_log. engineer/«architect» — не RBAC-роль. Для Console/API-действий нужна реальная рольmanager+.
10. Связанные мануалы и каноны¶
- Users-And-Access-Management.md — операционная сторона: как завести пользователя, выдать роль/scopes, breakglass-флоу.
- Connectors-Credentials.md §2 — детальная RBAC-картина по креденшiалам/коннекторам.
- Security-And-Audit.md — object/project scope, policy pre-check, audit log, объяснимость.
- Workflows.md / Cases.md / Approvals.md / Templates-And-Catalog.md — доменные права в контексте.
- Каноны:
core/models/auth.py(источник истины),ARCHITECTURE-V6.md(Безопасность),RULES-CODDING-DEVOPS.md(роли, write-команды),VISION.md§7 (инварианты 4 и 9).