Перейти к основному содержимому

Роли и разрешения

AgentCore использует гибридную RBAC-модель. Legacy enum Role остаётся для совместимости, а SystemRole хранит редактируемые наборы разрешений и department scope. Переопределения на уровне пользователя разруливают исключения без отдельной таблицы-джоина разрешений.

Системные роли

Четыре встроенные роли сидируются как строки SystemRole с isSystem: true. Системные роли можно назначать пользователям и обновлять через миграции или seed-данные, но UI продукта не должен позволять тенантам их удалять.

РольDepartment scopeКлючевые разрешения
adminвсе отделывсе известные разрешения
dept_headсвой отдел и подотделыпользователи отдела, namespaces, персоны, approvals, знания, шаблоны, профили сотрудников
approverсвой отдел и подотделыapprovals, эскалации, просмотр всех approvals, чтение знаний, генерация документов
employeeсвой отдел и подотделычтение персоны, чтение знаний, генерация документов, чтение плагинов, свой профиль

Legacy enum-значения всё ещё есть в User.role. Если roleId задан — основным источником разрешений служит User.systemRole. Если не задан, бэкенд откатывается на legacy enum mapping.

Кастомные роли

Кастомные роли — это строки в system_roles с isSystem: false.

Поля:

ПолеНазначение
nameОтображаемое имя.
slugСтабильный lowercase-ключ. Генерируется из name, если не указан.
isSystemЗащищает встроенные роли от удаления.
allDepartmentsЕсли true, даёт межотдельскую видимость.
departmentIdsЯвный department scope, когда allDepartments: false.
permissionsМассив permission-ключей или * для всех разрешений.

Маршруты кастомных ролей:

GET /api/v1/permissions
GET /api/v1/roles
GET /api/v1/roles/:id
POST /api/v1/roles
PATCH /api/v1/roles/:id
DELETE /api/v1/roles/:id

Просмотр ролей требует canViewRoles. Создание, обновление и удаление — canManageRoles. Удаление системных ролей отклоняется.

Каталог разрешений

Разрешения — строковые ключи, сгруппированные для отображения в UI:

ГруппаКлючи
ПользователиcanViewAllUsers, canCreateUsers, canManageUsers, canManageDepartmentUsers
РолиcanViewRoles, canManageRoles
ОтделыcanManageDepartments, canArchiveDepartments
Namespaces и персоныcanManageNamespaces, canEditPersona, canViewPersona
ApprovalscanApprove, canEscalate, canViewAllApprovals
ЗнанияcanViewKnowledge, canUploadDocuments, canDeleteDocuments
Генерация документовcanGenerateDocuments, canManageTemplates
ПлагиныcanViewPlugins, canManagePlugins
АдминистрированиеcanViewAudit, canManageEmployeeProfiles, canEditSettings, canEditSelfProfile
Система*

API валидирует каждую кастомную роль и override по этому каталогу.

Матрица разрешений

Заполненная встроенная матрица:

РазрешениеAdminDept headApproverEmployee
canCreateUsersданетнетнет
canManageUsersданетнетнет
canManageDepartmentUsersдаданетнет
canViewAllUsersдададанет
canViewRolesданетнетнет
canManageRolesданетнетнет
canManageDepartmentsданетнетнет
canArchiveDepartmentsданетнетнет
canManageNamespacesдаданетнет
canEditPersonaдаданетнет
canViewPersonaдададада
canApproveдададанет
canEscalateдададанет
canViewAllApprovalsданетданет
canUploadDocumentsдаданетнет
canDeleteDocumentsдаданетнет
canViewKnowledgeдададада
canManageTemplatesдаданетнет
canGenerateDocumentsдададада
canManagePluginsданетнетнет
canViewPluginsдададада
canViewAuditданетнетнет
canManageEmployeeProfilesдаданетнет
canEditSelfProfileдададада
canEditSettingsданетнетнет

Кастомные роли могут выдавать любое подмножество этих разрешений.

User overrides

У каждого пользователя четыре массива override-ов:

ПолеЭффект
extraPermissionsДобавляет permission-ключи после оценки роли.
revokedPermissionsУбирает permission-ключи после применения extraPermissions.
extraDepartmentIdsДобавляет видимые отделы после оценки scope роли.
revokedDepartmentIdsУбирает отделы после применения extraDepartmentIds.

Маршруты override:

POST /api/v1/users/:id/permissions/grant
POST /api/v1/users/:id/permissions/revoke
DELETE /api/v1/users/:id/permissions/grant/:permission
DELETE /api/v1/users/:id/permissions/revoke/:permission
GET /api/v1/users/:id/effective-access

Grant- и revoke-запросы могут включать permission, departmentId или то и другое. Каждая мутация пишет audit-запись.

Формула эффективного доступа

Разрешения:

rolePermissions = user.systemRole?.permissions ?? legacyPermissions(user.role)
effectivePermissions = (rolePermissions + user.extraPermissions) - user.revokedPermissions

Если в extraPermissions есть *, он раскрывается во все известные permission-ключи. Revoke применяется последним, поэтому отозванное разрешение бьёт и базовую роль, и extraPermissions.

Отделы:

if role.allDepartments or legacy role is admin:
effectiveDepartments = all
else:
effectiveDepartments =
role.departmentIds
+ user.primaryDepartmentId
+ user.departmentId
+ user.extraDepartmentIds
- user.revokedDepartmentIds

Хелпер forUser() оборачивает это вычисление для кода маршрутов. Он даёт:

  • directWhere() для моделей с прямым departmentId;
  • nestedWhere('namespace') для моделей, scope которых задан через связь;
  • canSeeDept(id) для проверки ресурса;
  • hasPermission(key) для RBAC-чеков.

Правила разработки

  • Применяйте requirePermission() на привилегированных маршрутах.
  • В новом коде используйте forUser(request.user) вместо проверки role === 'admin'.
  • Для устойчивой политики тенанта предпочитайте кастомные роли, а override-ы — для индивидуальных исключений.
  • Держите revokedPermissions небольшим. Если нужно убрать разрешение у многих пользователей — сделайте другую кастомную роль.
  • При разборе тикетов по доступу используйте GET /users/:id/effective-access.