Frontend Platform
Frontend Platform
Зачем нужен этот раздел
Этот раздел фиксирует роль frontend-ksailab в текущем auth/access контуре KSAILab после перехода на backend-owned browser session.
Проблема прошлых итераций была в том, что backend и IAM обсуждались отдельно, а реальная пользовательская поверхность доступа была размазана между меню, route guards, login pages и placeholder-экранами. Из-за этого команда легко скатывалась в спор, кто именно "владеет" browser auth flow.
Этот документ снимает двусмысленность:
- canonical human/browser auth flow принадлежит backend;
- frontend является consumer backend session/bootstrap;
- frontend использует
effective_capabilitiesдля UI gating; - frontend не владеет canonical OIDC code exchange.
Связанные репозитории:
frontend-ksailabbackend-ksailabdocs-ksailabkeycloak-scripts-ksailab
Что представляет собой текущий фронт
Текущий frontend-ksailab — это Nuxt 4 приложение с dashboard-навигацией и уже заметной платформенной поверхностью:
- главная;
- входящие;
- образование;
- мониторинг;
- система;
- разрешения;
- модули;
- настройки;
- профиль.
Именно этот UI уже диктует, какие global capabilities нужны для меню, страниц, CTA и route guards.
Что есть во фронте сейчас
Навигация
Основная навигация описана в app/layouts/default.vue и уже задаёт реальный список разделов, которые нужно открывать или скрывать по access context.
Аутентификация
Текущий frontend auth-слой нужно читать как переходный, но уже частично aligned с backend-owned contract:
useAuth.tsхранит frontend auth-state;authRepository.tsуже читаетGET /api/v1/auth/me;app/pages/auth/callback.vueуже работает как post-session bootstrap page;- infrastructure HTTP client уже использует cookie/session semantics;
- menu и route visibility постепенно переводятся на capability-driven access context.
При этом переходное состояние ещё не завершено:
- runtime defaults для login/logout уже выровнены на backend entrypoints, но logout UX и Keycloak SSO semantics ещё не доведены до финального full platform logout;
- часть guard logic ещё нуждается в cleanup, чтобы public auth routes не bootstrap-ились раньше времени;
- не весь UI ещё доведён до чистого capability-driven поведения.
Одновременно backend уже изменился:
- canonical browser login entrypoint теперь
GET /api/v1/auth/login; - canonical callback endpoint теперь
GET /api/v1/auth/callback; - canonical logout endpoint теперь
POST /api/v1/auth/logout; - canonical bootstrap endpoint теперь
GET /api/v1/auth/me; - отдельного
/capabilitiesendpoint в этой фазе нет; - local
POST /api/v1/auth/loginиPOST /api/v1/auth/refreshвозвращают410 Gone; - onboarding orchestration уже существует в
POST /api/v1/onboarding/*.
Из companion contracts для следующей wave frontend должен читать ещё и это:
POST /api/v1/auth/logoutнельзя трактовать только как local cleanup action;- self-service security должна стартовать через
GET /api/v1/auth/account/security, а не через legacy/users/password/*UX; logged-out,session-expiredиunauthorizedдолжны оставаться разными UX-сценариями;- продуктовая кнопка
Выйтидолжна приводить к full platform logout, а не к мгновенному silent re-login через живую Keycloak SSO session.
Экраны в состоянии partial contract / data-ready shell
Часть экранов уже полезна как реальная архитектурная поверхность, но backend раскрыт для них не полностью:
permissions/usersуже работает на реальных onboarding и user-directory контрактах;settings/securityбольше не является локальной password form и используется как backend-owned self-service shell для account security;permissions/groupsпереведён на честный backend snapshot без локального CRUD, но bundle/group assignment contract ещё отсутствует;permissions/rolesпереведён на list/detail/create-shell flow без мокового CRUD, но backend role mapping contract ещё отсутствует;- часть monitoring/system экранов всё ещё остаётся UI-shell.
Их всё равно нужно учитывать уже сейчас, потому что именно они формируют будущую административную модель.
Для первой полноценной реализации эти разделы должны получить такие роли:
permissions/users— teacher accounts, one-time credential handoff, assignments, overrides, user lifecycle;settings/security— self-service password/recovery shell через backend account security entrypoint;permissions/groups— bundles и групповые назначения;permissions/roles— mapping realm roles к starter bundles.
Отдельно важно зафиксировать onboarding surface:
education/groups— создание групп и roster actions;education/groups -> group detail— bulk onboarding студентов;- teacher-side создание пользователей из старого фронта не переносится как разрешённый flow v1.
Роль фронта в auth-схеме
Frontend не должен быть источником истины по доступам. Его задача — корректно потреблять уже рассчитанный access context.
Фронт должен
- отправлять browser login в backend entrypoint, а не напрямую в Keycloak по умолчанию;
- получать principal и capabilities через backend;
- рендерить меню по capabilities;
- применять route guards по capabilities;
- применять component-level visibility helpers;
- не дублировать backend ABAC на уровне бизнес-логики.
Фронт не должен
- считать роль единственным источником доступа;
- парсить JWT как основной permission source;
- владеть canonical browser code exchange;
- строить browser auth вокруг frontend-managed access/refresh lifecycle;
- хранить ad-hoc набор булевых флагов под каждый экран;
- считать hidden button достаточной защитой.
Canonical Browser Flow
Для frontend canonical human/browser auth contract выглядит так:
- Frontend отправляет browser на
GET /api/v1/auth/login. - Backend уводит browser в Keycloak.
- Keycloak возвращает browser на
GET /api/v1/auth/callback. - Backend выполняет callback/exchange, формирует server-side auth session и редиректит browser обратно на frontend route.
- Frontend запрашивает
GET /api/v1/auth/me. - Frontend получает:
principal;classification;realm_roles;bundles;effective_capabilities.
- Меню, страницы и компоненты рендерятся на основе capabilities.
- Любой реальный action всё равно повторно валидируется backend.
flowchart LR
F[Frontend] -->|GET /api/v1/auth/login| B[Backend]
B -->|Redirect| K[Keycloak]
K -->|GET /api/v1/auth/callback| B
B -->|Set opaque cookie + redirect| F
F -->|GET /api/v1/auth/me| B
Для frontend эту диаграмму нужно читать так:
- browser получает только session key cookie;
- auth session и tokens не живут в frontend state как canonical source;
/auth/meостаётся единственным bootstrap surface для UI.
Logout semantics for frontend
Frontend должен различать два уровня logout, а не скрывать их за одним действием:
Local app logout
- backend session и локальная app cookie больше невалидны;
- frontend переходит в
logged-outсостояние; - Keycloak SSO session может ещё оставаться живой;
- это объясняет, почему временный
logged-outUX workaround на frontend ещё не должен приниматься за финальный продуктовый контракт.
Full platform logout
- local app session завершена;
- Keycloak SSO session тоже завершена;
- следующий заход требует реального login flow, а не silent re-login;
- именно это должно быть user-facing meaning кнопки
Выйтив KSAILab.
Что сейчас остаётся переходным
frontend-ksailabнаmainвсё ещё содержитlogged-outrecovery semantics, чтобы не отправлять пользователя обратно в мгновенный re-login;- это нужно описывать как transitional UX gap до завершения
backend-ksailab#14иksailab-keycloak-scripts#9, а не как целевой смысл logout.
Transition vs target client model
Current transition model
Текущее переходное состояние нужно читать так:
- canonical browser flow уже backend-owned;
- frontend остаётся только consumer backend session/bootstrap;
- существующий Keycloak client
ksailab-frontendможет ещё участвовать в runtime-совместимости; - это не должно документироваться как признак frontend ownership над browser auth flow.
Практическое следствие:
- даже если backend временно инициирует browser login через текущую client config
ksailab-frontend, canonical owner flow всё равно backend; - direct frontend-to-Keycloak login не должен описываться как поддерживаемый default browser contract.
Target model
Архитектурный фаворит:
- отдельный backend browser-auth client в Keycloak;
- явная redirect/logout policy под backend callback surface;
- отсутствие двусмысленности между browser-session auth и explicit bearer/manual contract;
ksailab-frontendперестаёт трактоваться как долгосрочный canonical browser-login client.
Что именно фронт диктует архитектуре прав
Текущий фронт уже требует от backend и auth-системы как минимум следующих свойств:
- стабильный capability catalog;
- единый bootstrap endpoint;
- чёткое разделение между global capabilities и resource-scoped ABAC;
- возможность быстро подключать новый экран без полной переработки ролей;
- понятную административную модель для раздела
Разрешения.
Это означает, что frontend должен получать не только roles, но и уже рассчитанный набор:
effective_capabilities;bundles;- principal и профильный контекст.
Отдельно важно: ksailab-frontend как client name не должен использоваться как аргумент в пользу direct frontend-to-Keycloak login по умолчанию.
Что backend уже подготовил для фронта
Для первой auth/onboarding волны backend уже landed:
GET /api/v1/auth/login;GET /api/v1/auth/callback;POST /api/v1/auth/logout;GET /api/v1/auth/me;- отсутствие отдельного
/capabilitiesendpoint в первой фазе; - deprecated
410 Goneдля legacy local login/refresh; 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.
Текущий runtime capability baseline:
auth.bootstrap.readonboarding.teacher.createonboarding.group.createonboarding.group.assign_teacheronboarding.student.bulk_createonboarding.credentials.consume
Важно:
- create-операции больше не должны проектироваться как ответы с обычным inline
temporary_password; - frontend должен делать one-time receipt handoff;
- explicit bearer flow допустим только как отдельный non-browser/manual сценарий;
- bearer flow не должен становиться базой для browser bootstrap и не отменяет session/cookie contract;
- browser cookie должна трактоваться как opaque session key, а не как место хранения token payload.
Как старый фронт помогает текущему этапу
Старый фронт прошлого проекта дал полезные UX-референсы для текущего этапа, хотя его auth-модель уже legacy:
- ручное создание teacher account;
- bulk creation groups;
- bulk creation students с назначением в группу;
- reset password и lifecycle actions как legacy UX reference only: в текущем продукте парольный self-service вынесен в backend-owned security flow.
Именно эти UX-сценарии нужно использовать как основу нового onboarding, но с другой политикой доступа:
- provisioning выполняет только
admin; - credentials управляются через Keycloak;
- временный пароль раскрывается через receipt consume flow;
- первый вход требует смены временного пароля.
Validation и expected tests
Фронтовая реализация будет считаться корректной, когда появятся:
- tests на старт login через backend
/api/v1/auth/login; - tests на bootstrap через
GET /api/v1/auth/me; - tests на различие
logged-outvssession-expiredи на то, что logout не превращается обратно в implicit login success; - smoke на target full platform logout после завершения companion backend/keycloak changes;
- tests, подтверждающие, что frontend не ожидает отдельный
/capabilitiesendpoint; - tests на capability-driven menu и route guards;
- tests на отсутствие premature bootstrap на public auth routes;
- tests на onboarding teacher/group/student UI flows;
- tests на одноразовый показ временного пароля через receipt consume flow.