Andrey Epifancev 8bc76c69a0 docs(openspec): спеки синхронизированы с кодом issue #9 (ревью R-4)
- reference-data-seed: матрица role_permission целиком — только в пустую
  таблицу, в заполненную — лишь пары ролей/прав, вставленных тем же запуском
  (сценарии: снятое право, новые роль и право, все связи сняты); `--dev` только
  при DEBUG=true (код 2 до обращения к БД).
- audit-trail: требование «События входа» (LOGIN/LOGIN_FAILED, раздел SESSION)
  — исключение из «той же транзакции» с обоснованием, обрезка полей, доверенные
  прокси; строки в таблице событий.
- authn-authz: ссылка на аудит входа; требование «Прод-конфигурация
  HTTP-поверхности» — /docs, /redoc, /openapi.json только при DEBUG, CORS по
  CORS_ORIGINS, 405 на неверный метод, 404 под /api/v1, GET / без редиректа.

`openspec validate --specs`: 9 passed, 0 failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:49:46 +04:00

85 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# reference-data-seed Specification
## Purpose
Справочники продукта (роли, права и их матрица, план счетов, правила элиминации, состав обязательных документов) и
dev-данные загружаются из файлов репозитория одной идемпотентной командой; повторный запуск ничего не дублирует.
## Requirements
### Requirement: Идемпотентный seed справочников продукта
Команда `python -m scripts.seed` (из `api/`) SHALL загрузить из `api/seed/core/`: `regional_office` (Головной офис,
`is_head_office = true`), `role` — 7 системных ролей ТЗ 8.1 (`KA_RF`, `KA_GO`, `RKA`, `CLIENT_MANAGER`, `CURATOR_GO`,
`EXPERT`, `ADMIN`, `is_system = true`), `permission` — 16 сочетаний объект × действие из §10 правил с кодами
`<OBJECT>_<ACTION>` (`EXPORT` при совпадении), `role_permission` по матрице §10 (ASSUMPTION(OQ-16)), `chart_of_account`,
`elimination_rule` + `elimination_rule_account` версии 1 для ББ (§4), `required_document_rule` для `BASIC` и `EXTENDED`.
Записи SHALL вставляться или обновляться по натуральному ключу; удаление MUST NOT выполняться.
Исключение — матрица `role_permission` (ей после первичной загрузки владеет администратор, issue #9): в ПУСТУЮ таблицу
матрица файла SHALL загружаться целиком; в заполненную SHALL вставляться только пары, у которых роль или право
вставлены этим же запуском seed (их администратор снять не мог), а остальные пары файла MUST NOT добавляться — право,
снятое администратором, не возвращается, добавленное сверх файла не отзывается. Отчёт команды SHALL сообщать, что
матрица пропущена (или сколько добавлено пар новых ролей и прав).
#### Scenario: Первый запуск на пустой схеме
- **WHEN** после `alembic upgrade head` выполняется `python -m scripts.seed`
- **THEN** в `role` 7 строк, в `permission` 16, в `role_permission` — число строк равно сумме прав по матрице §10,
в `elimination_rule` 8 строк с `statement_type = balance`, `version_no = 1`, в `required_document_rule` для `BASIC`
10 строк (BALANCE, INCOME, OSV × 01, 58, 60, 62, 66, 67, 76, 90) и для `EXTENDED` 27 строк
#### Scenario: Повторный запуск
- **WHEN** `python -m scripts.seed` выполняется второй раз без изменения файлов
- **THEN** число строк во всех затронутых таблицах не меняется, команда завершается с кодом 0, в отчёте
`role_permission` помечена как пропущенная
#### Scenario: Право, снятое администратором
- **WHEN** администратор снял с роли `EXPERT` право `EX_VIEW`, после чего seed запущен снова
- **THEN** связь `EXPERT × EX_VIEW` не восстановлена, остальная матрица не изменилась
#### Scenario: Новые роль и право в файлах seed
- **WHEN** матрица заполнена, а в `permissions.yaml` добавлено новое право, в `roles.yaml` — новая роль, и в
`role_permissions.yaml` — их пары (новое право существующей роли, существующее право новой роли)
- **THEN** seed вставляет ровно эти пары; снятые ранее администратором связи существующих ролей и прав не возвращаются
#### Scenario: Администратор снял все связи
- **WHEN** таблица `role_permission` пуста и seed запущен снова
- **THEN** матрица файла загружается целиком, как при первом запуске
#### Scenario: Изменение названия роли в файле
- **WHEN** в `roles.yaml` изменено `name` роли `EXPERT` и seed запущен снова
- **THEN** строка `role` с `code = EXPERT` обновлена, новая не создана
### Requirement: Счета правил и чек-листа существуют в плане счетов
Все коды счетов, на которые ссылаются `elimination_rules_v1.yaml` и `required_document_rules.yaml`, SHALL резолвиться в
`chart_of_account.code` после seed; `elimination_rule_account.is_excluded = true` SHALL быть у исключений вида
«76 кроме 76.07.5, 76.07.9»; `chart_of_account.kind` SHALL быть задан для всех синтетических счетов, `is_off_balance = true`
для 001–011.
#### Scenario: Правило № 6 (основная пара)
- **WHEN** seed завершён
- **THEN** у правила `rule_no = 6` сторона 1 содержит счета 60.02, 60.22, 60.32, 62.01, 62.03, 62.21, 62.31, 76 и исключения
76.07.5, 76.07.9; сторона 2 — 60.01, 60.03, 60.21, 60.31, 62.02, 62.22, 62.32, 76 и исключение 76.07.1;
`elimination_mode = min`, `measure = closing`, `side_1 = D`
#### Scenario: Ссылка на несуществующий счёт
- **WHEN** в файл правил добавлен счёт, которого нет в `chart_of_accounts.csv`
- **THEN** seed падает до записи в БД с сообщением, какой счёт и в каком правиле не найден
### Requirement: Dev-данные только по явному флагу
`python -m scripts.seed --dev` SHALL дополнительно загрузить из `api/seed/dev/`: примеры региональных филиалов и по одному
`app_user` на каждую системную роль (`<role>@armka.local`, активные, с назначенной ролью через `user_role`). Без флага
`--dev` эти данные MUST NOT загружаться. Флаг `--dev` SHALL приниматься только при `DEBUG=true`: при `DEBUG=false`
команда MUST завершиться с кодом 2 и сообщением «--dev доступен только при DEBUG=true (dev-пользователи не для прода)»
до чтения файлов seed и обращения к БД (OQ-60).
#### Scenario: Dev-пользователи
- **WHEN** выполнен `python -m scripts.seed --dev`
- **THEN** в `app_user` 7 строк с email вида `ka_rf@armka.local`, каждая связана ровно с одной ролью через `user_role`
#### Scenario: Прод-режим
- **WHEN** выполнен `python -m scripts.seed` без `--dev`
- **THEN** таблица `app_user` пуста, `regional_office` содержит только Головной офис
#### Scenario: `--dev` без DEBUG
- **WHEN** при `DEBUG=false` выполнен `python -m scripts.seed --dev`
- **THEN** код возврата 2, в stderr — сообщение об отказе, БД не затронута