5 Commits
Author SHA1 Message Date
ksv741 7bc8792b98 chore: document and adopt Node 24 LTS 2026-09-13 15:05:39 +03:00
ksv741 c74c573733 docs: close SQLite migration and e2e blocker 2026-09-13 14:52:20 +03:00
ksv741 b940d39946 docs: record backend refactor and close P1-12 2026-09-13 13:54:24 +03:00
ksv741 66721eee62 docs: record P1-11 SQLite verification 2026-09-13 12:33:40 +03:00
ksv741 f4cefd5c40 docs: record backend strict typing completion
Record delivery commit 346a6f0, assertion restrictions, DTO validation, verification results, and the initial SQLite timeouts followed by successful baseline and retry runs.
2026-09-13 12:18:21 +03:00
16 changed files with 276 additions and 55 deletions
+1 -1
View File
@@ -1 +1 @@
22 24.21.0
+1 -2
View File
@@ -51,8 +51,7 @@ WealthLedger помогает частному инвестору понимат
| Изменить или проверить систему | [Сопровождение](development/README.md), затем инструкции нужного репозитория | | Изменить или проверить систему | [Сопровождение](development/README.md), затем инструкции нужного репозитория |
Практический tutorial первого инвестиционного сценария пока не подготовлен: Практический tutorial первого инвестиционного сценария пока не подготовлен:
он требует подключения брокера, а запуск на новой базе имеет известное он требует подключения брокера. Маршрут первого знакомства выше — чтение, не учебный запуск.
ограничение. Маршрут первого знакомства выше — чтение, не учебный запуск.
UI-каталог содержит безопасные вымышленные примеры и поясняет границы их использования. UI-каталог содержит безопасные вымышленные примеры и поясняет границы их использования.
## Границы знаний ## Границы знаний
+206 -4
View File
@@ -76,11 +76,11 @@ remediation change создаётся после выбора владельце
| FE26-09 | Убрать механическое обязательное дробление каждого component. | [FE-G] F-07 | already-covered | done | 06.09.2026; [FE26-E]. [UI pattern](../../frontend/.ai/conventions/frontend-ui.md) сохраняет semantic ownership и допускает tightly-coupled renderers; это guidance, а не line-count gate. Конкретное разделение крупных modules учтено отдельно FE26-13. | | FE26-09 | Убрать механическое обязательное дробление каждого component. | [FE-G] F-07 | already-covered | done | 06.09.2026; [FE26-E]. [UI pattern](../../frontend/.ai/conventions/frontend-ui.md) сохраняет semantic ownership и допускает tightly-coupled renderers; это guidance, а не line-count gate. Конкретное разделение крупных modules учтено отдельно FE26-13. |
| FE26-10 | Объединить protected query policy и endpoint query identity ownership. | [FE-G] F-08; [FE-S] F-05 | already-covered | done | 06.09.2026; [FE26-E]. [App defaults](../../frontend/src/app/ui/App.tsx), [T-Bank VM](../../frontend/src/features/tbank-connection/ui/TbankConnectionSection.vm.ts) и entity-owned options operations/portfolio; status использует общий authenticated query seam. | | FE26-10 | Объединить protected query policy и endpoint query identity ownership. | [FE-G] F-08; [FE-S] F-05 | already-covered | done | 06.09.2026; [FE26-E]. [App defaults](../../frontend/src/app/ui/App.tsx), [T-Bank VM](../../frontend/src/features/tbank-connection/ui/TbankConnectionSection.vm.ts) и entity-owned options operations/portfolio; status использует общий authenticated query seam. |
| FE26-11 | Централизовать test cleanup и auth reset. | [FE-S] F-02 | already-covered | done | 06.09.2026; [FE26-E]. [Test setup](../../frontend/src/test/setup.ts): RTL cleanup, auth reset, MSW handler reset в общем afterEach. | | FE26-11 | Централизовать test cleanup и auth reset. | [FE-S] F-02 | already-covered | done | 06.09.2026; [FE26-E]. [Test setup](../../frontend/src/test/setup.ts): RTL cleanup, auth reset, MSW handler reset в общем afterEach. |
| FE26-12 | Убрать повтор server identity из Income view/model. | [FE-S] F-03 | confirmed | done | 06.09.2026; [FE26-E]. [Backend income service](../../backend/src/tbank/income-analytics.service.ts) передаёт instrumentKey; [Income VM](../../frontend/src/pages/account-income/ui/AccountIncomePage.vm.ts) проверяет и группирует готовую связь, не вычисляя identity. | | FE26-12 | Убрать повтор server identity из Income view/model. | [FE-S] F-03 | confirmed | done | 06.09.2026; [FE26-E]. [Backend income service](../../backend/src/modules/investments/income/income-analytics.service.ts) передаёт instrumentKey; [Income VM](../../frontend/src/pages/account-income/ui/AccountIncomePage.vm.ts) проверяет и группирует готовую связь, не вычисляя identity. |
| FE26-13 | Выделить самостоятельные ответственности семи крупных TSX modules. | [FE-S] F-04 | already-covered | done | 06.09.2026; [FE26-E]. Income/Events/Accounts/Account state views, [route fallback](../../frontend/src/app/routes/RouteFallback.tsx), [guards](../../frontend/src/app/routes/RouteGuards.tsx), breadcrumbs и T-Bank loaded section выделены во frontend `c97f62b`. | | FE26-13 | Выделить самостоятельные ответственности семи крупных TSX modules. | [FE-S] F-04 | already-covered | done | 06.09.2026; [FE26-E]. Income/Events/Accounts/Account state views, [route fallback](../../frontend/src/app/routes/RouteFallback.tsx), [guards](../../frontend/src/app/routes/RouteGuards.tsx), breadcrumbs и T-Bank loaded section выделены во frontend `c97f62b`. |
| FE26-14 | Устранить повтор test client policy и нестабильный cache lifetime. | [FE-S] F-06 | confirmed | done | 06.09.2026; [FE26-E]. [Test query factory](../../frontend/src/test/query.tsx) используется оставшимися auth/T-Bank harnesses; [auth test](../../frontend/src/features/auth/model/auth.test.tsx) проверяет сохранение client и seeded cache при rerender. | | FE26-14 | Устранить повтор test client policy и нестабильный cache lifetime. | [FE-S] F-06 | confirmed | done | 06.09.2026; [FE26-E]. [Test query factory](../../frontend/src/test/query.tsx) используется оставшимися auth/T-Bank harnesses; [auth test](../../frontend/src/features/auth/model/auth.test.tsx) проверяет сохранение client и seeded cache при rerender. |
| FE26-15 | Перенести компонентные стили из global CSS к владельцам. | [FE-S] F-08 | already-covered | done | 06.09.2026; [FE26-E]. [Global styles](../../frontend/src/shared/theme/styles.css) содержат базовые правила; AppShell, breadcrumbs и auth используют CSS Modules, StateView — Mantine props. | | FE26-15 | Перенести компонентные стили из global CSS к владельцам. | [FE-S] F-08 | already-covered | done | 06.09.2026; [FE26-E]. [Global styles](../../frontend/src/shared/theme/styles.css) содержат базовые правила; AppShell, breadcrumbs и auth используют CSS Modules, StateView — Mantine props. |
| FE26-16 | Исправить source connectedAt contract вместо String coercion. | [FE-S] F-09 | already-covered | done | 06.09.2026; [FE26-E]. [Backend DTO](../../backend/src/tbank/tbank-connection.dto.ts) задаёт nullable date-time string; [frontend consumer](../../frontend/src/features/tbank-connection/ui/TbankConnectionSectionLoaded.tsx) не скрывает неверный transport type через String. | | FE26-16 | Исправить source connectedAt contract вместо String coercion. | [FE-S] F-09 | already-covered | done | 06.09.2026; [FE26-E]. [Backend DTO](../../backend/src/modules/investments/tbank-connection/tbank-connection.dto.ts) задаёт nullable date-time string; [frontend consumer](../../frontend/src/features/tbank-connection/ui/TbankConnectionSectionLoaded.tsx) не скрывает неверный transport type через String. |
| FE26-17 | Перенести auth validation и payment invariants из JSX к model owners. | [FE-S] F-10 | already-covered | done | 06.09.2026; [FE26-E]. [Auth validation](../../frontend/src/features/auth/model/validation.ts), [ledger display](../../frontend/src/entities/broker-operation/model/display.ts) владеют соответствующими правилами. | | FE26-17 | Перенести auth validation и payment invariants из JSX к model owners. | [FE-S] F-10 | already-covered | done | 06.09.2026; [FE26-E]. [Auth validation](../../frontend/src/features/auth/model/validation.ts), [ledger display](../../frontend/src/entities/broker-operation/model/display.ts) владеют соответствующими правилами. |
| FE26-18 | Удалить redundant position modes и test-only proxy exports. | [FE-S] F-11 | already-covered | done | 06.09.2026; [FE26-E]. [PositionCard](../../frontend/src/pages/account/ui/components/PositionCard.view.tsx) выводит mode из kind; [StateView](../../frontend/src/shared/ui/StateView.tsx) не экспортирует Mantine Button; page barrels сохраняют product surface. | | FE26-18 | Удалить redundant position modes и test-only proxy exports. | [FE-S] F-11 | already-covered | done | 06.09.2026; [FE26-E]. [PositionCard](../../frontend/src/pages/account/ui/components/PositionCard.view.tsx) выводит mode из kind; [StateView](../../frontend/src/shared/ui/StateView.tsx) не экспортирует Mantine Button; page barrels сохраняют product surface. |
@@ -226,8 +226,8 @@ authority.
| WL-P2-02 | Вернуть предсказуемый 409 при конкурентной регистрации. | backend, specs, docs | done | [`2026-08-23-harden-auth-and-cache-concurrency`](../../specs/openspec/changes/archive/2026-08-23-harden-auth-and-cache-concurrency/) | — | 2026-08-23; backend `c77b3cf`, specs `6e20cdf`, docs `8568e7b`; P2002 mapping and barrier regression test passed. | | WL-P2-02 | Вернуть предсказуемый 409 при конкурентной регистрации. | backend, specs, docs | done | [`2026-08-23-harden-auth-and-cache-concurrency`](../../specs/openspec/changes/archive/2026-08-23-harden-auth-and-cache-concurrency/) | — | 2026-08-23; backend `c77b3cf`, specs `6e20cdf`, docs `8568e7b`; P2002 mapping and barrier regression test passed. |
| WL-P2-03 | Сделать refresh rotation атомарной. | backend, specs, docs | done | [`2026-08-23-harden-auth-and-cache-concurrency`](../../specs/openspec/changes/archive/2026-08-23-harden-auth-and-cache-concurrency/) | — | 2026-08-23; backend `c77b3cf`, specs `6e20cdf`, docs `8568e7b`; CAS one-winner regression test passed. | | WL-P2-03 | Сделать refresh rotation атомарной. | backend, specs, docs | done | [`2026-08-23-harden-auth-and-cache-concurrency`](../../specs/openspec/changes/archive/2026-08-23-harden-auth-and-cache-concurrency/) | — | 2026-08-23; backend `c77b3cf`, specs `6e20cdf`, docs `8568e7b`; CAS one-winner regression test passed. |
| WL-P2-04 | Синхронизировать runtime, OpenAPI и auth success statuses. | backend, frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; backend `9bd3400`, frontend `6d892da`, specs `800450d`, docs `b91280c`; metadata regression, frontend OpenAPI check и runtime/snapshot SHA совпали. | | WL-P2-04 | Синхронизировать runtime, OpenAPI и auth success statuses. | backend, frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; backend `9bd3400`, frontend `6d892da`, specs `800450d`, docs `b91280c`; metadata regression, frontend OpenAPI check и runtime/snapshot SHA совпали. |
| WL-P2-05 | Восстановить runnable backend e2e gate. | backend | deferred | — | Пересмотреть после следующей stable Prisma: три чистых `migrate deploy` на Node 22 должны пройти подряд. | 2026-08-23; Prisma 7.9.1 на Node 22 воспроизводимо возвращает пустой schema-engine error даже для fresh SQLite DB; published latest также 7.9.1. | | WL-P2-05 | Восстановить runnable backend e2e gate. | backend | done | — | — | 2026-09-13; унаследованный RUST_LOG изолирован в Prisma config, 3 последовательных и 2 параллельных полных e2e passed. [Результаты](#2026-09-13--wl-p2-05-воспроизводимый-sqlite-e2e). |
| WL-P2-06 | Добавить проходящий app/test TypeScript gate backend. | backend | done | [`2026-08-23-make-local-verification-agent-safe`](../../specs/openspec/changes/archive/2026-08-23-make-local-verification-agent-safe/) | — | 2026-08-23; backend `71d57d6`, specs `72444db`, docs `293df9c`; `npm run typecheck:app` и `npm run typecheck:test` — passed. | | WL-P2-06 | Добавить проходящий app/test TypeScript gate backend. | backend | done | [`2026-08-23-make-local-verification-agent-safe`](../../specs/openspec/changes/archive/2026-08-23-make-local-verification-agent-safe/) | — | 2026-08-23; backend `71d57d6`, specs `72444db`, docs `293df9c`; `npm run typecheck:app` и `npm run typecheck:test` — passed. [2026-09-13: включён strict по P1-10](#2026-09-13--wl-p2-06-strict-typescript). |
| WL-P2-07 | Сохранять cached data во время background refetch. | frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; frontend `6d892da`, specs `800450d`, docs `b91280c`; observable Accounts/Portfolio refetch tests и `npm run verify` — passed (17 files, 55 tests). | | WL-P2-07 | Сохранять cached data во время background refetch. | frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; frontend `6d892da`, specs `800450d`, docs `b91280c`; observable Accounts/Portfolio refetch tests и `npm run verify` — passed (17 files, 55 tests). |
| WL-P2-08 | Нормализовать cold-start refresh failure. | frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; frontend `6d892da`, specs `800450d`, docs `b91280c`; cold-start и protected-401 transport-failure tests passed. | | WL-P2-08 | Нормализовать cold-start refresh failure. | frontend | done | [`2026-08-24-align-api-contract-and-client-resilience`](../../specs/openspec/changes/archive/2026-08-24-align-api-contract-and-client-resilience/) | — | 2026-08-24; frontend `6d892da`, specs `800450d`, docs `b91280c`; cold-start и protected-401 transport-failure tests passed. |
| WL-P2-09 | Проверять backend runtime OpenAPI против frontend snapshot. | backend, frontend | done | [`2026-08-23-make-local-verification-agent-safe`](../../specs/openspec/changes/archive/2026-08-23-make-local-verification-agent-safe/) | — | 2026-08-23; frontend `7a3048c`, backend `71d57d6`, specs `72444db`, docs `293df9c`; runtime и snapshot SHA-256 совпали, frontend `npm run openapi:check` — passed. | | WL-P2-09 | Проверять backend runtime OpenAPI против frontend snapshot. | backend, frontend | done | [`2026-08-23-make-local-verification-agent-safe`](../../specs/openspec/changes/archive/2026-08-23-make-local-verification-agent-safe/) | — | 2026-08-23; frontend `7a3048c`, backend `71d57d6`, specs `72444db`, docs `293df9c`; runtime и snapshot SHA-256 совпали, frontend `npm run openapi:check` — passed. |
@@ -249,10 +249,212 @@ authority.
| WL-P3-07 | Защитить рабочий `.env` от случайного commit. | frontend, specs, docs | done | [`2026-08-24-address-dependency-advisories-and-repo-hygiene`](../../specs/openspec/changes/archive/2026-08-24-address-dependency-advisories-and-repo-hygiene/) | — | 2026-08-24; frontend `826936c`, specs `8897bd9`, docs `60a1c33`; hygiene check passed. | | WL-P3-07 | Защитить рабочий `.env` от случайного commit. | frontend, specs, docs | done | [`2026-08-24-address-dependency-advisories-and-repo-hygiene`](../../specs/openspec/changes/archive/2026-08-24-address-dependency-advisories-and-repo-hygiene/) | — | 2026-08-24; frontend `826936c`, specs `8897bd9`, docs `60a1c33`; hygiene check passed. |
| WL-P3-08 | Исключить runtime SQLite DB из Git. | backend, specs, docs | done | [`2026-08-24-address-dependency-advisories-and-repo-hygiene`](../../specs/openspec/changes/archive/2026-08-24-address-dependency-advisories-and-repo-hygiene/) | — | 2026-08-24; backend `6052565`, specs `8897bd9`, docs `60a1c33`; hygiene check passed. | | WL-P3-08 | Исключить runtime SQLite DB из Git. | backend, specs, docs | done | [`2026-08-24-address-dependency-advisories-and-repo-hygiene`](../../specs/openspec/changes/archive/2026-08-24-address-dependency-advisories-and-repo-hygiene/) | — | 2026-08-24; backend `6052565`, specs `8897bd9`, docs `60a1c33`; hygiene check passed. |
### 2026-09-13 — WL-P2-11: переход на Node 24 LTS
Продолжение bootstrap policy из WL-P2-11, части 14.backend/frontend/docs
[рабочего TODO](../../todo/wealthledger-engineering-improvements.md).
Node 24.21.0 / npm 11.19.0 выбран по [официальному каталогу релизов](https://nodejs.org/dist/index.json)
и [расписанию поддержки](https://github.com/nodejs/Release#release-schedule):
ветка Krypton LTS поддерживается до 30.04.2028.
`.nvmrc` frontend/backend/docs фиксируют 24.21.0, engines — 24.x.
Backend `@types/node` обновлён до 24.13.3; runtime dependencies не обновлялись.
Npm дополнил backend lockfile платформенными optional dependencies существующего
resolver. Для npm 11.19 явно разрешены install scripts сборочных зависимостей
с pin версий. Инструкция переустановки и отката — в
[локальном окружении](local-workspace.md#версия-node).
Specs продолжает наследовать frontend runtime; самостоятельный bootstrap CLI
из части 14.specs и CI остаются отдельными незавершёнными задачами.
Проверки относятся к frontend `53c852b`, backend `ce24a84`, docs `c74c573`,
specs `834f2d1` с текущим diff перехода Node:
- `npm ci` в frontend/backend/docs — PASS; backend native modules установлены
под Node 24, `npm run build` с генерацией Prisma client — PASS.
- Frontend `npm run verify` — PASS: 46 files, 268 tests, coverage, OpenAPI drift,
TypeScript, Biome, Knip, dependency boundaries, приложение и Storybook.
Прогон одновременно с установкой backend упирался в UI timeout; отдельный
повтор полного gate прошёл без изменения тестов или их таймаутов.
- Backend `npm run verify` — PASS: 35 suites, 257 tests, lint, оба typecheck и build.
- Backend `npm run test:e2e` — PASS: 8 suites, 98 tests; новая SQLite и штатные
migrations для каждой suite, включая runtime OpenAPI. Для HTTP-портов нужен
запуск вне sandbox. Рабочая БД не использовалась.
- Docs `npm run verify` — PASS: 54 Markdown-файла, 0 issues;
`git diff --check` во всех четырёх repos — PASS.
- OpenSpec CLI 1.10.0, существующая установка, исполненная Node 24.21.0:
`schema validate wealth-ledger-sdd --verbose` и
`validate --specs --strict --store wealth-ledger-specs` — PASS, 25 specs.
## История registry ## История registry
Terminal evidence добавляется сюда только после завершения соответствующего change. Terminal evidence добавляется сюда только после завершения соответствующего change.
### 2026-09-13 — WL-P2-05: воспроизводимый SQLite e2e
Закрыты TODO 03 и 03.docs, повторно проверен SQLite scope 11. Backend
`8637ad2` с текущим diff, Node 22.21.0 / Prisma 7.9.1. Schema, migrations,
зависимости и HTTP-контракт не менялись.
- До исправления fresh migration: `RUST_LOG=warn` и `error` — exit 1 с пустым
`Schema engine error`; переменная отсутствует или равна `info` — exit 0.
В исходном окружении было `RUST_LOG=warn`. Это воспроизведённая зависимость
запуска от окружения, а не доказательство внутреннего дефекта Rust engine.
- Prisma config исключает унаследованный `RUST_LOG` после dotenv. Общий runner
даёт каждому suite свою DB и один URL для migration/Jest, отклоняет прямой
Jest без изоляции и очищает каталог после ошибки или сигнала.
- `npm run verify` — PASS: zero-warning lint, app/test types, 35 suites /
257 unit tests, Prisma generation и build.
- Docs `npm run verify` — PASS: Markdown, ссылки/якоря и `git diff --check`.
- `npm run test:e2e` — PASS: 8 suites / 98 tests, включая runtime OpenAPI.
- `node test/sqlite-regression.cjs` — PASS: три последовательных и два
параллельных полных e2e (каждый 98 tests, всего 40 разных DB); внешний
вымышленный файл неизменён. Недоступный schema engine возвращает exit 1;
SIGINT/SIGTERM — 130/143. Все 43 созданных DB-каталога удалены.
- `npm run test:durability -- /tmp/p111-baseline` — PASS: отдельная baseline
сборка `8ec172f48eefa2237dc0c16919fbb2e726b39a65`, additive migration,
сохранение User/Session/TbankConnection, банковской истории и защиты повторов,
restart, откат приложения и backup/restore. `RUST_LOG=info` удалён из runner;
для старого baseline унаследованная переменная также исключается.
- HTTP/durability проверены вне sandbox после воспроизведения запрета локальных
портов `EPERM`. Это ограничение среды, не failing migration. Пользовательская
DB и `.env` не использовались как цель записи.
Логи этой проверки: `/tmp/wl-sqlite-verify.log`, `/tmp/wl-sqlite-e2e-1.log`,
`/tmp/wl-sqlite-regression.log`, `/tmp/wl-sqlite-durability.log`.
Подробные regression logs сохранены в системном temp-каталоге
`wealthledger-sqlite-regression-pSyuoe`, durability —
`wealthledger-bank-durability-V0u1NA`. Эти локальные временные логи могут быть
удалены системой; воспроизводимые команды и
[матрица рисков](../../backend/README.md#реальная-sqlite-и-сохранность-данных)
остаются в backend. Исторические evidence ниже сохранены без переписывания.
### 2026-09-13 — P1-12: backend responsibilities
Статус: `done`. Backend commit `8ba0053`.
BankCards разделён на services карт, операций и категорий, сценарий сводки и
конкретный repository. Общая transaction/retry boundary, ownership, idempotency,
optimistic concurrency и ограничения возвратов сохранены. Stock/bond services
разделены по каталогу, рынку и доходам; связные operations и T-Bank client
сохранены. Business modules отделены от integrations; сложные modules используют
слои ответственности, компактные остаются плоскими.
- `npm run verify` — passed: lint, app/test typecheck, 35 suites / 257 tests, build.
- Восемь существующих HTTP/e2e suites выполнены временным runner
`/tmp/wl-modular-http.cjs`: отдельная SQLite DB на suite, migrations с
`RUST_LOG=info`, configured HTTP, 118 tests passed. OpenAPI совпадает с frontend
snapshot. Общий e2e blocker и статус задачи 03 этим не закрываются.
- Финальный перенос 47 файлов проверен сравнением 142 исходников/tests:
различий кроме относительных путей и форматирования нет.
- Formatter, docs `npm run verify`, lint backend conventions и `git diff --check`
прошли. Новые dependencies и architecture tests не добавлены.
### 2026-09-13 — P1-11: реальная SQLite
P1-11 поставлена в backend commit `7fde3ec`. Дополнено доказательство
WL-P2-03; статус общего e2e WL-P2-05 не меняется. Команды и матрица рисков —
[backend README](../../backend/README.md#реальная-sqlite-и-сохранность-данных).
- `npm run test:sqlite` — два последовательных успешных запуска после фиксации
loopback-listener: 8 auth и 21 карточный HTTP/SQLite test. Каждый suite получает
собственную временную DB; Prisma не мокируется. Барьер перед CAS гарантирует,
что оба refresh прочитали прежний hash; победившая сессия переживает replay.
- Существующие карточные tests покрывают owner links, idempotency/tombstones,
версии, конкурентные refund/archive/write, rollback source lock, атомарный
перевод, точные суммы и FK/unique constraints. Новая тестовая платформа не нужна.
- `npm run test:durability -- /tmp/p111-baseline` — PASS: migration, restart,
previous-app rollback, backup/restore и чтение сохранённой финансовой истории.
Baseline экспортирован из `8ec172f48eefa2237dc0c16919fbb2e726b39a65` и собран
отдельно. Его lockfile совпадает с текущим; при этой проверке переиспользованы
установленные node_modules. README также описывает независимый `npm ci`.
Runner проверяет наличие build и неизменённый префикс migration history.
- Node 22.21.0: `npm run verify` — PASS (35 suites, 257 unit tests, zero-warning
lint, оба typecheck, Prisma generate и build).
- Первые HTTP-запуски с автоматическим открытием/закрытием сервера Supertest
дали плавающий 404. Suites теперь держат один loopback-listener до `app.close()`;
повторные проверки прошли. Sandbox требует разрешения на локальный порт.
- Миграции выполнены с `RUST_LOG=info`. Это подтверждение выбранных DB-сценариев,
не снятие прежнего ограничения общего `test:e2e` и не выполнение задачи 03.
### 2026-09-13 — WL-P2-06: strict TypeScript
Поставка backend: commit `346a6f0` (`refactor: enforce strict backend typing`).
По продолжению P1-10 в [общем tsconfig](../../backend/tsconfig.json) включён
`strict: true` без отключения отдельных strict-проверок;
`noFallthroughCasesInSwitch` сохранён отдельно. Убраны избыточные настройки,
которые теперь включает `strict`.
После замечания владельца вариант с definite-assignment `!` заменён:
в 14 файлах 315 полей DTO объявлены через `declare`. Заполнение входных DTO
принадлежит Nest/class-transformer, ответные DTO описывают возвращаемые объекты.
`declare` не генерирует поля со значением `undefined` и не подменяет проверку
входных данных. Optional/nullable-типы, декораторы и валидация сохранены.
В [TbankClient](../../backend/src/integrations/tbank/tbank.client.ts)
`getOpenAccounts` и `getDividends` задают тип результата на `call<Response>`,
как соседние RPC; тип параметра `.then` выводится из этого результата.
В [ESLint](../../backend/eslint.config.mjs) включён
`@typescript-eslint/no-non-null-assertion: error`. Он не охватывает `field!: Type`,
поэтому `no-restricted-syntax` отдельно запрещает definite-assignment `!`
в свойствах и переменных. Устранены также 51 прежний non-null assertion и
четыре definite-assignment assertions в тестах: используются сужение типов,
локальные значения, типизированные результаты фильтрации и runtime assertions
в тестах. Транзакции, проверки доступа, cache generation и денежная точность
сохранены; отсутствующая категория в сводке приводит к явной внутренней ошибке.
Проверено на Node 22.21.0, backend `3cf883e` с указанными изменениями:
- `npm run verify` — passed: lint без warnings, strict app/test typechecks,
35 Jest suites / 257 tests, Prisma generation и production build.
- `DATABASE_URL=file:/tmp/wealthledger-declared-dto-openapi-20260913.db npm run test:openapi-contract`
— passed, 1 test; frontend snapshot не менялся.
- TypeScript Compiler API подтвердил все strict options в app/test/build/dev
configs. Каждый config отклоняет шесть примеров: неинициализированное поле,
несовместимый callback, `null` вместо строки, implicit `any`/`this`, доступ
к `unknown` в `catch` (TS2564, TS2345, TS2322, TS7006, TS2683, TS18046).
- Проверка ESLint через `lintText` подтверждает ошибки для `value!`, `field!`
и `let value!`; декларация DTO без `!` разрешена.
- Новые тесты ValidationPipe проходят до и после замены деклараций:
обязательные credentials, нормализация email, вложенные money DTO и
обязательный version с optional-полями `PartialType`. Дополнены проверки
инструментов без UID; отдельный тест проверяет имя категории и ошибку
при нарушенной ссылке в банковской сводке.
- `NODE_ENV=development NODE_OPTIONS=--experimental-vm-modules npx jest --config test/jest-e2e.json --runInBand bank-cards.e2e-spec.ts`
с новой `DATABASE_URL=file:/tmp/bank-cards-*/test.db` — passed, 21 tests,
включая реальные миграции, валидацию HTTP, права владельца, возвраты,
транзакции и перезапуск. Runner использует `RUST_LOG=info` для миграций.
Первый прогон дал 19 passed / 2 timeout в сценариях возвратов и потребовал
остановки оставшегося Jest-процесса. Повтор на новой базе прошёл 21/21;
исходный `3cf883e` в отдельной копии с теми же dependencies также прошёл
21/21. Это не доказательство стабильности общего e2e gate.
- Полный `strict` проходит; 317 diagnostics из предыдущей оценки устранены.
Общий DB/e2e gate и ограничение WL-P2-05 остаются отдельной задачей.
### 2026-09-13 — WL-P2-06: backend TypeScript
Выполнен пункт P1-10 списка инженерных улучшений от 13.09.2026
как продолжение существующего TypeScript gate. В [общем tsconfig](../../backend/tsconfig.json)
включены `noImplicitAny`, `strictBindCallApply`, `noFallthroughCasesInSwitch`;
app/test typechecks, production и dev build наследуют эти настройки.
Исходный код, зависимости, unsafe-checks и публичный API не менялись.
Проверено на Node 22.21.0, backend `3cf883e` с указанным изменением tsconfig:
- `npm run verify` до и после изменения — passed: zero-warning ESLint,
оба TypeScript gate, 33 Jest suites / 253 tests, Prisma generation и build.
- Проверка через TypeScript Compiler API с виртуальным ошибочным файлом для
каждого из четырёх configs — passed: implicit-any параметр даёт TS7006,
неверные аргументы `call`/`apply`/`bind` — TS2345/TS2322, проваливание `switch`
— TS7029. Контроль с выключенными тремя flags принимает тот же файл.
- `DATABASE_URL=file:/tmp/wealthledger-p1-10-openapi-20260913.db npm run test:openapi-contract`
— passed, 1 test; runtime OpenAPI совпал с frontend snapshot.
- `npx tsc --project tsconfig.typecheck.test.json --incremental false --strict --noImplicitAny --strictBindCallApply --noFallthroughCasesInSwitch --pretty false`
— оценка полного `strict`: 317 diagnostics, из них 315 TS2564 для полей DTO
и две TS2345 в `TbankClient.getOpenAccounts` / `getDividends` из-за callback
для `Promise<unknown>`. Полный `strict` пока не включён; это отдельный этап.
- Общий DB/e2e gate не запускался; WL-P2-05 сохраняет прежний статус.
### 2026-08-26 — SDD26-01–SDD26-03, SDD26-09, SDD26-12, SDD26-17, SDD26-21, SDD26-28–SDD26-30: done ### 2026-08-26 — SDD26-01–SDD26-03, SDD26-09, SDD26-12, SDD26-17, SDD26-21, SDD26-28–SDD26-30: done
Change синхронизирован в canonical specs и архивирован в [`2026-08-26-harden-openspec-sdd-quality`](../../specs/openspec/changes/archive/2026-08-26-harden-openspec-sdd-quality/). Change синхронизирован в canonical specs и архивирован в [`2026-08-26-harden-openspec-sdd-quality`](../../specs/openspec/changes/archive/2026-08-26-harden-openspec-sdd-quality/).
+25 -9
View File
@@ -6,9 +6,24 @@ WealthLedger поставляется как локальное приложен
исходного кода. Описано локальное окружение; production-топология по нему исходного кода. Описано локальное окружение; production-топология по нему
не подтверждается. не подтверждается.
## Версия Node
Все локальные проверки используют Node 24 LTS; `.nvmrc` в frontend, backend
и docs фиксирует 24.21.0. Specs использует frontend `.nvmrc`.
По [официальному расписанию Node](https://github.com/nodejs/Release#release-schedule)
поддержка Node 24 завершается 30.04.2028.
В каждом npm-репозитории выполните `nvm install`, `nvm use --silent` и `npm ci`;
в backend затем `npm run build` для генерации Prisma client.
Поставляемый npm 11.19 запускает dependency install scripts только по
`allowScripts` в package.json; разрешения привязаны к версиям сборочных
зависимостей и пересматриваются при их обновлении.
После смены major обязательна переустановка native modules через `npm ci`.
Для отката верните прежние runtime/package/lockfile-конфигурации, выберите Node 22
и повторите `npm ci` и backend build. Сам переход Node не меняет схему или данные.
## Подготовка backend ## Подготовка backend
Локальная серверная среда использует Node 22 и SQLite. Для работы нужны: Локальная серверная среда использует Node 24 и SQLite. Для работы нужны:
| Параметр | Назначение и ограничение | | Параметр | Назначение и ограничение |
| --- | --- | | --- | --- |
@@ -25,13 +40,14 @@ T-Bank token вводится пользователем через интерф
на отдельной копии. Потеря или замена ключа не является безвредным сбросом: на отдельной копии. Потеря или замена ключа не является безвредным сбросом:
прежнее подключение нельзя расшифровать новым ключом. прежнее подключение нельзя расшифровать новым ключом.
**Известное ограничение:** ранее была зафиксирована ошибка `Schema engine error` После подготовки зависимостей и конфигурации примените штатные migrations:
на новой временной SQLite-базе до создания схемы. Условия проверки и пересмотра — из backend после `nvm use --silent` выполните `npx prisma migrate deploy`.
в [ограничении сквозной проверки](verification.md#известное-ограничение-сквозной-проверки). Для существующей базы сначала сохраните согласованный backup.
На Node 22.21.0 / Prisma 7.9.1 подтверждено три последовательных применения На Node 22.21.0 / Prisma 7.9.1 обнаружена зависимость fresh migration от
миграций к новым временным базам с `RUST_LOG=info` вне sandbox. Без этой унаследованного `RUST_LOG=warn/error`. Backend Prisma config исключает эту
переменной ошибка воспроизводится. Пользовательская база для воспроизведения переменную из процесса CLI; назначать `RUST_LOG=info` больше не требуется.
не нужна; успешная миграция сама по себе не подтверждает полный первый запуск. Условия и доказательство — в
[сквозной проверке](verification.md#известное-ограничение-сквозной-проверки).
В development доступна [локальная Swagger UI](http://localhost:3000/api/docs) В development доступна [локальная Swagger UI](http://localhost:3000/api/docs)
при стандартном порте API. Она показывает контракт, но не доказывает доступность при стандартном порте API. Она показывает контракт, но не доказывает доступность
@@ -96,7 +112,7 @@ backend при сохранении расширенной схемы. Стар
| --- | --- | | --- | --- |
| Порт занят | Адрес действующего процесса или выбранный свободный порт должен совпадать с настройками клиента и разрешённым origin | | Порт занят | Адрес действующего процесса или выбранный свободный порт должен совпадать с настройками клиента и разрешённым origin |
| Ошибка CORS или сессия теряется после reload | Согласованность адресов, hostname и режима cookie проверяется на стороне browser и backend | | Ошибка CORS или сессия теряется после reload | Согласованность адресов, hostname и режима cookie проверяется на стороне browser и backend |
| Ошибка подготовки базы | Установленный blocker не устраняется удалением пользовательской базы или обходом миграций; сохраняются версия среды и текст ошибки | | Ошибка подготовки базы | Сохранить версию среды и текст ошибки; использовать backend Prisma config, не удалять пользовательскую базу и не обходить migrations |
| `TBANK_NOT_CONNECTED` | Подключение создаётся в настройках текущего пользователя | | `TBANK_NOT_CONNECTED` | Подключение создаётся в настройках текущего пользователя |
| `INVALID_TBANK_TOKEN` | После проверки token и прав у брокера подключение заменяется через настройки | | `INVALID_TBANK_TOKEN` | После проверки token и прав у брокера подключение заменяется через настройки |
| `TBANK_UNAVAILABLE`, TLS или rate limit | Проверяются сеть, лимиты и доверенный CA; проверка TLS сохраняется | | `TBANK_UNAVAILABLE`, TLS или rate limit | Проверяются сеть, лимиты и доверенный CA; проверка TLS сохраняется |
+6 -4
View File
@@ -34,8 +34,10 @@ API не требует нового описания контракта.
HTTP-потока. Согласованность описаний и функциональная корректность — HTTP-потока. Согласованность описаний и функциональная корректность —
разные доказательства. разные доказательства.
## Ограничение e2e ## Граница e2e
Сравнение OpenAPI не запускает сквозные проверки с миграциями базы. `npm run test:openapi-contract` подготавливает отдельную временную SQLite-базу
Известная ошибка движка миграций и условие пересмотра описаны в через общий runner и выполняет только сравнение OpenAPI. Соседний frontend
[сквозной проверке](verification.md#известное-ограничение-сквозной-проверки). checkout нужен для snapshot. Полные HTTP-сценарии запускает `test:e2e`;
миграция перед сравнением не подменяет проверку поведения приложения.
Подробности — в [сквозной проверке](verification.md#известное-ограничение-сквозной-проверки).
+19 -20
View File
@@ -33,28 +33,27 @@
### Известное ограничение сквозной проверки ### Известное ограничение сквозной проверки
В сохранённой проверке Prisma 7.9.1 под Node 22 применение миграций к новой Прежний blocker WL-P2-05 снят в конфигурации Prisma: на Node 22.21.0 /
SQLite-базе завершалось `Schema engine error` до запуска сквозных тестов. Prisma 7.9.1 унаследованный `RUST_LOG=warn` или `error` воспроизводит пустой
Это ограничение зафиксировано в [WL-P2-05](audit-remediation.md#p2). `Schema engine error`, а отсутствие переменной позволяет fresh migration.
Предыдущее описание локальной проверки от 12 сентября 2026 года также отмечало Backend Prisma config удаляет переменную в процессе CLI после загрузки `.env`;
ошибку на временной базе без обращения к пользовательской базе. это не меняет application logging. Версии зависимостей и SQL history сохранены.
Успех unit-проверок и OpenAPI не закрывает эту границу. Условие проверки — `npm run test:e2e` применяет migrations и запускает каждую HTTP suite на отдельной
стабильная версия Prisma с тремя последовательными успешными применениями временной DB. Один URL передаётся Prisma и Jest; прямой запуск Jest без runner
миграций на новых базах под Node 22. отклоняется до DB-запросов. При ошибке и SIGINT/SIGTERM выполняется cleanup.
`npm run test:sqlite` выбирает auth/cards; `test:durability` отдельно проверяет
migration, restart, возврат предыдущего приложения и backup/restore.
Команды и runnable regression — в
[backend README](../../backend/README.md#реальная-sqlite-и-сохранность-данных),
фактические результаты — в
[registry](audit-remediation.md#2026-09-13--wl-p2-05-воспроизводимый-sqlite-e2e).
При реализации ручных карт Prisma 7.9.1 на Node 22.21.0 трижды подряд применил Backend `verify` остаётся статическим/unit/build gate; полный HTTP/DB scope
существующие migrations к новым временным базам командой проверяется отдельным `test:e2e`. Успех этих команд не подтверждает доступность
`RUST_LOG=info DATABASE_URL=file:<новая-временная-база> npx prisma migrate deploy` внешнего T-Bank. HTTP tests требуют локальных портов, которые sandbox может
вне sandbox. Без `RUST_LOG=info` пустой `Schema engine error` воспроизводился запрещать. Безопасное сохранение реальных данных — в
и вне sandbox. Поэтому подтверждён именно этот способ запуска; исправление [локальном окружении](local-workspace.md).
обычного запуска или причина зависимости от журналирования не установлены.
Он использует штатную историю migrations без `db push`, reset или ручного SQL-обхода.
Результат исходной проверки сохранён в
[Tasks ручных карт](../../specs/openspec/changes/add-manual-bank-cards/tasks.md).
Применение новой миграции, DB-инварианты и HTTP-сценарии требуют своих проверок.
Условия безопасного локального запуска и сохранения данных —
в [локальном окружении](local-workspace.md).
## Где выполнять проверки ## Где выполнять проверки
+4 -2
View File
@@ -136,7 +136,9 @@ HTML-источник, общий кэш и поведение при измен
и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md) и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md)
описывают исходные финансовые понятия. Отдельная основная спецификация описывают исходные финансовые понятия. Отдельная основная спецификация
страницы облигации в текущем OpenSpec Store не найдена; условия вычислений страницы облигации в текущем OpenSpec Store не найдена; условия вычислений
подтверждены [сервисом облигаций](../../../backend/src/tbank/bond.service.ts) подтверждены [каталогом](../../../backend/src/modules/investments/instruments/bonds/application/bond-catalog.service.ts),
и его [проверками](../../../backend/src/tbank/bond.service.spec.ts). [рыночными данными](../../../backend/src/modules/investments/instruments/bonds/application/bond-market.service.ts),
[выплатами](../../../backend/src/modules/investments/instruments/bonds/application/bond-income.service.ts)
и [проверками](../../../backend/src/modules/investments/instruments/bonds/application/bond.spec.ts).
Границы источников описаны в [разделе интеграций](../../integrations/README.md), Границы источников описаны в [разделе интеграций](../../integrations/README.md),
сходное разделение рыночных и личных данных — в [акциях](stocks.md). сходное разделение рыночных и личных данных — в [акциях](stocks.md).
+3 -2
View File
@@ -173,6 +173,7 @@ TTM означает последние 12 месяцев, MRQ — послед
и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md) и [журнала](../../../specs/openspec/specs/brokerage-account-ledger/spec.md)
задают исходные финансовые понятия. Отдельная основная спецификация страницы задают исходные финансовые понятия. Отдельная основная спецификация страницы
акции в текущем OpenSpec Store не найдена; описанные механизмы проверяются акции в текущем OpenSpec Store не найдена; описанные механизмы проверяются
по [сервису акций](../../../backend/src/tbank/stock.service.ts) и его по [каталогу](../../../backend/src/modules/investments/instruments/stocks/application/stock-catalog.service.ts),
[проверкам](../../../backend/src/tbank/stock.service.spec.ts). [рыночным данным](../../../backend/src/modules/investments/instruments/stocks/application/stock-market.service.ts),
[выплатам](../../../backend/src/modules/investments/instruments/stocks/application/stock-income.service.ts) и [проверкам](../../../backend/src/modules/investments/instruments/stocks/application/stock.spec.ts).
Сопоставление с облигациями — на [странице облигаций](bonds.md). Сопоставление с облигациями — на [странице облигаций](bonds.md).
+1 -1
View File
@@ -114,6 +114,6 @@ Backend публикует статические маршруты под `/api/
[дохода](../../../specs/openspec/specs/brokerage-account-income-analytics/spec.md) [дохода](../../../specs/openspec/specs/brokerage-account-income-analytics/spec.md)
и [событий](../../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md) и [событий](../../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md)
описывают отдельный счёт. Общий режим подтверждён действующими маршрутизаторами, описывают отдельный счёт. Общий режим подтверждён действующими маршрутизаторами,
сервисами и [проверками агрегации](../../../backend/src/tbank/all-accounts.spec.ts), сервисами и [проверками агрегации](../../../backend/src/modules/investments/all-accounts.spec.ts),
но не выделен в самостоятельную основную спецификацию. Не следует считать но не выделен в самостоятельную основную спецификацию. Не следует считать
описание общего режима изменением требований к отдельному счёту. описание общего режима изменением требований к отдельному счёту.
+2 -2
View File
@@ -79,8 +79,8 @@ sequenceDiagram
| Метаданные инструмента | Успешный поиск или подтверждённое отсутствие | Свежими считаются 24 часа; общий кэш на 500 ключей UID/FIGI, ошибки не сохраняются | | Метаданные инструмента | Успешный поиск или подтверждённое отсутствие | Свежими считаются 24 часа; общий кэш на 500 ключей UID/FIGI, ошибки не сохраняются |
Это параметры текущей реализации, а не самостоятельная политика этого Это параметры текущей реализации, а не самостоятельная политика этого
документа: [снимки](../../../../backend/src/tbank/portfolio.service.ts), документа: [снимки](../../../../backend/src/modules/investments/portfolio/application/portfolio.service.ts),
[метаданные](../../../../backend/src/tbank/instrument-metadata.service.ts) и [метаданные](../../../../backend/src/integrations/tbank/instrument-metadata.service.ts) и
[клиентский запрос](../../../../frontend/src/entities/portfolio/api/usePortfolio.ts). [клиентский запрос](../../../../frontend/src/entities/portfolio/api/usePortfolio.ts).
Пять минут — предельный возраст успешного снимка, а не дополнительные Пять минут — предельный возраст успешного снимка, а не дополнительные
@@ -43,9 +43,9 @@
и реализации. и реализации.
Для адресной проверки исходников владельцами служат Для адресной проверки исходников владельцами служат
[сервис снимков](../../../../backend/src/tbank/portfolio.service.ts), [сервис снимков](../../../../backend/src/modules/investments/portfolio/application/portfolio.service.ts),
[валютные итоги](../../../../backend/src/tbank/portfolio-totals.ts), [валютные итоги](../../../../backend/src/modules/investments/portfolio/infrastructure/tbank-portfolio.mapper.ts),
[структура](../../../../backend/src/tbank/portfolio-structure.ts) и [структура](../../../../backend/src/modules/investments/portfolio/domain/portfolio-structure.ts) и
[подготовка экрана](../../../../frontend/src/pages/account/ui/AccountPage.vm.ts). [подготовка экрана](../../../../frontend/src/pages/account/ui/AccountPage.vm.ts).
Это точки продолжения расследования; смысл вычислений изложен выше. Это точки продолжения расследования; смысл вычислений изложен выше.
+1 -1
View File
@@ -50,4 +50,4 @@ HTTP-запрос ограничен таймаутом. Сеть, неуспе
Условия обработки источника в прогнозе закреплены в Условия обработки источника в прогнозе закреплены в
[спецификации будущих событий](../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md#requirement-upcoming-events-use-complete-source-results). [спецификации будущих событий](../../specs/openspec/specs/brokerage-account-upcoming-events/spec.md#requirement-upcoming-events-use-complete-source-results).
Точный механизм транспорта, разбора и сопоставления реализован в Точный механизм транспорта, разбора и сопоставления реализован в
[клиенте MOEX](../../backend/src/tbank/moex.client.ts). [клиенте MOEX](../../backend/src/integrations/moex/moex.client.ts).
+1 -1
View File
@@ -36,7 +36,7 @@ ISIN, даты и ссылки на выпуск. Изменение табли
После ошибки новая загрузка ограничена минутным интервалом; внутри одного После ошибки новая загрузка ограничена минутным интервалом; внутри одного
HTTP-запроса повторных попыток нет. Обновление запускается следующим обращением HTTP-запроса повторных попыток нет. Обновление запускается следующим обращением
после истечения кэша, без фонового задания. Точный механизм и сроки принадлежат после истечения кэша, без фонового задания. Точный механизм и сроки принадлежат
[клиенту НКР](../../backend/src/tbank/ncr-ratings.client.ts). [клиенту НКР](../../backend/src/integrations/ncr/ncr-ratings.client.ts).
При отказе реестра показатели облигации отмечают недоступность рейтинга, При отказе реестра показатели облигации отмечают недоступность рейтинга,
сохраняя остальные доступные показатели. Готовый ответ метрик имеет сохраняя остальные доступные показатели. Готовый ответ метрик имеет
+1 -1
View File
@@ -139,7 +139,7 @@ Backend хранит token в шифротексте AES-256-GCM с новым n
отсутствие инструмента, а не временный сбой. Остальные RPC при полной отсутствие инструмента, а не временный сбой. Остальные RPC при полной
очереди завершаются сразу. очереди завершаются сразу.
Параметры попыток принадлежат Параметры попыток принадлежат
[T-Bank client](../../backend/src/tbank/tbank.client.ts) (workspace-ссылка); [T-Bank client](../../backend/src/integrations/tbank/tbank.client.ts) (workspace-ссылка);
решение об ограниченных повторах — [ADR 005](../adr/005-tbank-upstream-resilience.md). решение об ограниченных повторах — [ADR 005](../adr/005-tbank-upstream-resilience.md).
Большое число ранее неизвестных инструментов требует отдельных запросов Большое число ранее неизвестных инструментов требует отдельных запросов
+1 -1
View File
@@ -12,7 +12,7 @@
"markdownlint-rule-relative-links": "5.1.2" "markdownlint-rule-relative-links": "5.1.2"
}, },
"engines": { "engines": {
"node": "22.x" "node": "24.x"
} }
}, },
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"engines": { "engines": {
"node": "22.x" "node": "24.x"
}, },
"scripts": { "scripts": {
"lint": "markdownlint-cli2 \"**/*.md\" \"#node_modules\"", "lint": "markdownlint-cli2 \"**/*.md\" \"#node_modules\"",