Срез 0 реализован и влит (PR #3), change перенесён в openspec/changes/archive, спеки — в openspec/specs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
32 lines
2.5 KiB
Markdown
32 lines
2.5 KiB
Markdown
# 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** такого метода нет (ошибка на этапе типизации/теста), запись остаётся прежней
|