Files

12 KiB
Raw Permalink Blame History

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

  1. Зафиксировать baseline assessments и выбрать outcome для каждого advisory.
  2. Выполнить согласованные dependency/lockfile updates или записать accepted/ deferred decision с review trigger.
  3. Перевести frontend configuration на .env.example + ignore policy; удалить tracked runtime inputs из index, сохранив локально воспроизводимый file через template.
  4. Удалить пустой backend runtime DB artifact, расширить ignore policy и проверить temporary DB location без касания production schema.
  5. Выполнить required gates и, только после archive, добавить terminal evidence в remediation registry. Rollback — независимый Git revert в затронутом repository; DB migration или user-data recovery не требуются.