# 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.