69 lines
6.9 KiB
Markdown
69 lines
6.9 KiB
Markdown
## Purpose
|
||
|
||
Определяет безопасные структурированные backend-логи, позволяющие связать HTTP-запрос, его ответ и вызовы T-Bank при диагностике инцидентов.
|
||
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Backend публикует единообразные структурированные события
|
||
Backend SHALL записывать lifecycle-, HTTP-, authentication-, domain- и T-Bank-события в stdout как Pino JSON-записи с time, level, message и безопасным context. Записи MUST поддерживать уровни debug, info, warn и error; уровень вывода MUST настраиваться валидируемой конфигурацией `LOG_LEVEL` с production-значением по умолчанию `info`.
|
||
|
||
#### Scenario: Приложение успешно запускается
|
||
- **WHEN** backend завершает запуск
|
||
- **THEN** stdout содержит info JSON-событие запуска с безопасными service и environment
|
||
|
||
#### Scenario: Выбран уровень debug
|
||
- **WHEN** backend запущен с допустимым `LOG_LEVEL=debug`
|
||
- **THEN** stdout содержит debug-события наряду с событиями более высоких уровней
|
||
|
||
#### Scenario: Указан недопустимый уровень логирования
|
||
- **WHEN** backend запущен с недопустимым значением `LOG_LEVEL`
|
||
- **THEN** запуск завершается ошибкой валидации конфигурации
|
||
|
||
### Requirement: HTTP-запросы имеют сквозной идентификатор
|
||
Backend SHALL создавать server-generated request ID для каждого HTTP-запроса, включать его в связанные с запросом log-события и возвращать его в response header `X-Request-ID`. CORS MUST разрешать browser-клиенту прочитать этот header. Входящий request ID MAY быть записан отдельным недоверенным полем, но MUST NOT заменять server-generated request ID и MUST NOT влиять на авторизацию или обработку запроса.
|
||
|
||
#### Scenario: Клиент получает идентификатор запроса
|
||
- **WHEN** browser-клиент получает HTTP-ответ backend
|
||
- **THEN** ответ содержит `X-Request-ID`, доступный через CORS, и этот же ID присутствует в HTTP log-событии
|
||
|
||
#### Scenario: Клиент передаёт собственный идентификатор
|
||
- **WHEN** HTTP-запрос содержит client-provided request ID
|
||
- **THEN** backend использует другой server-generated request ID для обработки и логирования запроса
|
||
|
||
### Requirement: Backend фиксирует итог каждого HTTP-запроса
|
||
Backend SHALL записывать ровно одно completion-событие для каждого HTTP-запроса с request ID, HTTP method, route template, status и duration. Completion-событие MUST иметь level info для обычных ответов, warn для authentication failures и status 429, error для status 5xx. События с ошибкой MUST включать стабильный public error code; error-события для status 5xx MUST включать stack trace.
|
||
|
||
#### Scenario: Запрос завершается успешно
|
||
- **WHEN** backend возвращает ответ со status 2xx
|
||
- **THEN** stdout содержит одно info completion-событие с route template без query string и длительностью обработки
|
||
|
||
#### Scenario: T-Bank недоступен во время запроса
|
||
- **WHEN** backend возвращает клиенту status 503 с public error code `TBANK_UNAVAILABLE`
|
||
- **THEN** stdout содержит одно error completion-событие с этим code, request ID и stack trace
|
||
|
||
#### Scenario: Запрос не проходит аутентификацию
|
||
- **WHEN** backend возвращает status 401 или 403
|
||
- **THEN** stdout содержит одно warn completion-событие без отдельного дублирующего события ошибки
|
||
|
||
### Requirement: События T-Bank позволяют диагностировать интеграцию
|
||
Backend SHALL записывать события вызовов T-Bank с request ID, именем операции и duration, когда вызов выполняется в контексте HTTP-запроса. Успешный вызов MUST иметь level debug, повтор вызова MUST иметь level warn, а окончательный сбой MUST иметь level error и содержать gRPC code и число попыток.
|
||
|
||
#### Scenario: Вызов T-Bank успешен с первой попытки
|
||
- **WHEN** вызов T-Bank завершается успешно без повтора
|
||
- **THEN** stdout содержит debug-событие операции с её duration и request ID
|
||
|
||
#### Scenario: Вызов T-Bank повторяется и затем завершается ошибкой
|
||
- **WHEN** вызов T-Bank исчерпывает разрешённые попытки
|
||
- **THEN** stdout содержит warn-событие повтора и error-событие окончательного сбоя с gRPC code и числом попыток
|
||
|
||
### Requirement: Логи не раскрывают секретные и чувствительные данные
|
||
Backend MUST NOT записывать в логи token, cookie, JWT, пароль, полный HTTP header, HTTP body, email, IP-адрес, финансовые значения или payload T-Bank. В production-логах MAY присутствовать только внутренние user ID и brokerage account ID, если они известны при формировании события. Ошибка формирования или вывода log-события MUST NOT менять HTTP-ответ или результат доменной операции.
|
||
|
||
#### Scenario: Запрос содержит секретные данные
|
||
- **WHEN** HTTP-запрос содержит authentication cookie, JWT или тело с паролем
|
||
- **THEN** связанные log-события не содержат эти значения
|
||
|
||
#### Scenario: Событие не сериализуется
|
||
- **WHEN** backend не может сериализовать поле log-события
|
||
- **THEN** backend завершает обработку исходного запроса без ошибки, вызванной логированием
|