# PLAN — Переработка ролевых прав (Role Permissions Rework) > Составлен 2026-06-03 (Opus) по итогам разбора. Цель — сделать модель ролевых прав корректной > (зависимости), прозрачной (история, линт), гибкой (группы, пресеты, кастомные роли) и убрать > болезненный сайд-эффект (массовый разлогин при смене права). > > Факты по текущему коду (проверено): > - `backend/src/permissions/registry.js` — 23 ключа, роли teacher/student (+free_student зеркалит student); > поля `role/roles/default/label/desc/requireConfirmOff`. > - Резолв: `requirePermission` (`middleware/auth.js:46`) читает **живьём из БД**: user_permissions → > role_permissions → дефолт реестра. `authMiddleware` каждый запрос перечитывает роль из БД. > - Таблицы `role_permissions(role,permission,enabled)`, `user_permissions(user_id,permission,enabled)`. > - `permissionsController.js`: GET /api/permissions, POST (role-level), GET /me, GET/POST /users/:id, DELETE reset. > На каждое изменение — `token_version++` (role-level → у ВСЕХ юзеров роли; user-level → у одного). > - UI: `frontend/js/admin/sections/permissions.js` (тумблеры по ролям) + `user-detail.js` (оверрайды). --- ## Phase A — Быстрые победы (низкий риск) - [ ] **A1. Зависимости между правами (`requires`).** Поле `requires:[...]` в реестре (`questions.delete`→`questions.manage`; `templates.public`→`templates.manage`; `courses.interactive`→`courses.manage`; `simulations.quiz`→`simulations.access`). Enforce в `requirePermission` (effective = own AND все requires). Учесть в `/me` и `/users/:id` (effective с учётом requires). UI: каскад (родитель off → дочерние серые/выключены). Тест. - [ ] **A2. Гигиена реестра + ясные метки.** Тест-линт: каждый ключ из `requirePermission/perm(...)` в коде есть в реестре; предупреждать о неиспользуемых ключах. Метки `theory.access`/`simulations.access` переформулировать как «… доступен роли» (видимость конкретного — по классам в content_access). - [ ] **A3. История изменений прав в UI.** Аудит уже пишется (`permission.set`/`permission.user_set`/ `permission.user_reset`). Эндпоинт `GET /api/permissions/log` (+ опц. фильтр по роли/пользователю), кнопка «История» на вкладке «Доступ · роли» и в карточке пользователя. Переиспользовать паттерн `/api/access/log`. - [ ] **A4. Смягчить `token_version++`.** Сервер уже применяет права live → массовый разлогин роли при одном тумблере не нужен. Убрать bump на role-level (и/или user-level), вместо этого клиент пере-запрашивает `/permissions/me` при `focus`/навигации. Сохранить немедленный серверный эффект (он и так есть). Аккуратно: проверить, где клиент кэширует права (lab-glue и т. п.). ## Phase B — Среднее (управление при масштабе) - [ ] **B5. Группы прав (`group`).** Поле `group` в реестре («Контент»/«Класс»/«Геймификация»/«Профиль»/ «Библиотека») → секции в UI + «вкл/выкл всю группу». - [ ] **B6. Массовое применение к классу / выбранным ученикам.** Через `class_members`: выставить право пачке учеников (аналог матрицы/массовых операций content_access). - [ ] **B7. Пресеты-профили прав.** Бандлы («Ограниченный ученик», «Ассистент учителя») — применить к пользователю/классу одним кликом. - [ ] **B8. Временные права (`expires_at`).** Колонка в `user_permissions` + авто-снятие в резолвере/кроне. ## Phase C — Крупное / архитектурное - [ ] **C9. Кастомные роли.** Таблица ролей в БД + наборы дефолтов; реестр остаётся словарём ключей. Кандидаты: методист/завуч, классрук/куратор, ассистент учителя, родитель (есть `parentAuth`). - [ ] **C10. Делегирование учителю.** Часть студенческих прав — учителю в рамках его классов. - [ ] **C11. Пер-классовый скоуп прав.** Право на уровне класса (свести к модели content_access). Большая работа. ## Порядок исполнения A1 → A2 → A3 → A4 → B5 → B6 → B7 → B8 → C9 → C10 → C11. Phase C — отдельными ветками/планом (архитектура). ## Тесты/гочи - Бэкенд-тесты через `backend/tests/setup.js` (харнесс монтирует /api/permissions). Прогон `node --test`. - pre-commit гоняет полный backend-набор (baseline 3 Auth + флака «intro» в chemistry8-page под нагрузкой). - ⛔ эмодзи; коммитить поимённо; fetch перед работой (активны параллельные сессии на master). ## Прогресс (2026-06-03) - [x] A1 зависимости (requires) — commit 9ac2a61 - [x] A2 гигиена реестра (lint) + ясные метки — b0e385b - [x] A3 история изменений прав (endpoint + UI) — 7d474b4 - [x] A4 убран role-level token_version bump (нет массового разлогина) — 6bd1532 - Фаза A завершена. Далее по порядку: B5 группы прав → B6 массово к классу → B7 пресеты → B8 временные → C9-11. - Линт A2 подсветил: ряд teacher-прав (students.invite, sessions.reset, results.export, schedule.manage, templates.public, courses.interactive) и theory.access НЕ enforce-ятся через requirePermission — потенциальные гейты для проверки (отдельно). ## Прогресс — Phase B (2026-06-03) - [x] B5 группы прав — 0a24a66 - [x] B6 массово по классу — b95b639 - [x] B7 пресеты-профили — 8b495f1 - [x] B8 временные права (expires_at, миграция 053) — a250d15 - Phase A + Phase B ЗАВЕРШЕНЫ. Остаётся Phase C (C9 кастомные роли / C10 делегирование учителю / C11 пер-классовый скоуп) — архитектура, отдельной веткой + обсуждение.