06 Authorization

Матрица прав текущего фронта

Матрица прав текущего фронта

Назначение

Документ связывает текущие экраны frontend-ksailab с capability catalog и показывает, где сейчас фронт уже задаёт реальную поверхность доступа, а где экран пока является UI-шаблоном.

Источники

Матрица составлена по текущему фронту:

  • app/layouts/default.vue — основная навигация;
  • app/composables/useAuth.ts — текущая frontend auth-модель;
  • app/middleware/auth.global.ts — route guard;
  • app/pages/login.vue — текущая страница логина;
  • app/pages/auth/callback.vue — post-session bootstrap page;
  • app/pages/** — текущий набор экранов.

Связанные репозитории:

  • frontend-ksailab
  • backend-ksailab
  • docs-ksailab

Текущий auth-статус фронта

На сегодня frontend находится в переходном состоянии:

  • authRepository.ts уже bootstrap-ится через GET /api/v1/auth/me;
  • app/pages/auth/callback.vue уже ведёт себя как frontend post-session page и не владеет code exchange;
  • HTTP client уже использует cookie/session semantics (credentials: 'include');
  • runtime defaults для login/logout уже выровнены на backend entrypoints;
  • middleware всё ещё требует финальной cleanup-синхронизации, чтобы public auth routes не bootstrap-ились слишком рано;
  • права на экраны уже должны идти от backend capability set, но не весь UI ещё доведён до capability-driven поведения;
  • logged-out остаётся отдельным переходным UX-состоянием, потому что full platform logout ещё не завершён во всех companion repos.

Одновременно backend уже changed underneath:

  • canonical bootstrap endpoint теперь GET /api/v1/auth/me;
  • отдельного /capabilities endpoint в этой фазе нет;
  • local POST /api/v1/auth/login и POST /api/v1/auth/refresh больше не рабочий auth flow и возвращают 410 Gone;
  • onboarding orchestration уже существует в POST /api/v1/onboarding/*.

Это означает: матрица ниже описывает целевую permission-модель, но должна учитывать уже landed backend contract.

Canonical browser auth contract for frontend

Для frontend canonical human/browser auth contract выглядит так:

  1. frontend отправляет browser на GET /api/v1/auth/login;
  2. backend уводит browser в Keycloak;
  3. Keycloak возвращает browser на GET /api/v1/auth/callback;
  4. backend создаёт server-side auth session и возвращает browser cookie;
  5. backend редиректит browser обратно на frontend route;
  6. frontend вызывает GET /api/v1/auth/me.

Для target next wave шаг 4 означает:

  • browser cookie содержит только opaque session key;
  • auth session и tokens живут server-side;
  • /auth/me читает backend session storage, а не frontend token state.

Из этого следуют жёсткие правила:

  • frontend не владеет canonical code exchange;
  • frontend не должен считать direct frontend-to-Keycloak login рекомендуемым default path;
  • существование Keycloak client ksailab-frontend не делает frontend владельцем browser auth flow;
  • frontend ownership начинается с bootstrap UI state, menu gating и route/component guards после /auth/me.

Что backend уже даёт фронту

Auth bootstrap

GET /api/v1/auth/me уже возвращает:

  • principal;
  • classification;
  • realm_roles;
  • bundles;
  • effective_capabilities.

Текущий runtime capability baseline

Для первой auth/onboarding волны backend уже отдаёт:

  • auth.bootstrap.read
  • onboarding.teacher.create
  • onboarding.group.create
  • onboarding.group.assign_teacher
  • onboarding.student.bulk_create
  • onboarding.credentials.consume

Текущий onboarding API

Backend уже экспонирует:

  • POST /api/v1/onboarding/teachers
  • POST /api/v1/onboarding/groups
  • POST /api/v1/onboarding/groups/{group_id}/teachers
  • POST /api/v1/onboarding/groups/{group_id}/students/bulk
  • POST /api/v1/onboarding/credentials/consume

Важно: временный пароль больше не должен ожидаться inline в create-ответах. Во фронте нужно проектировать one-time receipt handoff.

Permissions read layer

Для admin-facing Permissions section backend теперь отдельно экспонирует:

  • GET /api/v1/permissions/catalog
  • GET /api/v1/permissions/role-mappings
  • GET /api/v1/permissions/bundles

Это read-only metadata layer для roles/bundles/catalog UX. Он не заменяет GET /api/v1/auth/me как bootstrap current principal.

Матрица экранов

Экран / разделRouteCapabilityStarter bundlesРоли по умолчаниюBackend ABACСтатус текущего UI
Главная/home.readadmin.base, teacher.base, student.baseadmin, teacher, studentНетРеальный экран
Входящие/inboxinbox.readadmin.base, teacher.base, student.baseadmin, teacher, studentНетUI-оболочка
Профиль/profileprofile.readadmin.base, teacher.base, student.baseadmin, teacher, studentSelf onlyРеальный экран
Настройки/settingssettings.readadmin.base, teacher.base, student.baseadmin, teacher, studentSelf onlyРеальный экран
Безопасность/settings/securitysettings.security.read / settings.security.manageadmin.base, teacher.base, student.baseadmin, teacher, studentSelf onlyРеальный self-service shell: экран открывает backend-owned account security entrypoint GET /api/v1/auth/account/security и не держит локальную password form
Уведомления/settings/notificationssettings.notifications.read / settings.notifications.manageadmin.base, teacher.base, student.baseadmin, teacher, studentSelf onlyРеальный экран
Модули/modulesmodules.readadmin.base, teacher.base, student.baseadmin, teacher, studentНетUI-обзор
Система/systemsystem.readadmin.baseadminНетUI-обзор, интеграционный экран
Учебные курсы/education/courseseducation.courses.read / education.courses.manageadmin.base, teacher.base, student.baseadmin, teacher, student(read)ДаРеальный экран, требует дальнейшего ABAC
Учебные группы/education/groupseducation.groups.read / education.groups.manage / education.groups.members.manageadmin.base, teacher.base, student.baseadmin, teacher, student(read)ДаРеальный экран, должен стать точкой group creation, teacher assignment и student onboarding
Библиотека/education/libraryeducation.library.readadmin.base, teacher.base, student.baseadmin, teacher, studentДаРеальный экран
Банк вопросов/education/question-bankeducation.question_bank.read / education.question_bank.manageadmin.base, teacher.baseadmin, teacherДаРеальный экран
Логирование/monitoring/loggingmonitoring.logs.readadmin.monitoringadminНетСейчас считать admin-only
Системная информация/monitoring/system-infomonitoring.system_info.readadmin.monitoringadminНетСейчас считать admin-only
БД диагностика/monitoring/db-diagnosticsmonitoring.db_diagnostics.readadmin.monitoringadminНетСейчас считать admin-only
K8S диагностика/monitoring/k8s-diagnosticsmonitoring.k8s_diagnostics.readadmin.monitoringadminНетСейчас считать admin-only
Разрешения -> Пользователи/permissions/userspermissions.users.read / permissions.users.manage / permissions.users.credentials.manageadmin.permissionsadminНетРеальный admin screen: teacher provisioning через onboarding contract, one-time credential handoff, live backend user directory. Follow-up password changes уходят в personal security flow; assignments / overrides и admin credential lifecycle ещё ждут backend contract
Разрешения -> Группы/permissions/groupspermissions.groups.read / permissions.groups.manageadmin.permissionsadminНетЧестный backend-backed shell: starter bundle catalog и capability composition теперь приходят через GET /api/v1/permissions/bundles и GET /api/v1/permissions/catalog. Group assignments ещё остаются follow-up контрактом
Разрешения -> Роли/permissions/roles, /permissions/roles/new, /permissions/roles/:roleKeypermissions.roles.read / permissions.roles.manageadmin.permissionsadminНетРеальный list/detail/create-shell без липового CRUD. Экран читает GET /api/v1/permissions/role-mappings, GET /api/v1/permissions/bundles и GET /api/v1/permissions/catalog, показывая runtime baseline отдельно от target starter model

Важные ограничения текущего фронта

1. Login shell уже частично Keycloak-first, но ещё не полностью выровнен

Сейчас frontend уже живёт рядом с backend-owned session contract, но в runtime defaults ещё может оставаться wrong path:

  • login не должен по умолчанию стартовать direct frontend -> Keycloak;
  • canonical path должен идти через backend /api/v1/auth/login;
  • logout не должен миновать backend /api/v1/auth/logout;
  • продуктовая кнопка Выйти не должна документироваться как local-only cleanup.

2. Route guards уже partially capability-driven

Текущий middleware уже использует backend bootstrap context и часть capability-based route resolution, но переход ещё не завершён:

  • public auth routes требуют финальной ordering-синхронизации;
  • не весь UI одинаково строго опирается на capability manifest;
  • contract всё ещё нельзя считать полностью стабилизированным, пока frontend issue по auth alignment не закрыт.

3. Permissions section частично уже живёт на реальном API

Секция permissions/* больше не должна трактоваться как набор скрытых моков, но и не вся административная модель уже раскрыта backend.

Текущее состояние такое:

  • permissions/users уже работает поверх onboarding contract и backend user directory: teacher accounts, one-time credential handoff и базовые activate/delete lifecycle actions читаются как реальный runtime flow, а follow-up password changes делегированы в personal security flow;
  • permissions/groups больше не использует локальные массивы и fake CRUD: starter bundle catalog и capability composition уже читаются из backend read layer, но group assignments ещё ждут отдельный contract;
  • permissions/roles больше не использует моковые строки и локальный CRUD: starter role mappings и runtime baseline теперь читаются из backend read layer, но write-orchestration остаётся follow-up треком.

Дополнительно:

  • education/groups должен стать точкой bulk onboarding студентов и membership management;
  • teacher-side user creation сценарии из старого фронта не переносятся в v1 как разрешённый flow;
  • create flows не должны ожидать обычное поле temporary_password в response body.

4. Settings -> Security теперь backend-owned

/settings/security больше не должен документироваться как локальная password form внутри Nuxt.

Текущий фронт использует этот экран как self-service shell:

  • canonical entrypoint для пользователя — GET /api/v1/auth/account/security;
  • frontend не должен вызывать /users/password/* как рабочий UX;
  • delete-account и admin reset-password action нельзя показывать как живые, пока backend не отдаст отдельный lifecycle contract.

5. Monitoring и System требуют жёсткой явной политики

Даже если экран существует в меню, доступ к нему нельзя определять только по наличию route. Для этих разделов capability-подход обязателен с самого начала.

Что должен делать frontend после миграции

  1. Стартовать browser login через backend /api/v1/auth/login, а не через direct Keycloak URL как default contract.
  2. Инициализироваться через GET /api/v1/auth/me.
  3. Открывать self-service security только через GET /api/v1/auth/account/security, а не через legacy /users/password/* endpoints.
  4. Строить меню на основе capabilities.
  5. Применять route/component guards на основе capabilities.
  6. Не полагаться на роль как на единственный механизм доступа.
  7. Не считать скрытие элемента окончательной защитой, потому что backend всегда валидирует доступ повторно.

Отдельный /capabilities endpoint во frontend integration этой фазы закладывать не нужно: bootstrap идёт только через GET /api/v1/auth/me. При этом Permissions section может и должен читать отдельный read-only admin layer GET /api/v1/permissions/catalog, GET /api/v1/permissions/role-mappings и GET /api/v1/permissions/bundles. ksailab-frontend можно трактовать только как transition client contract в Keycloak, если runtime пока ещё требует его для совместимости. Это не меняет ownership canonical browser flow.

Как frontend участвует в быстром rollout фич

Frontend не должен ждать отдельной переработки role guards под каждую новую функцию.

Целевая схема:

  1. новый экран получает capability key;
  2. capability добавляется в bundle через admin UI;
  3. GET /api/v1/auth/me возвращает обновлённый effective capability set;
  4. меню и экран автоматически открываются нужной аудитории.

Для onboarding-сценариев это раскладывается так:

  1. permissions/users открывает admin-only teacher provisioning;
  2. education/groups открывает admin-only group and roster actions;
  3. student onboarding не требует отдельного меню, а живёт внутри group workflow;
  4. receipt consume flow показывает временный пароль только в одноразовом handoff UI.

Связанная operating model:

Что считать готовностью frontend permission-модели

Frontend считается согласованным с архитектурой, когда:

  • browser login стартует через backend entrypoint, а не через direct frontend-owned Keycloak flow;
  • browser logout различает local app cleanup и full platform logout;
  • каждый экран связан с capability key;
  • меню и CTA рендерятся по capabilities;
  • административные экраны не открываются по одному только факту логина;
  • GET /api/v1/auth/me полностью хватает для initial render и guards;
  • create/onboarding формы корректно работают с receipt-based credential handoff;
  • новые экраны добавляются через каталог capabilities, а не через набор ad-hoc условий.