Andrey Epifancev 89abf0a8ec openspec: архив change slice-3b-statements-api (2026-10-07) — спеки documents-api, osv-result-mapping, statement-checks и др.
Ссылки README и CLAUDE.md переведены на архив.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 15:23:35 +04:00

7.4 KiB
Raw Blame History

users-admin Specification

Purpose

Администрирование доступа: пользователи, назначение ролей и матрица «роль × право» как данные (role_permission), с аудитом; минимальный экран администратора во фронте.

Requirements

Requirement: Пользователи — список, создание, изменение, деактивация

Маршруты /api/v1/admin/users (право USERS_ADMIN): GET — список с ролями и филиалом (поиск по email/ФИО, фильтр is_active, пагинация); POST — создание с обязательными email (уникален без учёта регистра → 409 EMAIL_EXISTS), full_name, regional_office_id, необязательными employee_no, business_segment, roles (коды); PATCH …/{id} — full_name, employee_no, regional_office_id, business_segment, is_active. Удаление MUST NOT предоставляться. external_id через API не задаётся. Каждая мутация пишет audit_event(USER_CHANGE, section = USERS).

Scenario: Создание с ролью

  • WHEN администратор создаёт пользователя с roles = ["KA_RF"]
  • THEN появляются app_user и user_role, GET /me от его имени (dev-токен) возвращает права KA_RF

Scenario: Email в другом регистре

  • WHEN создаётся пользователь с email, отличающимся от существующего только регистром
  • THEN ответ 409 EMAIL_EXISTS

Requirement: Назначение ролей

PUT /api/v1/admin/users/{id}/roles (тело: список кодов) SHALL заменять набор ролей пользователя: отсутствующие в наборе назначения удаляются, новые добавляются; неизвестный или неактивный код роли → 422; пишется audit_event(USER_ROLE_CHANGE, before_value = прежний набор, after_value = новый). Замена набора ролей MUST NOT оставить систему без активного пользователя с USERS_ADMIN (409 LAST_ADMIN): администратор не может снять с себя последнюю роль, дающую USERS_ADMIN, если он — единственный активный обладатель этого права; при наличии другого активного администратора снятие у себя разрешено (решение №34).

Scenario: Замена набора ролей

  • WHEN у пользователя роли [KA_RF], администратор ставит [KA_GO, EXPERT]
  • THEN user_role содержит ровно две новые строки, в аудите before_value = ["KA_RF"], after_value = ["KA_GO","EXPERT"]

Scenario: Последний администратор

  • WHEN единственный активный пользователь с USERS_ADMIN снимает с себя роль ADMIN
  • THEN ответ 409 LAST_ADMIN, роли не изменены

Requirement: Матрица прав

GET /api/v1/admin/roles SHALL отдавать роли с их правами; GET /api/v1/admin/permissions — справочник прав (16 кодов, только чтение; создание прав MUST NOT предоставляться); PUT /api/v1/admin/roles/{code}/permissions (тело: список кодов прав) SHALL заменять набор прав роли и писать audit_event(ROLE_PERMISSION_CHANGE) с before/after. Системные роли (is_system) нельзя деактивировать или переименовать; нельзя снять USERS_ADMIN с роли, если после этого ни у одного активного пользователя не останется этого права (409 LAST_ADMIN).

Scenario: Изменение матрицы

  • WHEN у роли EXPERT добавляется право EXPORT
  • THEN role_permission содержит новую строку, пользователь с ролью EXPERT при следующем запросе /me видит EXPORT, в аудите ROLE_PERMISSION_CHANGE

Scenario: Снятие USERS_ADMIN с единственной роли

  • WHEN у роли ADMIN (единственной с USERS_ADMIN у активных пользователей) убирают USERS_ADMIN
  • THEN ответ 409 LAST_ADMIN

Requirement: Минимальный экран администратора

SPA SHALL содержать маршрут /admin (пункт «Система → Пользователи и роли» в боковом меню), доступный при наличии USERS_ADMIN в ответе /api/v1/me: таблица пользователей с выбором ролей и формой создания, таблица «роль × право» с чекбоксами и кнопкой сохранения; запросы идут через общий API-клиент с заголовком Authorization: Bearer. В режиме разработки SHALL быть доступен ввод email для получения dev-токена (POST /api/v1/dev/token); в сборке для прода этот ввод отсутствует.

Scenario: Назначение роли через экран

  • WHEN администратор на /admin выбирает пользователю роль KA_GO и сохраняет
  • THEN вызывается PUT /admin/users/{id}/roles, таблица показывает новую роль, ошибка API показывается уведомлением

Scenario: Нет права

  • WHEN пользователь без USERS_ADMIN открывает /admin
  • THEN страница показывает сообщение об отсутствии доступа и не делает запросов к /admin/*

Requirement: Краткий справочник пользователей

GET /api/v1/users/brief?ids=<uuid>,… SHALL быть доступен любому аутентифицированному пользователю без отдельного права и отдавать [{id, full_name, is_active}] для найденных id, включая неактивных; неизвестные id MUST NOT возвращаться и MUST NOT давать ошибку; больше 200 id — 422 TOO_MANY_IDS; некорректный UUID — 422. Админский список пользователей не меняется.

Scenario: Имя загрузившего

  • WHEN аналитик без права USERS_ADMIN запрашивает ids из uploaded_by двух файлов и неизвестный UUID
  • THEN 200, два элемента с ФИО, неизвестный UUID отсутствует

Scenario: Слишком много id

  • WHEN передан 201 id
  • THEN 422 TOO_MANY_IDS