58 lines
4.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.

# audit-trail Specification
## Purpose
Все действия из enum `audit_action` пишутся в `audit_event` одним способом — через сервис аудита; журнал только
дополняется, записи неизменяемы (ТЗ 8.2).
## Requirements
### Requirement: Единая точка записи
Сервис аудита SHALL предоставлять метод записи события с полями `action` (из enum `audit_action`), `section`
(из `audit_section`), `object_type`, `object_id`, `user_id` (NULL для системных действий), `consolidation_version_id`,
`description`, `before_value`, `after_value` (jsonb), `comment`, `result`, `changed_field`, `ip_address`, `user_agent`;
`occurred_at` SHALL проставляться сервером (UTC). Запись SHALL выполняться в той же транзакции, что и изменение данных.
NOTE: В Срезе 0 обмен через recognition_job аудит не пишет (рулинг R-7, design #20); сервис готов к использованию Срезом 2+.
#### Scenario: Системное событие
- **WHEN** системный процесс (без пользователя) вызывает сервис аудита
- **THEN** в `audit_event` появляется строка с `user_id = NULL`, `before_value`/`after_value` содержат старый и новый статус
#### Scenario: Откат транзакции
- **WHEN** изменение данных и запись аудита выполняются в одной транзакции, и она откатывается
- **THEN** строка `audit_event` не сохраняется
### Requirement: Журнал только дополняется
ORM-модель `audit_event` MUST NOT использоваться для `UPDATE` или `DELETE` в коде ядра; тест SHALL проверять, что в
`src/` нет обращений, изменяющих или удаляющих `audit_event`, а сервис аудита не имеет методов изменения.
#### Scenario: Попытка изменить запись
- **WHEN** код вызывает обновление строки `audit_event` через сервис аудита
- **THEN** такого метода нет (ошибка на этапе типизации/теста), запись остаётся прежней
### Requirement: События справочников, импорта и администрирования
Каждая мутация справочников, импорт и каждое действие администратора SHALL писать `audit_event` через сервис аудита в
той же транзакции с `user_id` инициатора, `ip_address` и `user_agent` запроса:
| Действие | `action` | `section` | `object_type` |
|---|---|---|---|
| создание/изменение/архив ГК | `GROUP_CHANGE` | `DIRECTORIES` | `company_group` |
| смена филиала ГК | `ASSIGNMENT_CHANGE` | `DIRECTORIES` | `company_group` |
| создание/изменение/перевод/закрытие ЮЛ, алиасы | `LEGAL_ENTITY_CHANGE` | `DIRECTORIES` | `legal_entity` / `legal_entity_alias` |
| ГСК/ГСЗ и их состав | `MEMBERSHIP_CHANGE` | `DIRECTORIES` | `related_group` / `related_group_member` |
| импорт выгрузки | `DIRECTORY_IMPORT` | `DIRECTORIES` | `directory_import` |
| пользователь создан/изменён/деактивирован | `USER_CHANGE` | `USERS` | `app_user` |
| роли пользователя | `USER_ROLE_CHANGE` | `USERS` | `app_user` |
| права роли | `ROLE_PERMISSION_CHANGE` | `ACCESS` | `role` |
`before_value`/`after_value` SHALL содержать изменённые поля (для списков — весь набор до и после); `changed_field` —
имя поля при изменении одного поля.
#### Scenario: Изменение имени ГК
- **WHEN** имя ГК меняется с «А» на «Б»
- **THEN** в `audit_event` строка `GROUP_CHANGE` с `changed_field = "name"`, `before_value = {"name": "А"}`, `after_value = {"name": "Б"}`, `user_id` инициатора
#### Scenario: Откат мутации справочника
- **WHEN** транзакция перевода ЮЛ откатывается
- **THEN** строки `LEGAL_ENTITY_CHANGE` и `MEMBERSHIP_CHANGE` в `audit_event` отсутствуют