# Proposal: Срез 1 — справочники (API), импорт из ЕЦП CRM, политика видимости, администрирование пользователей **Срез:** 1 «Справочники» (`../docs/context/09-delivery-plan.md`), в сокращённом объёме по решению владельца 04.10.2026: **без UI справочника**, экран администратора — минимальный. Цель — быстрее дойти до Среза 2 (`tabular-parser`). **Репозиторий:** arm-core. **Issue:** RSHB/arm-core#5. **Родительский change:** `../docs/openspec/changes/slice-1-directories` (DBML v5.14, §13 импорт, §10.1 видимость, OQ-86…91). **Фикстура:** `../fixtures/directories/ecp-export-russkiy-biskvit.xlsx` (RSHB/arm-ka-fixtures#2). ## Why Срез 2 (загрузка файлов и парсер) требует, чтобы в ядре уже были ЮЛ-владельцы файлов, их ГК и состав ГСК, а также пользователи с ролями, под которыми загружают. В Срезе 0 есть только схема, seed ролей и `/api/v1/me`: ни одной записи справочника создать нельзя, пользователей заводит только seed. Срез 1 даёт API справочников, импорт реальной выгрузки ЕЦП CRM (8400 строк, 345 ГК — включая группу «Русский Бисквит» для тестов), правило видимости по филиалу и администрирование пользователей. ## What Changes - **DBML v5.14** (`../docs/model/data-model-v5.14.dbml`): `related_group_member.kind` + частичный уникальный индекс `(legal_entity_id, kind) WHERE is_current` (ЮЛ одновременно в одной ГСК и одной ГСЗ), `audit_action` + `LEGAL_ENTITY_CHANGE`, `USER_CHANGE`. ORM, миграция `0002_dbml_v5_14`, `DBML_VERSION`, `Makefile`, `dbml_parity.DBML_FILE_NAME`, тесты миграций и паритета — на v5.14. Таблиц 43, enum'ов 27 — без изменений. - **Инфраструктура запросов** (общая для всех мутаций): зависимость сессии с commit при успехе и rollback при ошибке; зависимость `AuditService` с `ip_address`/`user_agent` из запроса и `user_id` из `Principal`; доменные исключения `NotFoundError` → 404, `ConflictError` → 409 (с осмысленным текстом вместо шаблонного «нарушение целостности»), `DomainValidationError` → 422; единый формат списков `{items, total, limit, offset}`. - **Policy-слой** `src/domain/policy.py` (чистые функции, без ролей): видимость ГК/ЮЛ по филиалу — ГО видит всё, филиал — ГК своего РФ и своих монозаёмщиков (§10.1); применение — фильтр в репозиториях и проверка на объекте (404 вне видимости). - **API справочников** (`/api/v1/directories/…`, права `DIRECTORY_VIEW` / `DIRECTORY_EDIT` / `DIRECTORY_DELETE`): - филиалы: список; - ГК: список (поиск по имени/`crm_id`, архив), карточка, создание (`code` генерируется `GK-NNNNNN`), изменение (имя, РФ — снимок в `company_group_history`, `GROUP_CHANGE`/`ASSIGNMENT_CHANGE`), архив/разархив, история; - ЮЛ/ИП: список (фильтры: ГК, «вне ГК», ИНН, имя), карточка, создание (ИНН 10/12 по типу), изменение, перевод в другую ГК (`MOVE_TO_GROUP`, `effective_date`), вывод из состава (`CLOSE` / `REMOVE_FROM_GROUP`), история, алиасы (добавить/удалить, `normalized_alias` по §3, конфликт с чужим алиасом → 409); - ГСК/ГСЗ: список по ГК, создание (`code` `GSK-`/`GSZ-NNNNNN`), изменение, удаление пустой (ASSUMPTION(OQ-34)), состав: добавить/исключить (SCD2; одна группа каждого вида на ЮЛ; ЮЛ только из той же ГК). - **Импорт из ЕЦП CRM** (`POST /api/v1/directories/import`, право `DIRECTORY_ADMIN`): xlsx/csv по §13 (`openpyxl` добавляется в `requirements.txt`), `dry_run`, `on_existing = skip | update`, одна транзакция, построчные коды §13.2, отчёт в ответе и в `audit_event(DIRECTORY_IMPORT)`, файл в S3 `uploads/imports/{audit_event_id}/{name}` + `s3_object`. Допущения `ASSUMPTION(OQ-87…OQ-91)` в коде. Тесты: срез по «Русскому Бисквиту» из fixtures и `dry_run` всей выгрузки (маркер `fixtures`, `ARM_KA_DOCS`). - **Администрирование** (`/api/v1/admin/…`, право `USERS_ADMIN`): пользователи (список, создание с обязательным email, изменение, деактивация; `USER_CHANGE`), роли (список), назначение ролей пользователю (`USER_ROLE_CHANGE`), матрица `role_permission` (чтение, замена набора прав роли; `ROLE_PERMISSION_CHANGE`); нельзя снять `USERS_ADMIN` с себя. - **Минимальный экран администратора** (`web/`): API-клиент с `Authorization: Bearer` (dev-токен по email в режиме разработки), страница `/admin`: таблица пользователей с назначением ролей и форма создания, матрица «роль × право» с чекбоксами. Без справочника ГК/ЮЛ (решение владельца). - **Фикстуры тестов**: фабрики `make_company_group`, `make_legal_entity`, `make_user`; общая фикстура `auth_client`. - **Документы:** `README.md` (API, импорт, права), `CLAUDE.md`, спеки. ## Capabilities ### New Capabilities - `directories-api`: ГК, ЮЛ/ИП, алиасы, ГСК/ГСЗ и состав, филиалы — поведение API, истории и аудита. - `directory-import`: импорт выгрузки ЕЦП CRM по §13 с отчётом, `dry_run`, стратегией дублей и следом в аудите/S3. - `directory-policy`: видимость справочников по филиалу без проверки кода роли. - `users-admin`: администрирование пользователей, назначения ролей и матрицы прав; минимальный экран администратора. ### Modified Capabilities - `data-model`: схема равна DBML **v5.14** (требования «Схема БД равна DBML», «Версия DBML зафиксирована в коде»); миграции 0001 → 0002 применяются с нуля и откатываются. - `audit-trail`: добавляется требование, какие события пишут справочники, импорт и администрирование (новые значения `LEGAL_ENTITY_CHANGE`, `USER_CHANGE`). ## Impact - **Таблицы DBML v5.14:** `regional_office` (чтение, создание при импорте), `company_group`, `company_group_history`, `legal_entity`, `legal_entity_history`, `legal_entity_alias`, `related_group`, `related_group_member` (новая колонка `kind`), `app_user`, `user_role`, `role_permission`, `audit_event`, `s3_object` (файл импорта). Полей вне DBML нет. - **Правила:** §3 (нормализация алиаса), §10/§10.1 (права и видимость), §13 (импорт, ручные операции). - **Зависимости:** `openpyxl` (чтение xlsx, в `requirements.txt`); фронт — без новых пакетов (antd, RTK уже есть). - **Seed:** права и матрица не меняются (16 кодов); `test_me_and_dev_token`/`test_seed_roles` не трогаются. - **Внешние системы:** S3 (файл импорта), PostgreSQL 16 (миграция 0002). ## Non-goals - UI справочника ГК/ЮЛ/ГСК по макету (экраны 50, 51, 61, 77–80) — отдельный срез. - Нерезиденты и физлица в справочнике, контрольные разряды ИНН, маппинг «ЦКБ»/«Головная организация» на ГО, несколько ГСК в одной ГК из выгрузки — после ответов OQ-87…OQ-91. - Фильтр видимости по ЗО (`business_segment`) — поля у ГК нет (OQ-86). - Онлайн-интеграция с ЕЦП CRM; удаление ГК и ЮЛ (только архив/закрытие); восстановление истории назад. - Проверка JWT РАИСА, аудит входа (`LOGIN`) — остаются как в Срезе 0.