6.4 KiB
HTTP API и ошибки
Источник контракта
Backend генерирует OpenAPI из собственного публичного API. Frontend использует
предоставленный OpenAPI snapshot как актуальный вход и локально генерирует
типизированный клиент. Направление описано в
OpenAPI contract flow.
API имеет prefix /api/v1; Swagger публикуется для локальной разработки по
environment policy, а не используется frontend в runtime.
Validation и identity
Backend преобразует и проверяет входные данные на общей HTTP-границе. Неизвестные свойства запроса удаляются; сам факт их передачи не обещает отказа. Проверка формата не заменяет бизнес-ограничения и проверку доступа к счёту. Аутентификация подтверждает личность пользователя; accountId из URL сам по себе не доказывает доступ к брокерским данным.
Error contract
Общая граница обработки HTTP-ошибок возвращает application/problem+json
со status и публичным code.
Неожиданный exception возвращает 500 / INTERNAL_SERVER_ERROR, без исходного
message/stack. Типичный ответ:
{ "status": 401, "code": "UNAUTHORIZED" }
Для input validation контракт требует 400, VALIDATION_ERROR и errors как
массив { pointer, detail }, где pointer адресует поле запроса. Это требование
не считается проверенным одним описанием OpenAPI: нужна проверка реального
HTTP-ответа после всех стадий обработки запроса.
Известное расхождение: согласованная
спецификация аутентификации
требует pointer и detail для невалидных полей. В текущей конфигурации
валидация формирует строковые сообщения, а фильтр ожидает структурированные
ошибки полей; поэтому корректность деталей errors не подтверждена.
Исправление требует отдельного изменения реализации и проверки полного
HTTP-потока. OpenAPI сам по себе этого расхождения не устраняет.
Ответ не включает автоматически все поля RFC (type, title, instance).
Добавление обязательного поля является изменением публичного контракта.
Клиент выбирает поведение по публичному коду, а не по внутреннему тексту ошибки.
Domain errors и auth
Специальный code определяется сценарием; общее преобразование ошибок и безопасная форма ответа принадлежат HTTP-границе. Auth endpoints используют свои status и cookie operations: Authentication. T-Bank token failure и временная недоступность имеют разные значения: Connection API. Raw upstream/Prisma errors и secrets не передаются frontend.
Граница доказательства
OpenAPI snapshot задаёт frontend transport types, но сам по себе не доказывает результат каждого запроса. Безопасная обработка неожиданной ошибки проверяется отдельно. Валидация, доступ, статусы и cookie требуют проверки полного HTTP-потока; атомарность хранения — проверки с изолированной реальной базой. Известное ограничение сквозных проверок описано в проверке backend.
Наблюдаемость
Backend пишет структурированные JSON-события в stdout через Pino. Обработка
HTTP-запроса получает серверный request ID, который возвращается заголовком
X-Request-ID; допустимый входящий идентификатор сохраняется отдельно как
client request ID. Это позволяет сопоставить публичную ошибку с обработкой
запроса без передачи внутреннего exception в ответ API.
Журнал завершения запроса содержит шаблон маршрута, метод, статус, длительность и при наличии публичный error code. События внешней границы добавляют операцию, результат и число попыток. Разрешённые поля ограничены; полные запросы и ответы, token, cookie и Authorization не являются данными журнала. Фильтрация полей и redaction не защищают секрет, вручную включённый в свободный текст сообщения или stack.
Выбор logger и граница ответственности описаны в ADR 008; согласованное поведение — в workspace-спецификации Structured logging. Сборщик, срок хранения журналов и alerting не определяются приложением.