Backend security / security (pull_request) Successful in 7s
Backend verify / verify (pull_request) Successful in 2m3s
Conventional commits / commits (pull_request) Successful in 24s
Backend security / security (push) Successful in 7s
Backend verify / verify (push) Successful in 2m10s
68 lines
4.9 KiB
Markdown
68 lines
4.9 KiB
Markdown
# Backend HTTP API
|
||
|
||
## Выбор boundary
|
||
|
||
Сначала определи, меняется wire contract или только реализация существующего
|
||
use case. Для route/request/response/status/error shape читай
|
||
[HTTP semantics и источник контракта](../../../docs/architecture/http-api.md).
|
||
|
||
| Проверка | Где выполнять |
|
||
| --- | --- |
|
||
| Тип/формат/диапазон входа | Runtime DTO class с class-validator/class-transformer |
|
||
| Согласованность полей, бизнес-ограничение | Feature service/domain helper |
|
||
| Session и identity | Existing guard/strategy |
|
||
| Доступ user к конкретному account | Existing access service |
|
||
| HTTP envelope/безопасная ошибка | Общий HttpExceptionFilter |
|
||
|
||
Controller объявляет contract и делегирует; не обращается напрямую к Prisma/gRPC
|
||
и не выполняет финансовые расчёты или сложную оркестрацию.
|
||
Controller вызывает application use case/service. Identity берётся из verified
|
||
`request.user`, не из body/userId, предоставленного клиентом. Access rules активируют Security.
|
||
|
||
## DTO и errors
|
||
|
||
DTO — runtime class: TS interface не предоставляет validation metadata.
|
||
`*.controller.ts` и `*.dto.ts` остаются около HTTP boundary, в root компактного
|
||
module или presentation. DTO можно передать application boundary при совпадении
|
||
формы; отдельный Input с теми же полями не нужен. Domain не импортирует DTO:
|
||
например, чистые денежные расчёты используют `Money`, а Swagger — `MoneyDto`.
|
||
Нормализованная форма input нужна только при смысловом отличии от wire contract;
|
||
выбор suffix принадлежит [Architecture](../architecture.md).
|
||
ValidationPipe уже настроен в `configureApp` (`transform`, `whitelist`).
|
||
Не обещай rejection неизвестных fields: `forbidNonWhitelisted` не включён.
|
||
Для query numbers/arrays выбирай явное преобразование и валидаторы, как в
|
||
[operations DTO](../../src/modules/investments/operations/presentation/brokerage-operation.dto.ts). Swagger metadata
|
||
описывает те же required/optional/nullable/enum/range значения.
|
||
|
||
Используй типизированные response DTO, `ApiOkResponse`/другой фактический status
|
||
и существующий `ApiProblemResponses`. Prisma model не является public contract:
|
||
response выбирает поля явно. Stable codes, RFC 9457 профиль и mapping принадлежат
|
||
[Errors](error-handling.md).
|
||
|
||
**Безопасный путь:** используй exception и общий filter, а не локальный
|
||
`res.status(...).json(...)`. Исключение — транспортная операция вроде cookie;
|
||
следуй существующему auth controller с `passthrough` и явно заданным status.
|
||
|
||
## Пример и проверка
|
||
|
||
Prefix `/api/v1` задаёт `configureApp`. Route/status/request/response/OpenAPI
|
||
change — изменение публичного backend contract; несовместимое изменение требует
|
||
согласованного перехода consumers, а не незаметной правки DTO. Новый API version
|
||
не вводи для внутреннего refactor.
|
||
|
||
Pagination сохраняет contract endpoint: operations использует opaque cursor,
|
||
limit и DTO bounds. Не заменяй cursor offset/page и не добавляй global pagination
|
||
helper ради первого endpoint. Новая pagination явно определяет порядок,
|
||
границу страницы и end-of-list; reused cursor не должен менять filters/owner.
|
||
|
||
[Operations controller](../../src/modules/investments/operations/presentation/brokerage-operations.controller.ts)
|
||
показывает guard, user.sub, DTO query и service delegation.
|
||
Для нового field обновляй canonical source и generated artifacts в определённом
|
||
направлении; body type frontend не исправляется вручную.
|
||
|
||
Проверь happy path и применимые invalid input/access/not-found/domain/upstream
|
||
errors на boundary, где они возникают. Unit вызов controller не запускает pipes,
|
||
guards или serialization. `npm run test:openapi-contract` проверяет schema parity,
|
||
но не поведение invalid request; выбирай соответствующий test по
|
||
[Testing](testing.md). Финальный gate не заменяет semantic review ошибок.
|