8 Commits
Author SHA1 Message Date
ksv741 660b250ecd chore(release): 0.1.0
Conventional commits / commits (pull_request) Successful in 31s
Backend security / security (pull_request) Successful in 9s
Backend verify / verify (pull_request) Successful in 2m25s
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Successful in 2m40s
2026-09-14 07:08:06 +03:00
ksv741 f01b82d366 chore: configure releases and develop workflow 2026-09-14 07:07:24 +03:00
ksv741 d4fc28cbbf docs: update system documentation references
Backend security / security (push) Successful in 7s
Backend verify / verify (push) Successful in 2m5s
2026-09-14 05:51:54 +03:00
renovate-bot 97e864bc06 chore(deps): pin node.js to v24.21.0
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Successful in 2m27s
2026-09-13 20:45:06 +03:00
ksv741 121af701b7 chore(deps): upgrade backend to Nest 12 and TypeScript 6
Backend security / security (pull_request) Successful in 8s
Backend security / security (push) Successful in 7s
Backend verify / verify (push) Successful in 2m28s
2026-09-13 20:43:50 +03:00
ksv741 2bc8745495 chore(deps): update and pin backend dependencies
Backend security / security (pull_request) Successful in 13s
Backend security / security (push) Successful in 10s
Backend verify / verify (push) Successful in 2m53s
2026-09-13 20:29:13 +03:00
ksv741 4c8ba2fac9 ci: verify backend and secure dependency updates #1 #5 #6
Backend security / security (pull_request) Successful in 8s
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Successful in 2m26s
2026-09-13 19:58:29 +03:00
renovate-bot a5156fbeb5 Add renovate.json 2026-09-13 14:02:04 +00:00
20 changed files with 4534 additions and 2129 deletions
+2 -2
View File
@@ -14,8 +14,8 @@
| JWT, cookie, login/refresh/logout, guard/access, token encryption, sensitive logs | [Security](conventions/security-auth.md) | | JWT, cookie, login/refresh/logout, guard/access, token encryption, sensitive logs | [Security](conventions/security-auth.md) |
| External client/integration boundary; T-Bank/gRPC/proto, retry/rate limit/cache | [Integrations](conventions/backend-integrations.md) | | External client/integration boundary; T-Bank/gRPC/proto, retry/rate limit/cache | [Integrations](conventions/backend-integrations.md) |
| Logging/request context без изменения secrets/auth | [Logging](conventions/backend-architecture.md#logging) | | Logging/request context без изменения secrets/auth | [Logging](conventions/backend-architecture.md#logging) |
| Новый abstraction/dependency, refactor, неясный scope | [Общий выбор реализации](../../docs/development/engineering-governance.md#выбор-реализации) | | Новый abstraction/dependency, refactor, неясный scope | [Общий выбор реализации](../../AGENTS.md) |
| Изменение request/response/route/status/error shape или Swagger metadata | HTTP API + [общий contract workflow](../../docs/development/runtime-openapi-verification.md) | | Изменение request/response/route/status/error shape или Swagger metadata | HTTP API + [Источник HTTP-контракта](../../docs/architecture/http-api.md#источник-контракта) |
Новый endpoint обычно требует HTTP API + Testing; Architecture/Data/Security Новый endpoint обычно требует HTTP API + Testing; Architecture/Data/Security
добавляются по новым ответственности, persistence или access rules. добавляются по новым ответственности, persistence или access rules.
+1 -2
View File
@@ -4,8 +4,7 @@
Сначала определи, меняется wire contract или только реализация существующего Сначала определи, меняется wire contract или только реализация существующего
use case. Для route/request/response/status/error shape читай use case. Для route/request/response/status/error shape читай
[HTTP semantics](../../../docs/architecture/http-api.md) и [HTTP semantics и источник контракта](../../../docs/architecture/http-api.md).
[общий contract workflow](../../../docs/development/runtime-openapi-verification.md).
| Проверка | Где выполнять | | Проверка | Где выполнять |
| --- | --- | | --- | --- |
+2 -1
View File
@@ -2,7 +2,8 @@
## Выбор уровня ## Выбор уровня
Применяй [общие testing risks](../../../docs/development/engineering-governance.md#risk-based-testing). Проверяй риски доступа, денежных расчётов, целостности данных, конкурентных
изменений, публичного контракта и подтверждённых регрессий.
Тесты должны различать правильное и неправильное наблюдаемое поведение. Тесты должны различать правильное и неправильное наблюдаемое поведение.
| Что меняется | Проверка | | Что меняется | Проверка |
+3
View File
@@ -0,0 +1,3 @@
{
"frontend": "0244acf429c525b23117f165bbe52ef5403eefd3"
}
+26
View File
@@ -0,0 +1,26 @@
name: Conventional commits
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
commits:
runs-on: ubuntu-latest
steps:
- uses: https://github.com/actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: https://github.com/actions/setup-node@v4
with:
node-version-file: .nvmrc
- run: npm ci --ignore-scripts
- name: Check PR title and commits
env:
PR_TITLE: ${{ github.event.pull_request.title }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
printf '%s\n' "$PR_TITLE" | npm run commitlint -- --strict
npm run commitlint -- --strict --from "$BASE_SHA" --to "$HEAD_SHA"
+31
View File
@@ -0,0 +1,31 @@
name: Backend security
on:
push:
branches:
- '**'
pull_request:
schedule:
- cron: '17 5 * * *'
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: https://github.com/actions/checkout@v4
with:
fetch-depth: 0
- name: Record checked revision
run: git rev-parse HEAD
- name: Scan history with Gitleaks 8.30.1
run: |
curl --fail --location --silent --show-error https://github.com/gitleaks/gitleaks/releases/download/v8.30.1/gitleaks_8.30.1_linux_x64.tar.gz -o /tmp/gitleaks.tar.gz
echo '551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb /tmp/gitleaks.tar.gz' | sha256sum --check
mkdir -p /tmp/gitleaks-bin
tar -xzf /tmp/gitleaks.tar.gz -C /tmp/gitleaks-bin gitleaks
/tmp/gitleaks-bin/gitleaks git --log-opts=--all --redact=100 --no-banner
- uses: https://github.com/actions/setup-node@v4
with:
node-version-file: .nvmrc
- name: Audit runtime and development dependencies
run: npm audit --include=dev --audit-level=low
+50
View File
@@ -0,0 +1,50 @@
name: Backend verify
on:
push:
branches: ['**']
pull_request:
jobs:
verify:
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
steps:
- uses: https://github.com/actions/checkout@v4
with:
path: backend
- name: Checkout compatible peer revisions
env:
SOURCE_BRANCH: ${{ github.head_ref || github.ref_name }}
TARGET_BRANCH: ${{ github.base_ref || github.ref_name }}
run: |
set -eu
for repo in frontend; do
ref=develop
case "$SOURCE_BRANCH:$TARGET_BRANCH" in
release/*:*|*:main)
ref=$(jq -er --arg repo "$repo" '.[$repo]' .ci/refs.json)
printf '%s\n' "$ref" | grep -Eq '^[0-9a-f]{40}$'
;;
esac
target="../$repo"
if [ "$repo" = main ]; then target=..; fi
git init "$target"
git -C "$target" remote add origin "https://git.personal.ksv741.ru/WealthLedger/$repo.git"
git -C "$target" fetch --depth 1 origin "$ref"
git -C "$target" checkout --detach FETCH_HEAD
git -C "$target" rev-parse HEAD
done
git rev-parse HEAD
- uses: https://github.com/actions/setup-node@v4
with:
node-version-file: backend/.nvmrc
- run: npm ci
- name: Generate Prisma client before typechecks
run: npx --no-install prisma generate
- name: Run all backend gates
run: npm run verify
- name: Run isolated SQLite and runtime OpenAPI suites
run: npm run test:e2e
+17
View File
@@ -0,0 +1,17 @@
# Reviewed historical false positives only; new commits remain scanned.
# Test fixtures: base64 of the deterministic string 0123456789abcdef repeated twice.
25d7c5780b60343fecb4f1ae9a30392776eb5aec:src/config/env.validation.spec.ts:generic-api-key:30
31cbba8654f01adf11c52e12c2b286200d6cad7d:src/config/env.validation.spec.ts:generic-api-key:10
31cbba8654f01adf11c52e12c2b286200d6cad7d:src/config/env.validation.spec.ts:generic-api-key:17
31cbba8654f01adf11c52e12c2b286200d6cad7d:src/config/env.validation.spec.ts:generic-api-key:42
31cbba8654f01adf11c52e12c2b286200d6cad7d:test/e2e-env.cjs:generic-api-key:4
326fb67def9b3878d5447ef838ae96d50bf493d6:src/tbank/brokerage-operations.service.spec.ts:generic-api-key:15
34c2b79e276c9575996604f3f862bc866cfe44e7:src/tbank/upcoming-events.service.spec.ts:generic-api-key:15
c0a4a9388074bdce20138dd5649805ed24a9e9fa:src/tbank/brokerage-accounts.service.spec.ts:generic-api-key:12
ce24a84b7fb48091d2b91836eb7b702a2f811c96:test/e2e-env.cjs:generic-api-key:16
dfca11c81f7e6dadce3ca6f961d265c5e3f8ff8e:src/tbank/portfolio.service.spec.ts:generic-api-key:16
# Historical .env.example JWT_SECRET is an explicit replace-with placeholder.
4cbfc2621cfc54df3d09786905130c28a2323a04:.env.example:generic-api-key:4
# Historical CircleCI badge copied verbatim from nestjs/typescript-starter README.
# Verified against https://github.com/nestjs/typescript-starter/blob/master/README.md
f8dcfb71c1767696a9aa6741ddaf6575416c901e:README.md:generic-api-key:5
+1
View File
@@ -0,0 +1 @@
save-exact=true
+106
View File
@@ -0,0 +1,106 @@
{
"git": {
"requireBranch": "release/*",
"requireCleanWorkingDir": true,
"requireUpstream": false,
"requireCommits": true,
"commitMessage": "chore(release): ${version}",
"tagName": "v${version}",
"tag": false,
"push": false
},
"npm": {
"publish": false
},
"github": {
"release": false
},
"gitlab": {
"release": false
},
"hooks": {
"after:git:init": "node scripts/check-release.cjs"
},
"plugins": {
"@release-it/conventional-changelog": {
"infile": "CHANGELOG.md",
"preset": {
"name": "conventionalcommits",
"types": [
{
"type": "chore",
"scope": "release",
"effect": "hidden"
},
{
"type": "feat",
"section": "Features",
"effect": "bump"
},
{
"type": "fix",
"section": "Bug Fixes",
"effect": "bump"
},
{
"type": "perf",
"section": "Performance",
"effect": "bump"
},
{
"type": "docs",
"section": "Documentation",
"effect": "bump"
},
{
"type": "spec",
"section": "Specifications",
"effect": "bump"
},
{
"type": "refactor",
"section": "Refactoring",
"effect": "bump"
},
{
"type": "build",
"section": "Build",
"effect": "bump"
},
{
"type": "ci",
"section": "CI",
"effect": "bump"
},
{
"type": "test",
"section": "Tests",
"effect": "bump"
},
{
"type": "style",
"section": "Styles",
"effect": "bump"
},
{
"type": "chore",
"section": "Maintenance",
"effect": "bump"
},
{
"type": "revert",
"section": "Reverts",
"effect": "bump"
}
]
},
"context": {
"host": "https://git.personal.ksv741.ru",
"owner": "WealthLedger",
"repository": "backend",
"linkReferences": true,
"commit": "commit"
}
}
}
}
+10 -3
View File
@@ -12,12 +12,19 @@ zero-warning ESLint, application/test TypeScript, Jest и build.
`lint:fix`/`format` пишут файлы и запускаются отдельно от доказательства проверки. `lint:fix`/`format` пишут файлы и запускаются отдельно от доказательства проверки.
`test:cov` — диагностика без общего threshold; scripts принадлежат `package.json`. `test:cov` — диагностика без общего threshold; scripts принадлежат `package.json`.
HTTP contract changes дополнительно проходят общий HTTP contract changes сохраняют [направление контракта](../docs/architecture/http-api.md#источник-контракта)
[contract workflow](../docs/development/runtime-openapi-verification.md). и проходят contract check. Общий e2e запускается на отдельных временных DB;
Общий e2e запускается на отдельных временных DB; применимость и маршрут проверки применимость и маршрут проверки
описаны в [backend testing](.ai/conventions/backend-testing.md). описаны в [backend testing](.ai/conventions/backend-testing.md).
Generated Prisma client не редактируется вручную. Credentials, авторизация Generated Prisma client не редактируется вручную. Credentials, авторизация
доступа к счетам и внешние интеграции остаются server-side. доступа к счетам и внешние интеграции остаются server-side.
ESLint/TypeScript не доказывают правильность domain boundaries, security или ESLint/TypeScript не доказывают правильность domain boundaries, security или
денежных вычислений: для них нужны semantic review и risk-based tests. денежных вычислений: для них нужны semantic review и risk-based tests.
## Ветки и релизы
Работа — в отдельной ветке от `develop`, затем PR в `develop`; в `main` напрямую
не пушить. Release/hotfix и синхронизация веток — по [root README](../README.md#релизы-и-ветки).
Commits и заголовки PR — Conventional Commits; для спецификаций допустим `spec:`.
Перед подготовкой релиза прочитай root README; версии вручную не повышать.
+83
View File
@@ -0,0 +1,83 @@
# Changelog
## 0.1.0 (2026-09-14)
### Features
* add authorization ([4cbfc26](https://git.personal.ksv741.ru/WealthLedger/backend/commit/4cbfc2621cfc54df3d09786905130c28a2323a04))
* add bond details, yields and credit ratings ([235c179](https://git.personal.ksv741.ru/WealthLedger/backend/commit/235c179ff813dac3312b849928d11734bccba823))
* add brocker account list ([c0a4a93](https://git.personal.ksv741.ru/WealthLedger/backend/commit/c0a4a9388074bdce20138dd5649805ed24a9e9fa))
* add logging ([25d7c57](https://git.personal.ksv741.ru/WealthLedger/backend/commit/25d7c5780b60343fecb4f1ae9a30392776eb5aec))
* add manual bank card ledger ([e6f58ef](https://git.personal.ksv741.ru/WealthLedger/backend/commit/e6f58ef0eef3fbae079270a0d429afd17e4cd3ac))
* add operations list ([326fb67](https://git.personal.ksv741.ru/WealthLedger/backend/commit/326fb67def9b3878d5447ef838ae96d50bf493d6))
* add portfolio ([dfca11c](https://git.personal.ksv741.ru/WealthLedger/backend/commit/dfca11c81f7e6dadce3ca6f961d265c5e3f8ff8e))
* add stock details and ticker resolution ([f24fd98](https://git.personal.ksv741.ru/WealthLedger/backend/commit/f24fd98fbcbbf952b11bb61f607ae0aec4456839))
* add tbank tokens ([31cbba8](https://git.personal.ksv741.ru/WealthLedger/backend/commit/31cbba8654f01adf11c52e12c2b286200d6cad7d))
* add агегку events ([34c2b79](https://git.personal.ksv741.ru/WealthLedger/backend/commit/34c2b79e276c9575996604f3f862bc866cfe44e7))
* aggregate portfolio data across accounts ([eaf2f67](https://git.personal.ksv741.ru/WealthLedger/backend/commit/eaf2f67b34b2f8b45a9f5d53c544b91304b333d3))
* **cards:** support inclusive date range queries ([3cf883e](https://git.personal.ksv741.ru/WealthLedger/backend/commit/3cf883efbc6fceddc889c5aadc3c8ffb410c6de5))
* enrich ledger events with logo metadata ([84fabd2](https://git.personal.ksv741.ru/WealthLedger/backend/commit/84fabd264fa539dfefb1172e27a038870a30d845))
* establish backend foundation ([ab21426](https://git.personal.ksv741.ru/WealthLedger/backend/commit/ab21426478233b1cdfc7571c796f76d347874501))
* **events:** support date range filtering ([a79f59a](https://git.personal.ksv741.ru/WealthLedger/backend/commit/a79f59a468dd113147b6f1a04ed0efd9828046c6))
* expose instrument brand logo name in portfolio positions ([5375e55](https://git.personal.ksv741.ru/WealthLedger/backend/commit/5375e5598a284238b995661dd2c0e9ce5901d190))
* expose instrument isin in portfolio positions ([5aa9bd3](https://git.personal.ksv741.ru/WealthLedger/backend/commit/5aa9bd395a8e49e423764eb7c4a88afe56332ad4))
* expose logos and ISINs for upcoming events ([33f703d](https://git.personal.ksv741.ru/WealthLedger/backend/commit/33f703d9a375e3d88e492fbb338e609d6c499d7f))
* **income:** add account income analytics API ([7ba4da0](https://git.personal.ksv741.ru/WealthLedger/backend/commit/7ba4da0d1b49afcb0db3d1756254e5d5e04f0c35))
* initial commit ([f8dcfb7](https://git.personal.ksv741.ru/WealthLedger/backend/commit/f8dcfb71c1767696a9aa6741ddaf6575416c901e))
* **portfolio:** expose asset allocation by currency ([05747dc](https://git.personal.ksv741.ru/WealthLedger/backend/commit/05747dc3757cdfd4c3d840ad0500861063a76b09))
* **portfolio:** expose position tickers ([924f60f](https://git.personal.ksv741.ru/WealthLedger/backend/commit/924f60f65357781df967bfbaf1538f3400ad620a))
* **tbank:** add brokerage account summaries ([e489d45](https://git.personal.ksv741.ru/WealthLedger/backend/commit/e489d45f889656183e88ad68d964f721b715cbdb))
* use money for upcoming event projections ([f1df104](https://git.personal.ksv741.ru/WealthLedger/backend/commit/f1df1044623862770ecb40fd735e1aea08dc2a68))
### Bug Fixes
* align auth success status contract ([9bd3400](https://git.personal.ksv741.ru/WealthLedger/backend/commit/9bd3400264de40a90b45d0cd997c2c752548c0bb))
* allow multi-year income analytics periods ([9fcc0ec](https://git.personal.ksv741.ru/WealthLedger/backend/commit/9fcc0ec01068372e6756f60bb49d83643e07466d))
* harden auth and cache concurrency ([c77b3cf](https://git.personal.ksv741.ru/WealthLedger/backend/commit/c77b3cf782f24ad3007add43f768d721e8f02386))
* harden backend runtime artifact hygiene ([6052565](https://git.personal.ksv741.ru/WealthLedger/backend/commit/60525656b8ecdc4b63956f0d7b77e4286961edc4))
* **income:** expose authoritative entry membership ([bdc3847](https://git.personal.ksv741.ru/WealthLedger/backend/commit/bdc384766649bb48513055bb809f0d1b45b91f54))
* isolate dev output from production builds ([320e8a0](https://git.personal.ksv741.ru/WealthLedger/backend/commit/320e8a04b0ad8e0d57a89e07768e600bc16bab36))
* little fixes ([e77ebc6](https://git.personal.ksv741.ru/WealthLedger/backend/commit/e77ebc6e8f78f96a4ee57c2684769ea4ec923017))
* make backend local verification safe ([71d57d6](https://git.personal.ksv741.ru/WealthLedger/backend/commit/71d57d60bcf2186d4f8f02169d1bea4ea4d672e3))
* make SQLite migrations and e2e reproducible ([ce24a84](https://git.personal.ksv741.ru/WealthLedger/backend/commit/ce24a84b7fb48091d2b91836eb7b702a2f811c96))
* recover portfolio instrument metadata on backend ([8ec172f](https://git.personal.ksv741.ru/WealthLedger/backend/commit/8ec172f48eefa2237dc0c16919fbb2e726b39a65))
* **tbank:** isolate caches by connection generation ([19fe7e7](https://git.personal.ksv741.ru/WealthLedger/backend/commit/19fe7e75d59792e9c6d6b702ab192fa2d5ccc936))
* **tbank:** type connectedAt as date-time ([55b100d](https://git.personal.ksv741.ru/WealthLedger/backend/commit/55b100d5f6bed126633432654a3353f862e6f428))
* type T-Bank client config ([18d7cfc](https://git.personal.ksv741.ru/WealthLedger/backend/commit/18d7cfcf9fecb89e99f7ba1f5d43602807ae98b2))
### Documentation
* **agents:** link audit remediation registry ([595fc04](https://git.personal.ksv741.ru/WealthLedger/backend/commit/595fc0458b3af37ef5eb0c647c401f39f34fe5f0))
* **ai:** add scoped backend conventions ([a83e26e](https://git.personal.ksv741.ru/WealthLedger/backend/commit/a83e26e5ef5d7cae3179a182fb5359a440538177))
* define canonical OpenSpec store ([fee4f8c](https://git.personal.ksv741.ru/WealthLedger/backend/commit/fee4f8c8e6e3aa8fc4c41522dc6697825316f8f6))
* refresh backend onboarding ([fec542a](https://git.personal.ksv741.ru/WealthLedger/backend/commit/fec542a275ed6c8273bb253ca4b58a497f74cd99))
* remove useless ([da17893](https://git.personal.ksv741.ru/WealthLedger/backend/commit/da178933509512c05c501773947f35397783f249))
* update routes to system documentation ([b1906c8](https://git.personal.ksv741.ru/WealthLedger/backend/commit/b1906c8e3ca242a0e30bd63519504c0c070f0354))
* update system documentation references ([d4fc28c](https://git.personal.ksv741.ru/WealthLedger/backend/commit/d4fc28cbbf0bb76a8c11a68f09bbe41151067d88))
### Refactoring
* centralize domain values and enforce numeric lint ([8637ad2](https://git.personal.ksv741.ru/WealthLedger/backend/commit/8637ad2f346c7e03e709b3a52d1d67995415a707))
* enforce strict backend typing ([346a6f0](https://git.personal.ksv741.ru/WealthLedger/backend/commit/346a6f0057178a2fe157c45ecf93740140c10440))
* organize backend by business responsibility ([8ba0053](https://git.personal.ksv741.ru/WealthLedger/backend/commit/8ba005346dbbd515e2c1d71bf99fdacf4b73947f))
* refactor future event list ([e005541](https://git.personal.ksv741.ru/WealthLedger/backend/commit/e0055414d6947e46fb58db1abe96f4ec3ea74f8c))
* **tbank:** centralize access rules ([130b303](https://git.personal.ksv741.ru/WealthLedger/backend/commit/130b303ec123f144d3833e5c7afa88d40f16f081))
### CI
* verify backend and secure dependency updates [#1](https://git.personal.ksv741.ru/WealthLedger/backend/issues/1) [#5](https://git.personal.ksv741.ru/WealthLedger/backend/issues/5) [#6](https://git.personal.ksv741.ru/WealthLedger/backend/issues/6) ([4c8ba2f](https://git.personal.ksv741.ru/WealthLedger/backend/commit/4c8ba2fac903c883849359aa354f3ffa749ca085))
### Tests
* cover isolated SQLite invariants and durability ([7fde3ec](https://git.personal.ksv741.ru/WealthLedger/backend/commit/7fde3ece6ec7143723140357602861cd2e20b3a5))
### Maintenance
* codify backend local verification ([2772d53](https://git.personal.ksv741.ru/WealthLedger/backend/commit/2772d53647132e6119e411c6d18234db4301e541))
* configure releases and develop workflow ([f01b82d](https://git.personal.ksv741.ru/WealthLedger/backend/commit/f01b82d36686ac27495263071bc82b34ae2f9b01))
* **deps:** pin node.js to v24.21.0 ([97e864b](https://git.personal.ksv741.ru/WealthLedger/backend/commit/97e864bc06a58737cae6669d42255f278d93e887))
* **deps:** update and pin backend dependencies ([2bc8745](https://git.personal.ksv741.ru/WealthLedger/backend/commit/2bc87454954d0bd3eeab11634ed16eed869dbaab))
* **deps:** upgrade backend to Nest 12 and TypeScript 6 ([121af70](https://git.personal.ksv741.ru/WealthLedger/backend/commit/121af701b722467353a33bf05e0b27a40ed5736e))
* save pending changes ([8c074d8](https://git.personal.ksv741.ru/WealthLedger/backend/commit/8c074d85de3bc55d0ba750b86bc7b026649fa6bf))
* simplify backend verification ([fd4572a](https://git.personal.ksv741.ru/WealthLedger/backend/commit/fd4572a64563c588029af38cd7b4cddc3e014cdf))
* upgrade Node to 24 LTS ([197ffe2](https://git.personal.ksv741.ru/WealthLedger/backend/commit/197ffe21368b337f27d27c22e473570258ebdc3b))
+35 -6
View File
@@ -34,8 +34,38 @@ application/test typechecks, Jest и build. `npm run lint:fix` — отдель
записывающая команда, `npm run test:cov` — диагностика без общего числового записывающая команда, `npm run test:cov` — диагностика без общего числового
threshold. `npm run test:e2e` отдельно проверяет все HTTP suites на новых базах threshold. `npm run test:e2e` отдельно проверяет все HTTP suites на новых базах
и runtime OpenAPI с соседним frontend checkout. Для полной backend-проверки и 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 и PR. Frontend snapshot для
разработки берётся из `develop`; для `main`, PR в `main` и `release/*` — из
полного SHA в `.ci/refs.json`. Лог сохраняет оба 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` Общий `tsconfig.json` включает `strict: true` и `noFallthroughCasesInSwitch`
для приложения, тестов и сборок. ESLint запрещает non-null assertions для приложения, тестов и сборок. ESLint запрещает non-null assertions
@@ -53,13 +83,10 @@ runtime-валидацию. В обычном коде нужны инициал
- [HTTP API](.ai/conventions/backend-http-api.md), [data](.ai/conventions/backend-data.md) и [testing](.ai/conventions/backend-testing.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) - [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) - [Карта проектных фактов](../docs/README.md)
- [API contract и runtime OpenAPI](../docs/development/runtime-openapi-verification.md) - [API contract и runtime OpenAPI](../docs/architecture/http-api.md#источник-контракта)
- [Обзор поставленной системы](../docs/overview.md) - [Обзор поставленной системы](../docs/overview.md)
- [Архитектурные решения](../docs/adr/README.md) - [Архитектурные решения](../docs/adr/README.md)
- [Remediation registry](../docs/development/audit-remediation.md)
Из backend runtime OpenAPI можно read-only сверить с frontend snapshot: Из backend runtime OpenAPI можно read-only сверить с frontend snapshot:
@@ -133,3 +160,5 @@ npm run test:durability -- "$baseline_dir"
выберите совместимую предыдущую revision и проверьте её API-сценарии runner. выберите совместимую предыдущую revision и проверьте её API-сценарии runner.
Durability оставляет временные DB, логи и `result.json` по пути из вывода для Durability оставляет временные DB, логи и `result.json` по пути из вывода для
диагностики; он не откатывает schema пользовательской базы. диагностики; он не откатывает schema пользовательской базы.
Версии и ветки: [процесс релиза](../README.md#релизы-и-ветки).
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: { "type-enum": [2, "always", ["feat", "fix", "perf", "docs", "spec", "refactor", "build", "ci", "test", "style", "chore", "revert"]] },
};
+4041 -2051
View File
File diff suppressed because it is too large Load Diff
+78 -63
View File
@@ -1,12 +1,12 @@
{ {
"name": "wealth-ledger-backend", "name": "wealth-ledger-backend",
"version": "0.0.1", "version": "0.1.0",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,
"license": "UNLICENSED", "license": "UNLICENSED",
"engines": { "engines": {
"node": "24.x" "node": "v24.21.0"
}, },
"scripts": { "scripts": {
"build": "prisma generate && nest build", "build": "prisma generate && nest build",
@@ -20,74 +20,88 @@
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"typecheck:app": "tsc --project tsconfig.typecheck.app.json", "typecheck:app": "tsc --project tsconfig.typecheck.app.json",
"typecheck:test": "tsc --project tsconfig.typecheck.test.json", "typecheck:test": "tsc --project tsconfig.typecheck.test.json",
"test": "jest", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:watch": "jest --watch", "test:watch": "npm test -- --watch",
"test:cov": "jest --coverage", "test:cov": "npm test -- --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:debug": "node --experimental-vm-modules --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "node test/sqlite.cjs --all", "test:e2e": "node test/sqlite.cjs --all",
"test:sqlite": "node test/sqlite.cjs", "test:sqlite": "node test/sqlite.cjs",
"test:durability": "node test/bank-cards-durability.cjs", "test:durability": "node test/bank-cards-durability.cjs",
"test:openapi-contract": "node test/sqlite.cjs openapi-contract.e2e-spec.ts", "test:openapi-contract": "node test/sqlite.cjs openapi-contract.e2e-spec.ts",
"verify": "npm run lint && npm run typecheck:app && npm run typecheck:test && npm test -- --runInBand && npm run build" "verify": "npm run lint && npm run typecheck:app && npm run typecheck:test && npm test -- --runInBand && npm run build",
"release:preview": "release-it --dry-run --ci",
"release:prepare": "release-it --ci",
"commitlint": "commitlint"
}, },
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.14.4", "@grpc/grpc-js": "1.14.4",
"@grpc/proto-loader": "^0.8.1", "@grpc/proto-loader": "0.8.1",
"@nestjs/common": "^11.0.1", "@nestjs/common": "12.0.1",
"@nestjs/config": "^4.0.4", "@nestjs/config": "12.0.0",
"@nestjs/core": "^11.0.1", "@nestjs/core": "12.0.1",
"@nestjs/jwt": "^11.0.2", "@nestjs/jwt": "12.0.1",
"@nestjs/passport": "^11.0.5", "@nestjs/passport": "12.0.0",
"@nestjs/platform-express": "^11.0.1", "@nestjs/platform-express": "12.0.1",
"@nestjs/swagger": "11.4.5", "@nestjs/swagger": "12.0.1",
"@prisma/adapter-better-sqlite3": "^7.9.1", "@prisma/adapter-better-sqlite3": "7.10.0",
"@prisma/client": "^7.9.1", "@prisma/client": "7.10.0",
"bcrypt": "^6.0.0", "bcrypt": "6.0.0",
"better-sqlite3": "^12.6.0", "better-sqlite3": "13.0.3",
"cheerio": "1.1.2", "cheerio": "1.2.0",
"class-transformer": "^0.5.1", "class-transformer": "0.5.1",
"class-validator": "^0.15.1", "class-validator": "0.15.1",
"cookie-parser": "^1.4.7", "cookie-parser": "1.4.7",
"lru-cache": "^11.2.4", "lru-cache": "11.5.2",
"nestjs-pino": "^4.6.1", "nestjs-pino": "5.1.0",
"passport": "^0.7.0", "passport": "0.7.0",
"passport-jwt": "^4.0.1", "passport-jwt": "4.0.1",
"pino-http": "^11.0.0", "pino-http": "11.0.0",
"reflect-metadata": "^0.2.2", "reflect-metadata": "0.2.2",
"rxjs": "^7.8.1" "rxjs": "7.8.2"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.2.0", "@commitlint/cli": "21.2.2",
"@eslint/js": "^9.18.0", "@commitlint/config-conventional": "21.2.2",
"@nestjs/cli": "^11.0.0", "@eslint/eslintrc": "3.3.7",
"@nestjs/schematics": "^11.0.0", "@eslint/js": "10.0.1",
"@nestjs/testing": "^11.0.1", "@nestjs/cli": "12.0.0",
"@types/bcrypt": "^6.0.0", "@nestjs/schematics": "12.0.1",
"@types/cookie-parser": "^1.4.10", "@nestjs/testing": "12.0.1",
"@types/express": "^5.0.0", "@release-it/conventional-changelog": "12.0.0",
"@types/jest": "^30.0.0", "@types/bcrypt": "6.0.0",
"@types/node": "^24.13.3", "@types/cookie-parser": "1.4.10",
"@types/passport-jwt": "^4.0.1", "@types/express": "5.0.6",
"@types/supertest": "^6.0.2", "@types/jest": "30.0.0",
"eslint": "^9.18.0", "@types/node": "24.13.4",
"eslint-config-prettier": "^10.0.1", "@types/passport-jwt": "4.0.1",
"eslint-plugin-prettier": "^5.2.2", "@types/supertest": "7.2.1",
"globals": "^16.0.0", "conventional-changelog-conventionalcommits": "10.4.0",
"jest": "^30.0.0", "eslint": "10.10.0",
"prettier": "^3.4.2", "eslint-config-prettier": "10.1.8",
"prisma": "^7.9.1", "eslint-plugin-prettier": "5.5.6",
"source-map-support": "^0.5.21", "globals": "17.12.0",
"supertest": "^7.0.0", "jest": "30.5.1",
"ts-jest": "^29.2.5", "prettier": "3.9.6",
"ts-loader": "^9.5.2", "prisma": "7.10.0",
"ts-node": "^10.9.2", "release-it": "21.0.2",
"tsconfig-paths": "^4.2.0", "source-map-support": "0.5.21",
"typescript": "^5.7.3", "supertest": "7.2.2",
"typescript-eslint": "^8.20.0" "ts-jest": "29.4.12",
"ts-loader": "9.6.2",
"ts-node": "10.9.2",
"tsconfig-paths": "4.2.0",
"typescript": "6.0.3",
"typescript-eslint": "8.70.0"
}, },
"overrides": { "overrides": {
"@nestjs/swagger@11.4.5": { "@nestjs/platform-express": {
"js-yaml": "5.2.3" "multer": "2.3.0"
},
"@prisma/config@7.10.0": {
"deepmerge-ts": "8.0.2"
},
"prisma": {
"mysql2": "3.24.4"
} }
}, },
"jest": { "jest": {
@@ -108,12 +122,13 @@
"testEnvironment": "node" "testEnvironment": "node"
}, },
"allowScripts": { "allowScripts": {
"@prisma/engines@7.9.1": true, "@prisma/engines@7.10.0": true,
"prisma@7.9.1": true, "prisma@7.10.0": true,
"bcrypt@6.0.0": true, "bcrypt@6.0.0": true,
"better-sqlite3@12.11.1": true, "better-sqlite3@12.11.1": true,
"fsevents@2.3.3": true, "fsevents@2.3.3": true,
"protobufjs@7.6.5": true, "protobufjs@7.6.5": true,
"unrs-resolver@1.12.2": true "unrs-resolver@1.12.2": true,
"better-sqlite3@13.0.3": true
} }
} }
+31
View File
@@ -0,0 +1,31 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":semanticCommitTypeAll(chore)"
],
"timezone": "Europe/Moscow",
"labels": [
"dependencies"
],
"dependencyDashboard": true,
"rangeStrategy": "pin",
"packageRules": [
{
"matchUpdateTypes": [
"minor",
"patch"
],
"groupName": "non-major dependencies"
},
{
"matchUpdateTypes": [
"major"
],
"dependencyDashboardApproval": true
}
],
"baseBranchPatterns": [
"develop"
]
}
+10
View File
@@ -0,0 +1,10 @@
const assert = require("node:assert/strict");
const { execFileSync } = require("node:child_process");
const { version } = require("../package.json");
const git = (...args) => execFileSync("git", args, { encoding: "utf8" }).trim();
assert.equal(git("status", "--porcelain"), "", "Commit all changes before preparing a release");
const tags = git("tag", "--merged", "HEAD", "--list", "v[0-9]*", "--sort=-version:refname")
.split("\n").filter(tag => /^v\d+\.\d+\.\d+$/.test(tag));
assert.equal(version, tags[0]?.slice(1) ?? "0.0.0",
"Version is already prepared or release tags are missing. Fetch tags; finish the existing release before preparing another.");
+1
View File
@@ -522,6 +522,7 @@ export class TbankClient {
if ( if (
[status.UNAUTHENTICATED, status.PERMISSION_DENIED].includes(grpcCode) [status.UNAUTHENTICATED, status.PERMISSION_DENIED].includes(grpcCode)
) )
// eslint-disable-next-line preserve-caught-error -- Discard raw upstream authentication errors at the integration boundary.
throw new Error('INVALID_TBANK_TOKEN'); throw new Error('INVALID_TBANK_TOKEN');
if ( if (
grpcCode === status.NOT_FOUND && grpcCode === status.NOT_FOUND &&
+2 -1
View File
@@ -13,7 +13,8 @@
"target": "ES2023", "target": "ES2023",
"sourceMap": true, "sourceMap": true,
"outDir": "./dist", "outDir": "./dist",
"baseUrl": "./", "rootDir": ".",
"types": ["node", "jest"],
"incremental": true, "incremental": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,