Files
backend/.ai/conventions/backend-architecture.md
T

54 lines
4.0 KiB
Markdown

# Backend architecture
## Выбор владельца
Найди существующий use case, его collaborators и tests до создания module/service.
Сохрани ответственность в текущем module, если новая возможность относится к нему.
Module — граница связного набора providers, а не папка для каждого endpoint.
| Решение | Owner |
| --- | --- |
| Route, request/response mapping, status/cookie | Controller, [HTTP rules](backend-http-api.md) |
| Business use case, orchestration, domain validation | Feature service |
| Input shape/format | DTO + configured ValidationPipe |
| Атомарность/DB query | Сервис use case через PrismaService, [Data](backend-data.md) |
| Внешний protocol, deadline/retry/limiting | Existing client, [Integrations](backend-integrations.md) |
| Чистое вычисление/mapper без lifecycle и DI | Обычная функция рядом с domain owner |
| Bootstrap/config/global cross-cutting concern | AppModule, config, существующий common owner |
**Безопасный путь:** расширь текущий owner; выделяй collaborator, когда он скрывает
самостоятельный инвариант или координацию. Не вводи CQRS, generic repository,
interface с одной реализацией или base controller только ради шаблона Nest.
Не превращай common в хранилище бизнес-логики и не переноси frontend модели сюда.
## Существующие seams
`TbankConnectionModule` уже объединяет счета, портфель, операции, доходы и события.
Новый связанный use case обычно добавляется в него; создание отдельного module
требует собственной ответственности, не только нового файла.
- [BrokerageOperationsController](../../src/tbank/brokerage-operations.controller.ts) передаёт user/account/query в service, без финансовых вычислений в controller.
- [TbankAccessService](../../src/tbank/tbank-access.service.ts) владеет connection/account access и generation; новые account use cases используют его вместо копирования guard/decrypt logic.
- [decimal.ts](../../src/tbank/decimal.ts) — пример pure domain helper; Injectable и adapter для арифметики не нужны.
Наличие guard подтверждает session, но не владение account. При пересечении
access boundary добавь [Security](security-auth.md). Ошибка upstream не должна
обходить общий HTTP filter или превращать чужой account в доступный.
## Logging
Единственный logger — nestjs-pino; application events используют существующий
[StructuredLogger](../../src/common/logging/structured-logger.service.ts) и
request context. Выбирай стабильное имя события и разрешённые scalar fields.
Wrapper отбрасывает неизвестные поля, но это не разрешение помещать secret
в `message`/`stack`: review sensitive logging обязателен.
Не добавляй второй logger или сырой request/body/error payload.
Источник rationale — [ADR 008](../../../docs/adr/008-pino-backend-logging.md);
при secrets/user data читай также Security.
## Проверка
`npm run typecheck:app`, `npm run lint`, targeted Jest по изменённому use case.
Смысл boundaries проверяется review: backend не имеет отдельного автоматического
FSD/DI architecture checker. Existing tests и build не доказывают правильный owner.