docs(ai): add scoped backend conventions
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
# Backend router
|
||||
|
||||
Объединяй triggers из смысла задачи, путей и обнаруженных boundaries.
|
||||
Читай выбранные guides до решения; якорь допускает чтение только нужного раздела.
|
||||
Просто backend-файл не требует всех conventions.
|
||||
|
||||
| Решение / сигнал | Читать |
|
||||
| --- | --- |
|
||||
| Новый module/provider/service; бизнес-логика; перенос responsibility | [Architecture](conventions/backend-architecture.md) |
|
||||
| Controller, DTO, route/status, validation/exception, публичная HTTP-семантика | [HTTP API](conventions/backend-http-api.md) |
|
||||
| Prisma/schema/query/persistence, transaction, migration, atomic write | [Data](conventions/backend-data.md) |
|
||||
| Тесты или behavior с testing risk | [Testing](conventions/backend-testing.md) |
|
||||
| JWT, cookie, login/refresh/logout, guard/access, token encryption, sensitive logs | [Security](conventions/security-auth.md) |
|
||||
| T-Bank/gRPC/proto, upstream retry/rate limit/cache, MoexClient | [Integrations](conventions/backend-integrations.md) |
|
||||
| Logging/request context без изменения secrets/auth | [Logging](conventions/backend-architecture.md#logging) |
|
||||
| Новый abstraction/dependency, refactor, неясный scope | [Общий выбор реализации](../../docs/development/engineering-governance.md#выбор-реализации) |
|
||||
| Изменение request/response/route/status/error shape или Swagger metadata | HTTP API + [общий contract workflow](../../docs/development/runtime-openapi-verification.md) |
|
||||
|
||||
Новый endpoint обычно требует HTTP API + Testing; Architecture/Data/Security
|
||||
добавляются по новым ответственности, persistence или access rules.
|
||||
Изменение одного Prisma query без HTTP/auth границы не требует HTTP API/Security.
|
||||
Auth refresh активирует Security + Data + Testing; HTTP API добавляется, если
|
||||
меняется controller/HTTP contract. Exact docs/spec sources выбирай через SOURCES.
|
||||
Повтори routing при расширении diff, включая новые и unstaged файлы.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Источники backend
|
||||
|
||||
| Что нужно установить | Владелец |
|
||||
| --- | --- |
|
||||
| Implementation decision и безопасный pattern | [CONVENTIONS](CONVENTIONS.md) |
|
||||
| HTTP errors, DTO semantics, public wire shape | [docs: HTTP API](../../docs/AI_INDEX.md#http-api); runtime OpenAPI из Nest — единственный editable source |
|
||||
| Auth/session, account access, token encryption | [docs: Security](../../docs/AI_INDEX.md#security) |
|
||||
| Prisma schema/data ownership и migration context | [docs: Data](../../docs/AI_INDEX.md#data) |
|
||||
| T-Bank/gRPC/cache, logging | [docs: Integrations](../../docs/AI_INDEX.md#integrations) |
|
||||
| Money, account/position/income/cache meanings | [docs: Domain](../../docs/AI_INDEX.md#domain) |
|
||||
| Поведение конкретной feature | [docs: Features](../../docs/AI_INDEX.md#features) |
|
||||
| Существующие behavioral requirements при необходимости | [specs index](../../specs/AI_INDEX.md) |
|
||||
| Versions/scripts и scope автоматических checks | package.json/lockfile, ESLint/TypeScript/Jest/Prisma configs |
|
||||
|
||||
SOURCES — карта, не требование прочитать все ссылки. Code показывает реализацию,
|
||||
ADR — rationale, docs — текущие факты; старый пример не отменяет контракт.
|
||||
Исследование предлагает варианты, а actual source разрешает выбор. При missing
|
||||
или conflicting security/data facts сначала установи источник. Для обычной
|
||||
работы OpenSpec/SDD не требуется.
|
||||
@@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Backend data
|
||||
|
||||
## Ownership и выбор операции
|
||||
|
||||
PrismaService — существующий shared DB provider с lifecycle приложения.
|
||||
`prisma/schema.prisma` и migrations владеют persistence; `generated/prisma`
|
||||
создаётся Prisma и не редактируется вручную. Конфигурация URL находится в
|
||||
`prisma.config.ts`/validated environment; SQLite — текущая локальная база.
|
||||
|
||||
| Ситуация | Решение |
|
||||
| --- | --- |
|
||||
| Один query/write конкретного use case | Existing service + PrismaService |
|
||||
| Несколько записей обязаны выполниться вместе | Database transaction вокруг инварианта |
|
||||
| Конкурентная смена одного значения | Atomic conditional update/constraint с проверкой результата |
|
||||
| Независимые reads | Не добавляй transaction ради внешнего вида |
|
||||
| Общая persistence abstraction | Только при реальной общей ответственности; generic repository для одной Prisma реализации не нужен |
|
||||
|
||||
Выбирай только нужные данные, сохраняй user/account ownership в запросах и
|
||||
application checks. Предварительный lookup не заменяет unique constraint при race.
|
||||
Пример: AuthService обрабатывает P2002 и использует conditional `updateMany`
|
||||
для refresh rotation. Сначала пойми invariant; не копируй его flow в другой use case.
|
||||
|
||||
Transaction не охватывает сетевой T-Bank вызов как будто это одна atomic DB
|
||||
операция. Планируй порядок и compensation по текущей задаче; не удерживай DB
|
||||
lock во время retry внешней сети. Access/cache generation semantics — у
|
||||
[T-Bank source](../../../docs/features/tbank-connection.md#граница-финансового-кэша).
|
||||
|
||||
## Деньги и точность
|
||||
|
||||
Для денежных значений используй existing decimal helpers и строковый wire value,
|
||||
не JS floating-point арифметику для сумм. Currency — отдельная часть Money;
|
||||
разные валюты не складываются без явно заданного conversion contract.
|
||||
Источник: [Money](../../../docs/architecture/domain-glossary.md#money),
|
||||
пример: [decimal.ts](../../src/tbank/decimal.ts). UI formatting не меняет
|
||||
backend ownership расчётов и доменную семантику.
|
||||
|
||||
## Schema и migration
|
||||
|
||||
Сначала определи, какие существующие данные/consumers должны сохраниться.
|
||||
Миграцию проверяй на disposable копии с representative existing data; generated
|
||||
client обновляй из schema. Не переписывай уже применённую migration ради нового
|
||||
состояния и не выполняй reset/drop реальной базы как шаг верификации.
|
||||
Для destructive или compatibility-sensitive изменения подготовь backup/restore,
|
||||
переход и проверку отката до его применения. SQLite/local MVP не означает disposable data.
|
||||
|
||||
**Безопасный путь:** additive изменение, заполнение/проверка данных и только затем
|
||||
удаление прежней формы, если задача этого требует. Примеры schema/migrations:
|
||||
[Prisma source](../../prisma/schema.prisma); исторический rationale —
|
||||
[ADR 001](../../../docs/adr/001-prisma-sqlite-local-mvp.md), не текущий список таблиц.
|
||||
|
||||
## Проверка
|
||||
|
||||
`npx prisma validate`; после schema change `npx prisma generate` и
|
||||
`npm run typecheck:app`. Invariants/atomicity/migration safety требуют tests
|
||||
на соответствующей boundary: mock Prisma не доказывает реальную transaction.
|
||||
Выбор integration/e2e и известные ограничения — в [Testing](backend-testing.md).
|
||||
@@ -0,0 +1,52 @@
|
||||
# Backend HTTP API
|
||||
|
||||
## Выбор boundary
|
||||
|
||||
Сначала определи, меняется wire contract или только реализация существующего
|
||||
use case. Для route/request/response/status/error shape читай
|
||||
[HTTP semantics](../../../docs/architecture/http-api.md) и
|
||||
[общий contract workflow](../../../docs/development/runtime-openapi-verification.md).
|
||||
|
||||
| Проверка | Где выполнять |
|
||||
| --- | --- |
|
||||
| Тип/формат/диапазон входа | Runtime DTO class с class-validator/class-transformer |
|
||||
| Согласованность полей, бизнес-ограничение | Feature service/domain helper |
|
||||
| Session и identity | Existing guard/strategy |
|
||||
| Доступ user к конкретному account | Existing access service |
|
||||
| HTTP envelope/безопасная ошибка | Общий HttpExceptionFilter |
|
||||
|
||||
Controller объявляет contract и делегирует; не обращается напрямую к Prisma/gRPC
|
||||
ради обхода service. Request identity берётся из verified `request.user`, не из
|
||||
body/userId, предоставленного клиентом. Access rules активируют Security.
|
||||
|
||||
## DTO и errors
|
||||
|
||||
DTO — runtime class: TS interface не предоставляет validation metadata.
|
||||
ValidationPipe уже настроен в `configureApp` (`transform`, `whitelist`).
|
||||
Не обещай rejection неизвестных fields: `forbidNonWhitelisted` не включён.
|
||||
Для query numbers/arrays выбирай явное преобразование и валидаторы, как в
|
||||
[operations DTO](../../src/tbank/brokerage-operation.dto.ts). Swagger metadata
|
||||
описывает те же required/optional/nullable/enum/range значения.
|
||||
|
||||
Используй типизированные response DTO, `ApiOkResponse`/другой фактический status
|
||||
и существующий `ApiProblemResponses`. При новых ошибках задай публичный stable
|
||||
`code`; сообщение внутреннего exception не является UI contract. Не возвращай
|
||||
raw upstream error, Prisma record с secrets или stack. Текущая форма ошибок
|
||||
описана у HTTP owner; не добавляй поля RFC только потому, что они встречаются в tutorial.
|
||||
|
||||
**Безопасный путь:** используй exception и общий filter, а не локальный
|
||||
`res.status(...).json(...)`. Исключение — транспортная операция вроде cookie;
|
||||
следуй существующему auth controller с `passthrough` и явно заданным status.
|
||||
|
||||
## Пример и проверка
|
||||
|
||||
[Operations controller](../../src/tbank/brokerage-operations.controller.ts)
|
||||
показывает guard, user.sub, DTO query и service delegation.
|
||||
Для нового field обновляй canonical source и generated artifacts в определённом
|
||||
направлении; body type frontend не исправляется вручную.
|
||||
|
||||
Проверь happy path и применимые invalid input/access/not-found/domain/upstream
|
||||
errors на boundary, где они возникают. Unit вызов controller не запускает pipes,
|
||||
guards или serialization. `npm run test:openapi-contract` проверяет schema parity,
|
||||
но не поведение invalid request; выбирай соответствующий test по
|
||||
[Testing](backend-testing.md). Финальный gate не заменяет semantic review ошибок.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Backend integrations
|
||||
|
||||
## Выбор boundary
|
||||
|
||||
T-Bank gRPC принадлежит TbankClient; MOEX metadata — MoexClient. Сервисы use case
|
||||
получают нормализованный результат через эти clients. Frontend не вызывает
|
||||
T-Bank и не получает credentials/proto client. Reference source —
|
||||
[ADR 003](../../../docs/adr/003-tbank-server-side-grpc-boundary.md) и
|
||||
[connection behavior](../../../docs/features/tbank-connection.md).
|
||||
|
||||
Для нового account use case сначала используй TbankAccessService: access,
|
||||
connection generation и invalid-token translation не дублируются в callers.
|
||||
Чистый mapper финансового значения остаётся рядом с domain owner.
|
||||
|
||||
## Retry, cache и protocol
|
||||
|
||||
Existing client уже владеет bounded FIFO queue, rate limit, deadline и retry
|
||||
классификацией. Новый RPC проходит тот же путь; не добавляй вложенный retry loop
|
||||
в service. Не отключай TLS verification ради окружения: используй документированный
|
||||
CA mechanism. Точные параметры и ограничения принадлежат
|
||||
[connection configuration](../../../docs/features/tbank-connection.md#конфигурация-и-ограничения).
|
||||
|
||||
При query/cache change установи key, user/account/generation ownership,
|
||||
freshness и поведение late response. Старый результат не может обслужить новую
|
||||
connection generation. Client Cached Snapshot frontend отличается от backend
|
||||
cache/stale policy; semantics конкретного use case читай через
|
||||
[feature index](../../../docs/AI_INDEX.md#features).
|
||||
|
||||
Внешний auth failure и временная недоступность имеют разные public codes;
|
||||
raw gRPC exception не уходит клиенту. Existing translation — в TbankTokenService
|
||||
и общем HTTP boundary. Для HTTP error change читай HTTP API/Security по trigger.
|
||||
|
||||
Vendor proto хранится в `src/tbank/proto/contracts`; для обновления сверяй
|
||||
официальный source и влияние на loader/DTO, не редактируй read-only references.
|
||||
Generated artifacts, если есть, создавай из source, без ручной подгонки вывода.
|
||||
|
||||
## Безопасный путь и проверка
|
||||
|
||||
Сначала добавь нужный operation в существующий client и используй его из
|
||||
ответственного service. Отдельный abstraction/adapter оправдан новой
|
||||
ответственностью или несовместимым protocol, не только вторым методом.
|
||||
|
||||
[TbankClient tests](../../src/tbank/tbank.client.spec.ts) — пример controlled
|
||||
upstream responses. Проверь queue/deadline/retry limit, token translation,
|
||||
cache isolation и late response для затронутых ветвей. Fixtures синтетические;
|
||||
реальная сеть, секреты и пользовательские accounts не нужны.
|
||||
Logging использует [existing logger](backend-architecture.md#logging).
|
||||
@@ -0,0 +1,46 @@
|
||||
# Backend testing
|
||||
|
||||
## Выбор уровня
|
||||
|
||||
Применяй [общие testing risks](../../../docs/development/engineering-governance.md#risk-based-testing).
|
||||
Тесты должны различать правильное и неправильное наблюдаемое поведение.
|
||||
|
||||
| Что меняется | Проверка |
|
||||
| --- | --- |
|
||||
| Pure mapper/decimal/domain branch | Unit со значимыми edge cases |
|
||||
| Service orchestration/access/retry policy | Jest с mocks внешних boundaries и observable outcome |
|
||||
| Pipe/guard/cookie/status/HTTP error | Configured Nest HTTP boundary; прямого вызова метода controller недостаточно |
|
||||
| OpenAPI metadata/wire schema | `test:openapi-contract` + потребительский contract check |
|
||||
| DB constraint/CAS/transaction/migration | Integration с изолированной реальной DB |
|
||||
| Только DTO declarations/thin wiring | Existing contract/type/build без искусственного unit test |
|
||||
|
||||
Unit specs colocated в `src/**/*.spec.ts`; HTTP/integration — `test/`.
|
||||
Мокируй T-Bank, время и нужную DB boundary, а не проверяемую business-функцию.
|
||||
Не зови реальный внешний account/API. Expected error/code, отсутствие запроса
|
||||
при недопустимом доступе и сохранение данных важнее private method call count.
|
||||
|
||||
## Случаи и примеры
|
||||
|
||||
- [BrokerageAccountsService tests](../../src/tbank/brokerage-accounts.service.spec.ts): отсутствие connection не вызывает upstream, нормализация и точные суммы.
|
||||
- [AuthService tests](../../src/auth/auth.service.spec.ts): invalid/expired/superseded token и concurrent rotation; mock race test не является доказательством DB transaction.
|
||||
- [HTTP filter tests](../../src/common/filters/http-exception.filter.spec.ts): безопасный error envelope.
|
||||
- [OpenAPI integration](../../test/openapi-contract.e2e-spec.ts): configured app + frontend snapshot, без записи snapshot и без T-Bank.
|
||||
|
||||
При bug сначала воспроизведи именно его исход, затем исправь responsible owner.
|
||||
Не создавай tests для каждой декларации, logs строки или поведения Prisma/Nest
|
||||
без собственного инварианта. Coverage не имеет общего threshold.
|
||||
|
||||
## Команды и ограничения
|
||||
|
||||
Итерация: `npm test -- --runInBand <pattern>`, затем нужный typecheck/lint.
|
||||
Полный `npm run verify` включает lint, оба typecheck, Jest и build.
|
||||
`npm run test:openapi-contract` — отдельный required check при wire contract change.
|
||||
|
||||
`npm run test:e2e` существует, но известный Prisma migration blocker описан в
|
||||
[backend workflow](../../../docs/development/backend-workflow.md) и WL-P2-05
|
||||
[registry](../../../docs/development/audit-remediation.md). Скрипт использует
|
||||
фиксированную `/tmp/wealth-ledger-e2e.db`; не запускай его конкурентно как
|
||||
независимые DB tests. Для isolation выбери отдельную test DB и runner configuration.
|
||||
Если задаче нужна HTTP/DB proof, установи применимость blocker и выполни доступную
|
||||
изолированную проверку. Не объявляй покрытым то, что до tests не запустилось;
|
||||
сохрани точный failure и оставшуюся проверку. Unit/Swagger success не заменяет e2e.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Security и auth
|
||||
|
||||
Читай при изменении session/token/cookie/guard, account access, encryption или
|
||||
sensitive logging; обычный data query без этой границы не требует всего документа.
|
||||
|
||||
## Выбор владельца
|
||||
|
||||
Identity/session — AuthService + strategy/guard; cookie transport — AuthController;
|
||||
account access/connection generation — TbankAccessService; token crypto —
|
||||
TbankTokenService/TbankCrypto. Расширяй существующую boundary, не добавляй
|
||||
второй JWT middleware, decrypt helper или refresh coordinator.
|
||||
|
||||
[Authentication](../../../docs/features/authentication.md) и
|
||||
[ADR 006](../../../docs/adr/006-auth-session-policy.md)/[009](../../../docs/adr/009-concurrent-refresh-rotation-policy.md)
|
||||
задают session semantics. Access хранится только в памяти frontend; refresh
|
||||
передаётся httpOnly cookie. Source code конфигурации cookie —
|
||||
[AuthController](../../src/auth/auth.controller.ts); изменение flags/path требует
|
||||
проверки browser/HTTP поведения, не только TypeScript.
|
||||
|
||||
Refresh rotation атомарна: один победитель, проигравший/superseded token получает
|
||||
401, но сам по себе не отзывает session победителя. Не вводи replay history/grace
|
||||
или иной security contract без текущей задачи. Logout идемпотентен; in-memory
|
||||
frontend session/cache очищается и при network failure.
|
||||
|
||||
## Trust boundaries
|
||||
|
||||
Verified JWT не доказывает доступ к accountId из URL. Используй user.sub и
|
||||
existing account access policy; не доверяй userId/token из клиента как authority.
|
||||
Cross-user, invalid/expired/superseded token и concurrent requests — обязательные
|
||||
cases для соответствующего изменения.
|
||||
|
||||
T-Bank credentials остаются server-side и хранятся encrypted. Используй
|
||||
existing AES-256-GCM boundary с validated 32-byte key; не печатай plaintext,
|
||||
шифротекст, cookie, Authorization или connection generation в logs/errors/API.
|
||||
[Connection source](../../../docs/features/tbank-connection.md) определяет
|
||||
cache invalidation при замене/deletion и ограничение key rotation.
|
||||
|
||||
Не передавай Prisma User/Session целиком наружу; выбирай public DTO. Пароль
|
||||
обрабатывает существующий bcrypt flow. Не копируй требования о нормализации
|
||||
или длине из tutorial: сверяй runtime DTO, tests и feature source.
|
||||
|
||||
## Безопасный путь и проверка
|
||||
|
||||
При неясной ownership/crypto/session семантике прочитай exact source до edits.
|
||||
Добавляй проверку на ответственной границе; не скрывай проблему общим catch,
|
||||
фиктивным success или log. Logger allowlist/redaction не делает произвольный
|
||||
message безопасным.
|
||||
|
||||
Targeted auth/access/crypto/logging tests + [Testing](backend-testing.md).
|
||||
Cookie/guard/HTTP changes требуют configured HTTP proof; frontend Bearer/retry
|
||||
проверяется MSW. Schema parity не доказывает отсутствие утечки secret.
|
||||
@@ -1,37 +1,23 @@
|
||||
# Backend
|
||||
|
||||
## Назначение и authority
|
||||
NestJS API; общие правила работы — в root `AGENTS.md`.
|
||||
До backend-решения прочитай [router](.ai/CONVENTIONS.md) и
|
||||
[sources](.ai/SOURCES.md), затем только применимые документы/разделы.
|
||||
|
||||
NestJS API WealthLedger владеет доменной логикой, данными, конфигурацией и
|
||||
server-side интеграциями. Workspace layout и reference policy — в root
|
||||
`AGENTS.md`. Для planning, implementation, validation и завершения читай
|
||||
[canonical lifecycle](../docs/development/openspec-authority-and-lifecycle.md);
|
||||
для recovery и выбора relevant evidence —
|
||||
[context discipline](../docs/development/agent-token-efficiency.md).
|
||||
Они доступны без optional agent skills или commands.
|
||||
## Проверка
|
||||
|
||||
Для устойчивых backend decisions читать [`../docs/adr/README.md`](../docs/adr/README.md).
|
||||
Перед Node-командами: `nvm use --silent` по `.nvmrc`.
|
||||
После lockfile install `npm ci` полный gate — `npm run verify`:
|
||||
zero-warning ESLint, application/test TypeScript, Jest и build.
|
||||
`lint:fix`/`format` пишут файлы и запускаются отдельно от доказательства проверки.
|
||||
`test:cov` — диагностика без общего threshold; scripts принадлежат `package.json`.
|
||||
|
||||
## Canonical gate
|
||||
HTTP contract changes дополнительно проходят общий
|
||||
[contract workflow](../docs/development/runtime-openapi-verification.md).
|
||||
Общий e2e имеет известный environment blocker; применимость и маршрут проверки
|
||||
описаны в [backend testing](.ai/conventions/backend-testing.md).
|
||||
Generated Prisma client не редактируется вручную. Credentials, авторизация
|
||||
доступа к счетам и внешние интеграции остаются server-side.
|
||||
|
||||
Перед Node-командами активировать `.nvmrc` через `nvm use --silent`; это выбирает
|
||||
Node 22. Не запускать отдельную проверку версии, кроме диагностики runtime issue.
|
||||
После lockfile install единственный completion gate:
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm run verify
|
||||
```
|
||||
|
||||
Gate non-mutating и последовательно проверяет ESLint, application/test TypeScript, risk-based Jest suite и build. `npm run lint:fix` и `npm run format` изменяют files и выполняются только явно; `npm run test:cov` — диагностика без общего threshold. `npm run test:e2e` не входит в passing gate до WL-P2-05 trigger из remediation registry. `npm run test:openapi-contract` — отдельный contract gate для изменений обеих сторон API contract.
|
||||
Актуальные scripts проверять в `package.json`/`npm run`.
|
||||
|
||||
## Enforceable boundaries
|
||||
|
||||
- Style задают `eslint.config.mjs` и TypeScript configs; zero-warning lint и оба typecheck обязательны.
|
||||
- Публичный HTTP API версионируется как `/api/v1`; generated backend OpenAPI — contract authority для frontend snapshot.
|
||||
- Frontend не вызывает T-Bank напрямую; credentials, rate limiting и integration resilience остаются server-side.
|
||||
- Не размещать frontend code, generated client или durable documentation в backend.
|
||||
- Security, money, data integrity, concurrency, public contracts, critical journeys и regressions требуют risk-based tests. DTO, declarative config и thin scripts не требуют отдельного unit test без собственной logic.
|
||||
|
||||
Непроверяемые предпочтения являются guidance и не заменяют canonical gate.
|
||||
ESLint/TypeScript не доказывают правильность domain boundaries, security или
|
||||
денежных вычислений: для них нужны semantic review и risk-based tests.
|
||||
|
||||
@@ -10,6 +10,7 @@ NestJS API WealthLedger. Backend владеет auth, SQLite-данными и s
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nvm use --silent
|
||||
npm ci
|
||||
npm run start:dev
|
||||
```
|
||||
@@ -27,7 +28,7 @@ T-Bank token в `.env`: он вводится пользователем и хр
|
||||
npm run verify
|
||||
```
|
||||
|
||||
Он сначала отклоняет runtime вне Node 22, затем запускает hygiene, lint,
|
||||
Он запускает zero-warning lint,
|
||||
application/test typechecks, Jest и build. `npm run lint:fix` — отдельная
|
||||
записывающая команда, `npm run test:cov` — диагностика без общего числового
|
||||
threshold. `npm run test:e2e` пока не является passing gate: Prisma schema
|
||||
@@ -36,19 +37,25 @@ engine останавливает migration до запуска Jest. Точны
|
||||
|
||||
## Документация
|
||||
|
||||
- [Router conventions](.ai/CONVENTIONS.md) и [источники](.ai/SOURCES.md)
|
||||
- [Backend architecture](.ai/conventions/backend-architecture.md)
|
||||
- [HTTP API](.ai/conventions/backend-http-api.md), [data](.ai/conventions/backend-data.md) и [testing](.ai/conventions/backend-testing.md)
|
||||
- [Security/auth](.ai/conventions/security-auth.md) и [integrations](.ai/conventions/backend-integrations.md)
|
||||
|
||||
- [Backend workflow](../docs/development/backend-workflow.md)
|
||||
- [Engineering governance и risk-based testing](../docs/development/engineering-governance.md)
|
||||
- [OpenSpec authority и lifecycle](../docs/development/openspec-authority-and-lifecycle.md)
|
||||
- [Карта проектных фактов](../docs/AI_INDEX.md)
|
||||
- [API contract и runtime OpenAPI](../docs/development/runtime-openapi-verification.md)
|
||||
- [Обзор поставленной системы](../docs/architecture/system-overview.md)
|
||||
- [Архитектурные решения](../docs/adr/README.md)
|
||||
- [Remediation registry](../docs/development/audit-remediation.md)
|
||||
|
||||
Из workspace runtime OpenAPI можно read-only сверить с frontend snapshot:
|
||||
Из backend runtime OpenAPI можно read-only сверить с frontend snapshot:
|
||||
|
||||
```bash
|
||||
npm run test:openapi-contract
|
||||
```
|
||||
|
||||
Полный multi-repository change проверяется из workspace через
|
||||
native OpenSpec validation and the canonical gates of each affected repository.
|
||||
Разработка идёт напрямую по задаче пользователя. Каждый affected repo проходит
|
||||
свой verify; при изменении wire contract дополнительно выполняется contract check.
|
||||
Обязательного OpenSpec/SDD lifecycle нет.
|
||||
|
||||
Reference in New Issue
Block a user