12 KiB
Context
См. motivation в proposal.md. На старте change frontend напрямую использует
react-router@7.9.6; backend получает deepmerge-ts@7.1.5 транзитивно через
prisma@7.9.1 -> @prisma/config. Frontend одновременно хранит одинаковые
.env и .env.example, а backend хранит пустой tracked dev.db; текущий
backend ignore rule покрывает только prisma/*.db.
Каждый application directory — отдельный Git repository с собственным lockfile. Prisma 7.9.1 также является причиной deferred WL-P2-05, поэтому dependency change не может считать e2e gate восстановленным без отдельного подтверждения его review trigger.
Baseline 2026-08-24
| Область | Наблюдение |
|---|---|
| Frontend dependency | direct react-router@7.9.6 |
| Backend dependency path | prisma@7.9.1 -> @prisma/config@7.9.1 -> deepmerge-ts@7.1.5; @prisma/client и adapter также 7.9.1 |
| Frontend environment | .env и .env.example tracked с одинаковым content; local .env не игнорируется |
| Backend SQLite | пустой root dev.db tracked; ignore покрывает только prisma/*.db |
| Local URLs | development template направляет DB в prisma/dev.db; e2e config направляет её в /tmp/wealth-ledger-e2e.db |
Advisory assessment 2026-08-24
npm audit --omit=dev reproduces one high frontend finding and three high
backend findings. The direct frontend path is react-router@7.9.6.
GHSA-2w69-qvjg-hvjx affects React Router >=7.0.0, <=7.11.0 and is patched
in 7.12.0; npm identifies 7.18.2 as the current non-major version that
also resolves the broader audit result. WealthLedger uses only
declarative <BrowserRouter>, static internal Link targets and local
navigate calls. It has no loaders, actions, SSR, RSC, single-fetch or
prerendering surface. This removes the known preconditions for
GHSA-2w69-qvjg-hvjx, but does not justify retaining an old direct package:
the supported fixed version is compatible with Node 22 and React 19 and will
be adopted.
The backend findings resolve through
prisma@7.9.1 -> @prisma/config@7.9.1 -> deepmerge-ts@7.1.5.
GHSA-ggr8-5vv4-36mx affects deepmerge-ts <8.0.0 and is patched in 8.0.0.
Source code does not import @prisma/config or deepmerge-ts; the former is
used by the local Prisma CLI configuration, while runtime uses the generated
Prisma client and SQLite adapter. The vulnerability requires two
attacker-controlled recursive object graphs passed into deepmerge APIs, a path
absent from the delivered HTTP service. npm offers only a Prisma 6.12.0 major
downgrade and the published latest Prisma remains 7.9.1, so this change
accepts the tooling-only residual risk rather than forcing an unsupported
override.
Review trigger: a vendor-supported Prisma release for the 7.x integration
that resolves deepmerge-ts@>=8, or new evidence that public runtime input
reaches a deepmerge API.
Implemented dependency outcome
react-router is upgraded from 7.9.6 to 7.18.2, its current
non-major npm audit fix. The existing AppRoutes regression suite validates
the delivered declarative routing contract after the update, and the frontend
production dependency audit reports zero findings. The Prisma/deepmerge-ts
finding is accepted as tooling-only residual risk under the review trigger
above; no manifest, lockfile or runtime behavior is changed for it.
Implemented hygiene outcome
Each application repository exposes a non-mutating hygiene:check command.
The frontend check permits only tracked .env.example, requires local
.env* files to be ignored, and is part of npm run verify. The backend
check rejects tracked SQLite runtime files and verifies root/Prisma DB and
sidecar patterns without treating text fixtures as databases. The redundant
tracked frontend .env and empty backend root dev.db are removed; existing
documented URLs still create development data under ignored prisma/ and e2e
data under /tmp.
Application-gate evidence
Under Node v22.21.0 and npm 10.9.4, frontend npm run verify passes with
17 test files / 55 tests after the Router update. Backend npm ci,
hygiene:check, non-mutating lint, application/test typechecks and
npm test -- --runInBand pass with 19 suites / 59 tests. npm run test:e2e
still stops during prisma migrate deploy with the pre-existing empty
Schema engine error before Jest starts. This is recorded as the WL-P2-05
deferred outcome, not as a passing e2e result or evidence of a Prisma fix.
npm audit --omit=dev after the clean install reports zero frontend
production findings. Backend still reports three high findings in the exact
Prisma 7.9.1 path recorded above, with only a Prisma 6.12.0 major downgrade as
an automatic fix. OpenSpec authority, strict change validation, all synced
spec validation (16/16) and git diff --check in every affected repository
pass.
The remediation registry is updated with terminal evidence only after archive.
It is deliberately not a checkbox in tasks.md: the archive lifecycle
requires every task to be complete before archive, so post-archive bookkeeping
cannot also be an unfinished implementation task.
Goals / Non-Goals
Goals:
- Получить evidence-based решение по каждому high advisory, а не скрыть его массовым обновлением.
- Применить только минимальные поддерживаемые dependency updates и доказать их существующими non-mutating gates.
- Сделать local environment и SQLite artifacts непригодными для случайного commit, не ломая documented bootstrap.
Non-Goals:
- Автоматически обновлять все устаревшие packages, добавлять package manager
или вводить blanket
overridesбез vendor-supported compatibility path. - Менять HTTP/OpenAPI contract, Prisma schema/migrations, production data, T-Bank integration или обходить deferred Prisma e2e gate.
- Создавать CI/CD security scanner, secret-management service или хранить реальные секреты в versioned files.
Decisions
Каждый advisory проходит assessment до изменения manifest
Для WL-P2-12 сначала фиксируются исходные advisory metadata, installed path,
affected version range, runtime/build reachability и минимальный supported
fixed candidate. Затем выбирается один из outcomes: coordinated upgrade,
accepted risk или deferred risk с конкретным trigger. npm audit fix --force
не используется: он смешивает unrelated upgrades и не создаёт evidence
применимости.
Альтернатива — обновить все findings одной командой audit fix. Она отвергнута, потому что Prisma является источником отдельного e2e failure и semver-compatible разрешение не доказывает поведение Nest/Prisma integration.
Transitive Prisma finding обновляется только согласованной цепочкой
Если assessment требует remediation deepmerge-ts, change обновляет Prisma packages только в vendor-supported, lockstep-compatible наборе и проверяет фактический resolved graph после чистой установки. Точечный npm override транзитивного package допустим только если Prisma официально поддерживает этот диапазон; иначе finding остаётся документированным accepted/deferred risk.
Альтернатива — принудительно override-ить deepmerge-ts. Она отвергнута по
умолчанию, поскольку обходит ownership dependency chain и может скрыть
несовместимость Prisma tooling.
Templates versioned, рабочие значения local
Frontend сохраняет единственный versioned template .env.example; .env и
варианты .env.* игнорируются, кроме явно разрешённого example. При удалении
tracked .env его содержимое сначала сверяется с example, поэтому documented
cp .env.example .env остаётся воспроизводимым. Backend dev.db удаляется
только как пустой runtime artifact; ignore policy покрывает root и Prisma
SQLite locations, не затрагивая будущие намеренно versioned fixtures.
Альтернатива — оставить безопасный сегодня .env tracked. Она отвергнута:
Git policy должна предотвращать будущий commit с секретом, а не оценивать
только текущее значение.
Evidence собирается существующими gates
После каждой manifest/lockfile change выполняются npm ci, dependency graph и
relevant audit command в затронутом repository, затем существующие frontend
npm run verify и backend non-mutating lint/typecheck/unit-test gates. Любая
Prisma-related проверка отдельно сообщает исход migrate deploy; её failure
не маскируется и не переводит WL-P2-05/P2-13 в done.
Risks / Trade-offs
- [Минимальный fixed release меняет router behavior или peer resolution] → выполнить targeted route/auth regression tests и полный frontend verify до принятия lockfile.
- [Prisma update меняет schema-engine behavior или incompatibly разрешает adapter/client packages] → обновлять vendor-supported packages вместе, запускать generated/type/unit gates и сохранить фактический e2e outcome.
- [Ignore rule слишком широка и скрывает fixture] → покрыть только runtime DB patterns, проверить tracked files и явно оставить fixtures вне policy.
- [Удаление tracked
.envоставляет разработчика без config] → template и documented copy command проверяются до удаления tracked файла.
Migration Plan
- Зафиксировать baseline assessments и выбрать outcome для каждого advisory.
- Выполнить согласованные dependency/lockfile updates или записать accepted/ deferred decision с review trigger.
- Перевести frontend configuration на
.env.example+ ignore policy; удалить tracked runtime inputs из index, сохранив локально воспроизводимый file через template. - Удалить пустой backend runtime DB artifact, расширить ignore policy и проверить temporary DB location без касания production schema.
- Выполнить required gates и, только после archive, добавить terminal evidence в remediation registry. Rollback — независимый Git revert в затронутом repository; DB migration или user-data recovery не требуются.