Модель администрирования capabilities
Модель администрирования capabilities
Статус документа
Этот документ фиксирует операционную модель, по которой команда администрирует доступы в KSAILab после перехода на Keycloak.
Его цель: снять двусмысленность между IAM, platform permissions и frontend visibility.
По состоянию на 2026-03-11 backend auth foundation уже landed, поэтому ниже описывается не только target-state, но и текущий runtime baseline.
Короткий ответ
Где хранится каталог возможностей
Каталог capabilities хранится как версионируемый продуктовый контракт в двух местах:
- в backend как capability registry;
- в документации как canonical human-readable catalog.
Новые capability keys не создаются из UI и не заводятся вручную в Keycloak.
Где capabilities администрируются
Повседневное администрирование выполняется в platform UI, а не в Keycloak:
- админ собирает bundles;
- назначает bundles пользователям и группам;
- делает точечные allow/deny overrides;
- проверяет итоговый effective access.
Где хранятся назначения прав
Рабочие назначения прав хранятся в БД платформы:
- bundles;
- assignments;
- overrides;
- связи между bundle и capability.
Для чего нужен Keycloak
Keycloak хранит IAM-контур:
- identity;
- credentials;
- login/logout endpoints и SSO session lifecycle;
- realm roles;
- clients;
- protocol mappers;
- service account
ksailab-admin-service.
Важно: ksailab-admin-service нужен backend для provisioning и lifecycle-операций. Это не human admin.
Keycloak не является основным хранилищем полного каталога platform permissions.
Keycloak также не является владельцем canonical browser session bootstrap для KsaiLab UI: эту роль выполняет backend через /api/v1/auth/login, /api/v1/auth/callback и GET /api/v1/auth/me.
Принцип разделения ответственности
| Зона | Где живёт | Кто администрирует | Как часто меняется |
|---|---|---|---|
| Пользователь, пароль, login/logout endpoints | Keycloak | IAM/platform admin | По жизненному циклу аккаунтов |
Базовые realm roles admin, teacher, student | Keycloak | IAM/platform admin | Редко |
| Capability definitions | Backend + docs | Разработчики | При добавлении новых фич |
| Permission bundles | Платформа БД | Platform admin | Часто |
| Assignments user/group -> bundle | Платформа БД | Platform admin | Часто |
| Allow/deny overrides | Платформа БД | Platform admin | Точечно |
| Resource-scoped ABAC | Backend | Разработчики | При развитии доменной модели |
Runtime baseline после backend MR !10
Сейчас в runtime уже подтверждено:
- canonical browser login entry идёт через
GET /api/v1/auth/login; - canonical browser callback идёт через
GET /api/v1/auth/callback; - canonical browser logout идёт через
POST /api/v1/auth/logout; - frontend bootstrap идёт через
GET /api/v1/auth/me; - backend рассчитывает effective access по модели
principal + bundles + overrides; - local
POST /api/v1/auth/loginиPOST /api/v1/auth/refreshбольше не являются рабочим auth flow и возвращают410 Gone; - onboarding orchestration вынесен в отдельный
POST /api/v1/onboarding/*контур; - минимальный capability baseline уже существует в коде.
Это нужно читать как один непрерывный контракт:
- frontend инициирует browser login только через backend entrypoint;
- backend владеет code exchange и browser auth session;
- frontend потребляет только уже поднятый bootstrap-контекст через
/auth/me.
Следующая logout/session wave добавляет сюда ещё четыре жёстких правила:
- browser cookie = opaque session key only;
- auth session и access/refresh/id tokens = server-side only;
Redis= target storage для browser auth session;local app logoutиfull platform logout= разные уровни одного контракта.
Текущие runtime capability keys
На сейчас backend уже отдаёт:
auth.bootstrap.readonboarding.teacher.createonboarding.group.createonboarding.group.assign_teacheronboarding.student.bulk_createonboarding.credentials.consume
Текущие runtime bundle identifiers
Сейчас backend возвращает минимальную bootstrap summary через технические bundle identifiers:
role:adminrole:teacherrole:student
Это не отменяет более богатую целевую модель bundles вроде admin.base или admin.permissions, но важно не путать текущий runtime baseline с будущим административным UX.
Read-only permissions source of truth wave
Первая delivery-wave для permission administration deliberately вводит отдельный backend read layer без CRUD:
GET /api/v1/permissions/catalog;GET /api/v1/permissions/role-mappings;GET /api/v1/permissions/bundles.
Этот слой code-backed и нужен, чтобы frontend Permissions -> Roles и Permissions -> Groups перестали читать docs или локальные массивы как runtime source of truth.
Важно:
/auth/meостаётся bootstrap endpoint только для current principal;- новый
/api/v1/permissions/*слой не является generic/capabilitiesbootstrap endpoint; - role mappings и starter bundles в этой волне ещё не требуют отдельной DB-модели;
- assignments, overrides и write-оркестрация остаются follow-up треком.
Целевая административная модель
1. Capability Definition
Capability definition — это стабильный ключ вида domain.resource.action.
Примеры:
education.courses.readeducation.courses.managepermissions.users.managemonitoring.logs.read
Definition включает:
- ключ;
- display name;
- описание;
- тип (
globalилиresource-aware); - backend enforcement note;
- frontend usage note;
- suggested starter bundles.
Capability definition добавляется только через релиз и одновременно фиксируется:
- в backend registry;
- в
permission-catalog.md; - во frontend permission matrix, если capability влияет на экран или действие.
2. Permission Bundle
Bundle — это рабочий административный набор capabilities.
Именно bundles должны быть основной единицей повседневного администрирования, потому что они:
- быстрее поддерживаются, чем ручные назначения по одному permission;
- уменьшают хаос;
- позволяют быстро включать новую фичу без правок Keycloak.
Рекомендуемый продуктовый стартовый набор bundles:
admin.baseadmin.permissionsadmin.monitoringteacher.basestudent.base
Эти bundle names нужно трактовать как target administrative design для платформенного UI.
3. Assignment
Assignment связывает subject с bundle.
Subject может быть:
- пользователем;
- платформенной группой;
- в будущем организационным контекстом или workspace.
Основной путь выдачи прав:
- realm role даёт базовую классификацию пользователя;
- platform admin назначает один или несколько bundles;
- backend рассчитывает effective capabilities;
- frontend получает готовый capability set через
GET /api/v1/auth/me.
Важно: этот шаг 4 не означает, что frontend владеет permissions. Он только потребляет backend-calculated result.
4. Overrides
Overrides нужны как исключение, а не как основная модель.
Разрешены два вида:
allow overridedeny override
Приоритет:
deny overrideallow override- bundle grants
- starter mapping from realm role
Это правило нужно считать canonical precedence для всей платформы.
Как это администрируется в platform UI
Раздел Permissions
Целевой административный UX должен опираться на уже существующие frontend-разделы:
Permissions -> UsersPermissions -> GroupsPermissions -> Roles
Permissions -> Users
Экран должен покрывать:
- просмотр пользователя;
- его realm role;
- список назначенных bundles;
- effective capabilities;
- точечные allow/deny overrides;
- создание teacher accounts;
- запуск one-time credential handoff;
- lifecycle actions через отдельный backend credential/admin contract.
Текущий frontend runtime уже пришёл к этой модели частично:
- teacher account provisioning идёт через onboarding contract;
- временный пароль раскрывается только через one-time credential receipt flow;
- каталог пользователей, активация и удаление читаются из backend directory API;
- follow-up password changes больше не живут в admin UI и уходят в self-service
Settings -> Securityflow; - assignments, effective capabilities, allow/deny overrides и admin credential lifecycle ещё ждут отдельный backend permission contract.
Settings -> Security
Self-service безопасность не должна смешиваться с административным CRUD раздела Permissions.
Текущий frontend contract здесь такой:
Settings -> Securityоткрывает только backend-owned account security entrypointGET /api/v1/auth/account/security;- frontend не вызывает legacy
/users/password/*endpoints как рабочую модель; - delete-account и admin reset-password остаются явно unavailable, пока backend не отдаст отдельный lifecycle contract.
Permissions -> Groups
Экран должен покрывать:
- создание и редактирование permission bundles;
- привязку capabilities к bundle;
- назначение bundle группам;
- просмотр, какие пользователи получают право через group assignment.
Текущий frontend runtime здесь сознательно ограничен:
- экран больше не использует моковые группы, fake counters или локальный CRUD;
- он показывает живой backend snapshot существующих групп как будущих assignment targets;
- создание учебных групп и roster actions остаются в
Education -> Groups; - собственный bundle catalog и group assignments ещё должны прийти отдельным backend-контрактом.
Permissions -> Roles
Экран должен покрывать:
- mapping базовых realm roles к стартовым bundles;
- просмотр базового набора capabilities по role family;
- аудит, какие capabilities приходят из role starter mapping, а какие из bundle/override.
Текущий frontend runtime здесь тоже уже подготовлен к следующей волне:
- список, detail route и create route уже разведены как отдельные экраны;
- список показывает runtime baseline
role:admin,role:teacher,role:studentи документированные starter bundles / scope groups; - backend read-model теперь поставляет этот snapshot через
GET /api/v1/permissions/role-mappings,GET /api/v1/permissions/bundlesиGET /api/v1/permissions/catalog; - create и edit intentionally не притворяются рабочим CRUD, пока backend role mapping orchestration ещё не отдал контракт.
При этом onboarding первой версии раскладывается так:
Permissions -> Users— teacher accounts;Education -> Groups— создание groups;Education -> Groups -> roster— bulk onboarding студентов.
Это важно, потому что student provisioning в KSAILab привязан к group membership, а не к абстрактной пользовательской карточке.
Как быстро добавлять новую capability
Целевой рабочий сценарий должен занимать один релиз и несколько минут админской настройки после него.
Добавление новой фичи
- Разработчик добавляет capability key в backend registry.
- Разработчик обновляет
permission-catalog.md. - Разработчик добавляет backend policy check.
- Если capability влияет на UI, обновляется
frontend-permission-matrix.md. - После релиза platform admin открывает
Permissions -> Groupsи добавляет capability в нужные bundles. - Пользователи сразу получают новый доступ через существующие assignments.
Это и есть модель релиз + UI-настройка.
Удаление capability
Безопасный порядок:
- отметить capability как
deprecatedв каталоге; - убрать её из bundles;
- удалить обращения из frontend;
- удалить backend policy usage;
- только после этого удалять definition.
Что меняется без релиза, а что нет
Без релиза можно
- создать новый bundle;
- выдать или снять bundle;
- сделать точечный override;
- поменять composition существующих bundles;
- изменить mapping realm role -> starter bundles;
- отключить или включить пользователя через platform UI.
Для первой версии отдельно фиксируется:
- manual onboarding выполняет только
admin; - учётки teacher и student не создаются преподавателями;
- временный пароль выдаётся через
credential_receiptи одноразовый consume flow; - обычное добавление новой platform feature не требует правок в Keycloak.
Требует релиза
- новый capability key;
- новая backend policy;
- новая resource-scoped ABAC логика;
- новая frontend feature, если у неё ещё нет capability contract;
- изменения в auth flow;
- изменения клиентов, realm roles или mapper contract в Keycloak.
Как быстро настраивать Keycloak
Основной принцип
Keycloak нужно настраивать как Realm as Code, а не вручную через GUI как единственный способ работы.
Это означает:
- realm/bootstrap/provisioning config хранится в
keycloak-scripts-ksailab; - clients, roles и mappers заводятся через bootstrap/import;
- ручные правки в UI допустимы только для диагностики и экстренного администрирования.
Отдельные repo boundaries для Keycloak-контура:
ci-pipelines/pipelines-ksailab— source of truth для pipeline logic;infra-keycloak-ksailab— физический deployment Keycloak;keycloak-theme-ksailab— login theme и branding.
Поддерживаемый scripting path для scripts repo — только Python. PowerShell fallback больше не считается supported operational path.
Что обязательно должно быть описано as code
- realm;
- clients
ksailab-frontend,ksailab-backend,ksailab-admin-service; - redirect URIs;
- logout URIs и post-logout redirect contract;
- realm roles
admin,teacher,student; - protocol mappers для базовых claims и roles;
- service account permissions для backend orchestration.
При этом ownership clients нужно описывать явно:
ksailab-frontendможет оставаться transition browser-login client, если runtime ещё опирается на него под backend initiation;ksailab-backendне нужно путать с canonical browser-login client, пока он остаётся backend-facing audience/bearer contract;- target architecture предпочитает отдельный backend browser-auth client, чтобы убрать двусмысленность ownership.
Временная политика работы через Keycloak GUI
До полной стабилизации realm as code допускается использовать Keycloak GUI, но только как вспомогательный инструмент:
- для первичного исследования настроек realm/client;
- для smoke-валидации после деплоя;
- для аварийного unblock, если нужно быстро подтвердить гипотезу.
При этом действуют жёсткие правила:
- Ручная GUI-правка не становится канонической сама по себе.
- Любое рабочее изменение должно быть перенесено в
keycloak-scripts-ksailabв том же delivery cycle. - Если GUI-изменение влияет на backend/frontend contract, это отдельно фиксируется в docs и связанных issue.
- Долгоживущая конфигурация, существующая только в GUI, считается техническим долгом.
Отдельная boundary по human admin bootstrap:
- первый human admin
platform-adminсоздаётся через отдельный operator flow в Keycloak; - backend runtime может только проверять presence и синхронизировать профиль при login;
ksailab-admin-serviceне должен описываться как human admin surrogate.
Когда Keycloak реально нужно менять
Правки в Keycloak нужны, если меняется:
- login flow;
- client configuration;
- redirect URI policy;
- post-logout redirect policy;
- realm roles;
- federation;
- SSO/integration topology;
- claims или mapper contract.
Для обычного добавления новой platform feature Keycloak менять не нужно. Для обычного изменения bundles, assignments, overrides или capability rollout Keycloak также не должен становиться точкой ежедневного администрирования.
Что должен рассчитывать backend
Backend должен возвращать в GET /api/v1/auth/me уже готовый effective access context:
principal;classification;realm_roles;effective_capabilities;bundles.
Backend остаётся единственным источником истины по effective permissions, потому что только он видит:
- realm roles из IAM;
- bundles и assignments из БД платформы;
- overrides;
- ABAC-контекст ресурса.
Отдельно:
/auth/meне является прямым чтением Keycloak token payload для UI;/auth/meне заменяет backend session ownership;/auth/meне отменяет обязательную backend ABAC-проверку реального действия.
Критерии правильной модели
Модель считается операционно удачной, если:
- Keycloak не превращается в хранилище сотен platform permissions;
- новые capability keys появляются только через контролируемый релиз;
- админ может за минуты выдать новую фичу через bundle composition;
- frontend строит меню и экраны по
GET /api/v1/auth/me; - backend централизованно проверяет доступ и не полагается на UI.