# WealthLedger backend NestJS API WealthLedger. Backend владеет auth, SQLite-данными и server-side интеграцией T-Bank; frontend не обращается к T-Bank напрямую. ## Быстрый старт Требуется Node 24 (`.nvmrc`). Создайте `.env` из примера, замените placeholder секреты и установите зависимости строго из lockfile: ```bash cp .env.example .env nvm use --silent npm ci npx prisma migrate deploy npm run start:dev ``` `JWT_SECRET` должен быть секретом не короче 32 символов, а `TOKEN_ENCRYPTION_KEY` — base64-кодированным 32-байтным ключом. Не добавляйте T-Bank token в `.env`: он вводится пользователем и хранится в зашифрованном виде. ## Проверка Единый completion gate не изменяет versioned-файлы: ```bash npm run verify ``` Он запускает zero-warning lint, application/test typechecks, Jest и build. `npm run lint:fix` — отдельная записывающая команда, `npm run test:cov` — диагностика без общего числового threshold. `npm run test:e2e` отдельно проверяет все HTTP suites на новых базах и runtime OpenAPI с соседним frontend checkout. Для полной backend-проверки выполните обе команды. Результаты — в [remediation registry](../docs/development/audit-remediation.md). Nest 12 поставляется как ESM. Скрипты Jest включают `--experimental-vm-modules`, включая watch/coverage/debug; SQLite runner включает тот же флаг. TypeScript 6 использует явные `rootDir` и типы Node/Jest в `tsconfig.json`. Переход на TypeScript 7 требует поддержки со стороны `ts-jest` и `typescript-eslint`. ### CI и обновления зависимостей `.gitea/workflows/verify.yml` запускает `npm ci`, генерацию Prisma client, `npm run verify` и `npm run test:e2e` на каждом push ветки. Frontend snapshot берётся из `main` соседнего репозитория; лог сохраняет оба SHA. Изменение контракта согласуется с этой frontend revision. Успешный unit gate не заменяет SQLite/e2e; ошибка любой suite завершает job с FAIL. `security.yml` сканирует всю Git-историю Gitleaks 8.30.1 с полностью скрытыми значениями и выполняет `npm audit --include=dev --audit-level=low` при push, PR и ежедневно. `.gitleaksignore` перечисляет только проверенные исторические совпадения: детерминированные fixtures, placeholder и badge из Nest starter. Новые коммиты этими исключениями не покрываются. Renovate группирует minor/patch updates, а major требует согласования в Dependency Dashboard. Автоматический merge не включён. Прямые зависимости фиксируются точными версиями: `.npmrc` задаёт `save-exact=true` для npm install, Renovate использует `rangeStrategy: pin`. Обновляйте `package.json` вместе с `package-lock.json`. Overrides в `package.json` закрывают advisories транзитивных `multer`, `deepmerge-ts` и `mysql2`; удаляйте их, когда родительские пакеты примут исправленные версии. Совместимость Prisma override проверяется генерацией и SQLite migrations. Required checks настраиваются отдельно в Gitea: наличие workflow само по себе не блокирует merge. Общий `tsconfig.json` включает `strict: true` и `noFallthroughCasesInSwitch` для приложения, тестов и сборок. ESLint запрещает non-null assertions (`value!`) и definite-assignment assertions (`field!: Type`). Поля DTO, заполняемые вне конструктора, описываются через `declare`: входные значения заполняет и проверяет Nest, ответные DTO описывают форму возвращаемых объектов. `declare` не создаёт значение и не заменяет runtime-валидацию. В обычном коде нужны инициализация или сужение типа после проверки значения. ## Документация - [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) - [Границы проверки API и данных](../docs/development/verification.md#api-и-хранение-данных) - [Engineering governance и risk-based testing](../docs/development/engineering-governance.md) - [Карта проектных фактов](../docs/README.md) - [API contract и runtime OpenAPI](../docs/development/runtime-openapi-verification.md) - [Обзор поставленной системы](../docs/overview.md) - [Архитектурные решения](../docs/adr/README.md) - [Remediation registry](../docs/development/audit-remediation.md) Из backend runtime OpenAPI можно read-only сверить с frontend snapshot: ```bash npm run test:openapi-contract ``` Разработка идёт напрямую по задаче пользователя. Каждый affected repo проходит свой verify; при изменении wire contract дополнительно выполняется contract check. Обязательного OpenSpec/SDD lifecycle нет. ## Реальная SQLite и сохранность данных После `nvm use --silent` запускайте `npm run test:sqlite` при изменении auth, карточных операций или DB boundary, `npm run test:e2e` — для всех HTTP suites. Обе команды используют один runner: отдельный каталог `wealthledger-e2e-*` в системном temp на каждую suite, один `DATABASE_URL` для migrations и Jest. Внешний `DATABASE_URL` заменяется временным; `.env` и пользовательские данные не изменяются. Прямой Jest без runner отклоняется до обращения к базе. При ошибке migration/Jest или SIGINT/SIGTERM runner останавливает дочерние процессы, удаляет свой каталог и возвращает ненулевой exit code. Нужен доступ к локальным HTTP-портам; sandbox может его запрещать. `prisma.config.ts` удаляет унаследованный `RUST_LOG` только в процессе Prisma CLI: на Prisma 7.9.1 уровни `warn`/`error` вызывают пустой `Schema engine error` при fresh migration, без переменной миграция проходит. Постоянный `RUST_LOG=info` и обновление зависимостей не нужны. Logging приложения настраивается отдельно. История migrations применяется штатным `migrate deploy`. Регрессия самого запуска: `node test/sqlite-regression.cjs`. Она выполняет три последовательных и два параллельных полных e2e, проверяет уникальность DB, сохранность вымышленного внешнего файла, отказ migration и SIGINT/SIGTERM cleanup. Логи остаются в каталоге из вывода. Для одной suite: `node test/sqlite.cjs app.e2e-spec.ts`. | Риск | Проверка реальной DB | | --- | --- | | Чужой пользователь | `bank-cards.e2e-spec.ts`: owner каждой карты, категории, покупки и стороны перевода | | Повтор и конкурентный update | Те же tests: fingerprint, tombstone, версии, один refund в пределах покупки, archive/write | | Конкурентный refresh | `app.e2e-spec.ts`: оба запроса читают прежний hash до CAS; один 200, один 401, cookie победителя работает после replay | | Rollback и деньги | Карточные tests: откат source lock, атомарный перевод, точные суммы выше 2^53 и границы signed64 | | Migration, restart, backup/restore | `test:durability`: прежнее приложение, новая schema, история, откат приложения и восстановление backup | Prisma в этих suites не заменяется mocks. В refresh тесте барьер задерживает настоящую подпись JWT, чтобы оба запроса дошли до реальной конкурентной записи. Unit tests с mocks отдельно проверяют orchestration и не доказывают DB concurrency. При изменении schema/migrations или сохранения данных дополнительно выполните `npm run test:durability -- /absolute/path/to/baseline`. Он не входит в lint/verify. Baseline — отдельная сборка до проверяемых миграций с неизменённым префиксом migration history. Для текущей карточной схемы подходит revision `8ec172f48eefa2237dc0c16919fbb2e726b39a65` (до добавления карт): ```bash # Из backend; экспорт не содержит .env или локальную базу. baseline_dir=$(mktemp -d /tmp/wealthledger-baseline-XXXXXX) git archive 8ec172f48eefa2237dc0c16919fbb2e726b39a65 | tar -x -C "$baseline_dir" ( cd "$baseline_dir" nvm use --silent npm ci npm run build ) nvm use --silent npm run build npm run test:durability -- "$baseline_dir" ``` Не подменяйте baseline текущей сборкой: runner отвергает тот же путь, отсутствующую сборку и неподходящую migration history. Для следующей schema выберите совместимую предыдущую revision и проверьте её API-сценарии runner. Durability оставляет временные DB, логи и `result.json` по пути из вывода для диагностики; он не откатывает schema пользовательской базы.