Core-роли и каталог абилок
Источник правды: apps/backend/src/modules/spaces/abilities/core-abilities.ts.
Core roles
| Role | Назначение |
|---|---|
owner | Полный контроль space, members, policies, удаление артефактов |
editor | Создание и редактирование артефактов, без управления space |
viewer | Только чтение |
Core abilities (матрица по умолчанию)
| Ability ID | owner | editor | viewer | Категория |
|---|---|---|---|---|
space.read | ✓ | ✓ | ✓ | Space |
space.manage | ✓ | Space | ||
space.manageMembers | ✓ | Space | ||
space.managePolicies | ✓ | Space | ||
artifact.read | ✓ | ✓ | ✓ | Artifacts |
artifact.create | ✓ | ✓ | Artifacts | |
artifact.update | ✓ | ✓ | Artifacts | |
artifact.delete | ✓ | Artifacts | ||
artifact.move | ✓ | ✓ | Artifacts | |
artifact.runAction | ✓ | ✓ | Artifacts | |
artifact.agentEdit | ✓ | ✓ | Artifacts | |
artifact.manageVersions | ✓ | ✓ | Artifacts | |
template.use | ✓ | ✓ | ✓ | Templates |
template.create | ✓ | ✓ | Templates | |
template.manage | ✓ | Templates |
Owner space может переопределить grants в UI политик (см. policies) — например запретить artifact.delete для editor.
Маппинг на CASL
Ability ID маппится на проверки вида can(action, subject):
artifact.create→ созданиеArtifactв данномspaceIdspace.managePolicies→ mutationsetSpaceAbilityPolicy
Расширения добавляют свои ability ID; core не знает их семантику, только хранит grants.
Проверка в коде хоста
typescript
import { buildSpaceAbility } from '../spaces/abilities';
const ability = await buildSpaceAbility(context, { userId, spaceId });
ability.assert('artifact.update');
if (ability.can('artifact.agentEdit')) { /* ... */ }В entity hooks доступен тот же checker: hookCtx.ability?.can('artifact.create').