## 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 ``, 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 не требуются.