Files
specs/openspec/specs/backend-structured-logging/spec.md
T
2026-08-14 17:19:10 +03:00

71 lines
6.9 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.
# backend-structured-logging Specification
## Purpose
Определяет безопасные структурированные backend-логи, позволяющие связать HTTP-запрос, его ответ и вызовы T-Bank при диагностике инцидентов.
## 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 завершает обработку исходного запроса без ошибки, вызванной логированием