docs: refine backend conventions and routing
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Successful in 2m12s
Conventional commits / commits (pull_request) Successful in 25s
Backend security / security (pull_request) Successful in 7s
Backend verify / verify (pull_request) Successful in 2m3s
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Successful in 2m12s
Conventional commits / commits (pull_request) Successful in 25s
Backend security / security (pull_request) Successful in 7s
Backend verify / verify (pull_request) Successful in 2m3s
This commit is contained in:
@@ -2,11 +2,8 @@
|
||||
|
||||
## Module-first organization
|
||||
|
||||
Backend — domain-oriented modular monolith с лёгким разделением
|
||||
по ответственности. `src/modules` группирует код по бизнес-возможности: `auth`, `banking/bank-cards`, области `investments`.
|
||||
В инвестициях отдельные Nest modules владеют `brokerage-accounts`, `portfolio`,
|
||||
`operations`, `income`, `upcoming-events`, `instruments`, `tbank-connection`.
|
||||
`instruments/stocks` и `instruments/bonds` — slices внутри одного модуля.
|
||||
Устройство и data flow — в [mental model](../architecture.md).
|
||||
Сначала выбери business owner в `modules/`, затем ответственность внутри него.
|
||||
|
||||
### Progressive structure
|
||||
|
||||
@@ -36,15 +33,6 @@ feature/
|
||||
Для одного controller или пары DTO дополнительная поддиректория не нужна.
|
||||
Пустые папки, новые barrels, CQRS и interfaces не требуются для этой организации.
|
||||
|
||||
В текущем коде слои используют `auth`, `bank-cards`, `portfolio`, `operations`
|
||||
и slices `instruments/stocks`, `instruments/bonds`. Общие application helpers
|
||||
инструментов находятся в `instruments/application`; `instruments.module.ts`
|
||||
компонует оба slice. `stock-position.ts` и `instrument-position.ts` формируют
|
||||
результат из portfolio DTO; `instrument-market.ts` обрабатывает внешние данные
|
||||
и ошибки Nest. Это application code, а не независимая domain model.
|
||||
`brokerage-accounts`, `income`, `upcoming-events`, `tbank-connection` остаются
|
||||
компактными плоскими modules. Наличие tests само по себе не требует слоёв.
|
||||
|
||||
## Поиск и создание файла
|
||||
|
||||
При работе над feature проходи владельцев в порядке:
|
||||
@@ -134,6 +122,10 @@ Tests могут импортировать внутренний owner для п
|
||||
Новый export требует текущего потребителя; controller и persistence остаются
|
||||
приватными. Не добавляй `index.ts` на каждом уровне.
|
||||
|
||||
Circular dependencies устраняй изменением ownership/composition. `forwardRef()`
|
||||
не является стандартным исправлением boundaries; исключение требует конкретной
|
||||
неизбежной связи и проверки DI initialization.
|
||||
|
||||
Каждый provider регистрируется у одного владельца. Потребители импортируют
|
||||
его module, а не повторяют provider: это сохраняет единственный кэш и лимитер.
|
||||
`AuthModule` экспортирует guard; наличие JWT не заменяет account access check.
|
||||
@@ -169,30 +161,18 @@ DTO остаются транспортными runtime classes; существ
|
||||
|
||||
Сохраняй существующий error contract: HTTP exceptions остаются на application/
|
||||
transport boundary. Чистому расчёту не нужен новый framework ошибок.
|
||||
Mapping и stable codes — по [Errors](backend-error-handling.md).
|
||||
Точные ограничения — [HTTP](backend-http-api.md), [Data](backend-data.md),
|
||||
[Security](security-auth.md), [Integrations](backend-integrations.md).
|
||||
|
||||
## Сценарии и размер сервисов
|
||||
|
||||
Разделяй независимые операции, а не строки. `BankCardsService` отвечает за карты,
|
||||
`BankOperationsService` — журнал/переводы/возвраты, `ExpenseCategoriesService` —
|
||||
категории, `GetBankSummaryUseCase` — сводку. `BankCardsRepository` сохраняет
|
||||
общий transaction retry и owner lookup; денежные транзакции не разрываются.
|
||||
Чистые расчёты банковских карт находятся в `domain` этого модуля.
|
||||
Разделяй независимые операции, а не строки. Пример: `BankCardsService` владеет
|
||||
картами, `BankOperationsService` — журналом/переводами, `GetBankSummaryUseCase` —
|
||||
сводкой через repository и чистый расчёт. Не разрывай денежную transaction,
|
||||
общий cache/limiter или pending promises при extraction.
|
||||
|
||||
У инструментов `StockCatalogService` / `BondCatalogService` хранят идентичность
|
||||
листинга и общий кэш slice; market service — котировки/свечи, income service — выплаты/личные позиции.
|
||||
`GetStockCompanyUseCase` владеет сведениями об эмитенте. Ключи, TTL и pending
|
||||
promises разделяют прежний экземпляр кэша; extract не должен менять generation.
|
||||
Portfolio и operations сохраняют связную координацию снимков/страниц и кэшей.
|
||||
Расчёты портфеля находятся в `portfolio/domain`; преобразование брокерских
|
||||
позиций — в `tbank-portfolio.mapper.ts`. `bond-money.mapper.ts` преобразует
|
||||
ответ клиента и не является value object.
|
||||
|
||||
Выбирай обычную функцию для чистого вычисления; repository contract — только
|
||||
для реальной границы. CQRS/buses/events, BaseRepository/BaseService, DI token
|
||||
для каждого класса, mapper/presenter для каждого DTO и новые dependencies
|
||||
не нужны для структурного переноса.
|
||||
Расширение abstractions — по [change scope](../../../.ai/conventions/code-health.md#change-scope).
|
||||
|
||||
## Common
|
||||
|
||||
@@ -205,39 +185,12 @@ protobuf units/nano conversion — T-Bank integration. Domain используе
|
||||
|
||||
## Domain literals and magic values
|
||||
|
||||
Finite business vocabulary must be modeled explicitly; incidental implementation
|
||||
literals stay inline. Это относится к error codes, statuses, operation/account/
|
||||
instrument/transaction types, permissions, roles, feature states и бизнес-режимам.
|
||||
|
||||
Перед новым определением найди existing owner/type/value. В branching и comparisons
|
||||
используй символическое значение владельца; не повторяй raw domain literals.
|
||||
Храни словарь у domain/module/entity с соблюдением границ слоёв, без глобальной
|
||||
свалки `constants.ts`. Сохраняй принятый pattern; для нового project-owned словаря
|
||||
без подходящего аналога используй `as const` с derived union:
|
||||
|
||||
```ts
|
||||
const BankErrorCode = {
|
||||
InvalidDate: "BANK_INVALID_DATE",
|
||||
ImmutableOperation: "BANK_IMMUTABLE_OPERATION",
|
||||
} as const;
|
||||
type BankErrorCode = (typeof BankErrorCode)[keyof typeof BankErrorCode];
|
||||
|
||||
// Вместо code === "BANK_INVALID_DATE":
|
||||
if (code === BankErrorCode.InvalidDate) { /* existing handling */ }
|
||||
```
|
||||
|
||||
Значимые numeric policies (timeout, retry, page size, threshold, coefficient)
|
||||
называй по смыслу и единицам: `REQUEST_TIMEOUT_MS`, `CACHE_TTL_SECONDS`,
|
||||
`MAX_RETRY_COUNT`, `PAGE_SIZE`. Оставляй inline UI labels в принятом месте,
|
||||
log messages, индексы, `index + 1`, `Math.max(value, 0)`, `page ?? 1`,
|
||||
`percentage * 100` и очевидные локальные детали без semantic benefit.
|
||||
При неясном owner/смысле оставь значение и укажи ограничение в review.
|
||||
|
||||
Не мигрируй корректные existing enum/union styles массово. Не добавляй ради
|
||||
правила factories, registries, schemas, loaders, abstraction layers, dependencies,
|
||||
custom lint/AST rules, generation/validation scripts или тесты существования
|
||||
констант. Semantic review проверяет ownership, единое написание и неизменность
|
||||
wire values; обычные behavior tests проверяют поведение.
|
||||
Общий выбор symbolic values и числовых policies —
|
||||
[Domain values](../../../.ai/conventions/code-health.md#domain-values).
|
||||
Сохраняй strict TS и explicit boundary types. Для недоверенного input выбирай
|
||||
`unknown` + runtime narrowing; отключённый lint `no-explicit-any` не делает
|
||||
`any` нормой domain/application model. `declare` допустим для заполняемых извне
|
||||
DTO fields, не для сокрытия неинициализированного owned state.
|
||||
|
||||
OpenAPI enum metadata и runtime validation должны читать тот же vocabulary,
|
||||
что application/domain. Например, `BankOperationKind` принадлежит bank-cards/domain,
|
||||
@@ -255,14 +208,8 @@ semantic magic strings проверяются conventions/review без ново
|
||||
|
||||
## 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.
|
||||
События, levels, correlation и safe fields — по
|
||||
[Observability](backend-observability.md).
|
||||
|
||||
## Проверка
|
||||
|
||||
|
||||
Reference in New Issue
Block a user