118 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` — раздел «Технический долг — кандидат на следующую итерацию»