# Backend Architecture Refactor Дата: 2026-06-25 Статус: draft ## Контекст После аудита backend-архитектуры от 2026-06-25 и последующей фичи `backend-architecture-improvements` большая часть первого слоя долга закрыта: общий envelope DTO, domain exceptions, dependency-aware health checks, DI-подключение middleware и разделение `MoexClientService`. Оставшийся долг неоднороден. Часть пунктов требует новых продуктовых или доменных решений (`T-Bank` multi-tenancy, локальный read-path истории операций, device sessions, ledger-модель). Эти изменения не должны попадать в локальный рефакторинг без отдельной спецификации, потому что меняют поведение, модель данных или threat model. Текущая фича фиксирует только refactor-only итерацию: привести существующий backend к более правильным архитектурным границам без добавления новых пользовательских возможностей и без изменения публичной формы API, кроме уточнения валидации некорректных входных данных. ## Цель Снизить backend technical debt в существующем поведении за счёт точечных архитектурных правок: безопаснее обрабатывать ошибки, формализовать production-конфигурацию, усилить DTO-валидацию, сузить `any` на границе T-Bank gRPC, улучшить cache metadata и синхронизировать опубликованную backend-документацию с текущим кодом. ## Требования ### 1. Error masking для необработанных исключений Backend не должен возвращать клиенту внутренние сообщения необработанных `Error` в ответах `500`. Подробности должны оставаться в backend-логах. Публичный ответ для unknown/internal errors должен быть стабильным и безопасным. ### 2. Production configuration hardening Backend должен явно отделять dev defaults от production-конфигурации: - production-запуск не должен молча использовать дефолтные JWT access/refresh secrets; - CORS с credentials не должен отражать произвольный origin в production; - список допустимых origins должен задаваться конфигурацией окружения. ### 3. DTO validation hardening Существующие DTO должны отсеивать заведомо некорректные значения до попадания в service-layer: - даты покупки позиции должны валидироваться как ISO/date строки; - количество позиции не должно допускать `0` там, где service-layer уже трактует это как ошибку; - изменения должны сохранять существующий успешный пользовательский сценарий для валидных данных. ### 4. T-Bank gRPC typed boundary Динамическая природа protobuf/gRPC клиента должна быть локализована в одном typed boundary, чтобы доменные broker-сервисы не приводили service clients к `any` напрямую. Цель — улучшить compile-time границы без переписывания vendored proto contract и без изменения внешнего T-Bank API behavior. ### 5. Cache metadata consistency Cache helper должен сохранять полезность `meta.cachedAt`: cache hit не должен выглядеть как состояние без времени кеширования, если timestamp уже можно сохранить вместе с cached payload. ### 6. Backend documentation sync Опубликованные docs в `apps/docs/docs/backend/` должны отражать текущее состояние backend после закрытых refactor-работ: - split MOEX clients вместо устаревшего `MoexClientService` как единого God Service; - актуальный envelope contract; - актуальные health response и broker operations sync endpoint. ## Ограничения - Не добавлять новые user-facing возможности. - Не менять публичный API shape для успешных ответов. - Не вводить multi-tenancy или пользовательские T-Bank connections в рамках этой фичи. - Не переводить операции T-Bank на локальный read-path в рамках этой фичи. - Не менять модель сессий на device/session table в рамках этой фичи. - Не менять финансовую модель хранения (`Float`, `Int`, JSON/string fields) и не создавать ledger ADR в рамках этой фичи. - Не выполнять механическое дробление больших сервисов без проверяемой архитектурной цели. - Не редактировать Prisma migrations вручную. ## Acceptance Criteria - Необработанные backend exceptions логируются, но `500` response не раскрывает внутренний `Error.message`. - Production-конфигурация не стартует с дефолтными JWT secrets и не использует wildcard/reflected CORS для credentialed requests. - DTO портфельных позиций валидируют даты и количество на boundary-уровне; добавлены regression tests. - Production-код broker-сервисов не содержит прямых `as any` для получения T-Bank gRPC service clients; небезопасное приведение, если оно необходимо, локализовано и покрыто типом/facade. - Cache metadata на hit/miss согласована тестами и не ломает `ApiEnvelopePayload`/`ApiResponse` contract. - Backend docs обновлены и не ссылаются на удалённый `MoexClientService` как primary abstraction, устаревший `/operations/refresh` endpoint или raw health response без envelope. - Затронутые backend tests проходят. - Backend build проходит. - OpenAPI/types обновляются только если реально меняется Swagger contract; `apps/frontend/src/api/types.ts` не редактируется вручную. ## Out Of Scope - T-Bank data isolation and multi-tenancy. - Local T-Bank operations read-path. - Device-level sessions, refresh-token rotation и reuse detection. - Ledger/financial data model migration. - Rate limiting, CSRF и security headers, если они требуют отдельной threat model или middleware policy. - Декомпозиция `PortfolioService` или `tbank/` на новые модули без отдельного плана. ## Источники - `docs/research/2026-06-25-backend-audit.md` - `docs/features/backend-architecture-improvements/spec.md` - `docs/features/moex-client-split/spec.md` - `docs/features/api-envelope-contract/spec.md` - `docs/inbox.md` — раздел «Технический долг — кандидат на следующую итерацию»