54 lines
4.0 KiB
Markdown
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.
|