Skip to content

chore(deps): dependency sweep, security fix, and Dependabot grouping - #52

Merged
ByteMeBaby merged 5 commits into
mainfrom
chore/deps-sweep-2026-07
Aug 2, 2026
Merged

chore(deps): dependency sweep, security fix, and Dependabot grouping#52
ByteMeBaby merged 5 commits into
mainfrom
chore/deps-sweep-2026-07

Conversation

@ByteMeBaby

Copy link
Copy Markdown
Owner

Clears the open high-severity advisory, brings every patch/minor dependency current, and fixes the Dependabot config that was generating structurally broken update PRs. Supersedes #47, #48, #50, and #51, and repairs the lockfile damage from the already-merged #49.

Five commits, each independently verified, so any one can be reverted without taking the others.

What this changes

b9f7dd0 security, lockfile only. brace-expansion 5.0.7 -> 5.0.9, transitive through eslint > @eslint/config-array > minimatch. GHSA-mh99-v99m-4gvg, high: a crafted brace pattern expands without bound and crashes the process out of memory. Dev-only path, no runtime exposure. Kept separate so a revert of any bump below cannot silently take the security fix with it.

583135c react and react-dom to 19.2.8 in lockstep, plus @types/react 19.2.18 and @types/react-dom 19.2.4. packages/ui keeps its peer range at ^19.0.0.

0d2e0b8 the Radix set plus lucide. All six @radix-ui/* packages move together (react-tabs to 1.1.21), plus lucide-react 1.28.0. Net effect on the lockfile is a deletion of 260 lines, because collapsing duplicate internals outweighs the version bumps.

c6d89c4 dev tooling and API runtime. eslint 10.8.0, typescript-eslint 8.65.0, turbo 2.10.8, @playwright/test 1.62.1, vite 8.2.0, @vitejs/plugin-react 6.0.5, tsx 4.23.4, @types/node 26.1.2, @types/pg 8.20.3, hono 4.12.33, @hono/node-server 2.0.12. tooling/eslint-plugin keeps its eslint peer range at ^10.6.0.

ab404e0 Dependabot grouping. Groups react with react-dom and their types, groups @radix-ui/*, groups @tanstack/*, and groups remaining dev tooling for minor/patch only. Raises open-pull-requests-limit to 10.

Why not just merge the five PRs

Three of them were defective, and the defects came from the config rather than from bad luck.

#48 (react alone) would have failed pnpm test. Its lockfile pins react-dom@19.2.7(react@19.2.8). react-dom asserts exact version equality with react at module load and throws rather than warning, and the guard is compiled into the development client build that jsdom loads as well as every server build. Because react-dom@19.2.7 declares a peer of ^19.2.7, which 19.2.8 satisfies, pnpm reports no peer problem while the runtime contract is broken.

#49 (react-tabs alone) forked the shared Radix internals. Merging it left 12 internal packages at two versions each on main, including two copies of @radix-ui/react-slot (1.3.0 and 1.3.1) while packages/ui/src/components/button.tsx imports Slot directly. Nothing in the four gates detects this. 0d2e0b8 collapses them back to one version each. The other risk on that PR did not land: it was two commits behind and its lockfile predated the Tailwind v4 work, but git's text merge preserved all 50 tailwindcss entries.

#47 (eslint) did not actually fix the advisory the way a hand-applied bump would. eslint 10.8.0 still resolves @eslint/config-array 0.23.5 and minimatch 10.2.5, and minimatch declares brace-expansion: ^5.0.5, so editing the manifest and running pnpm install keeps the vulnerable 5.0.7 locked. Dependabot's lockfile only moved because it regenerates from scratch. Hence the explicit pnpm update in b9f7dd0.

Separately, the default open-pull-requests-limit of 5 was hiding the backlog: 27 packages were outdated while only 5 were visible.

Verification

  • pnpm audit: no known vulnerabilities.
  • All four gates pass uncached under TURBO_FORCE=true, and pnpm test:e2e passes.
  • Every one of the five commits passes pnpm install --frozen-lockfile, so no commit carries a lockfile out of sync with its manifests.
  • Zero react@19.2.7 references remain in the lockfile, and react-dom@19.2.8(react@19.2.8) is matched.
  • Every shared Radix internal resolves to exactly one version (12 checked before and after).
  • SSR smoke test, which no gate covers: the dev server returns 200 with real server-rendered HTML and logs (ssr) connected, with no Incompatible React versions error. This is the exact path chore(deps): bump react from 19.2.7 to 19.2.8 #48 would have broken.
  • apps/web/src/routeTree.gen.ts does not drift.

Held back

Majors and the SSR framework, each of which deserves its own verified change: @testing-library/jest-dom 7.0.0, typescript 7.0.2, jsdom 30.0.1, and the @tanstack/react-start and react-router bumps.

Note for whoever merges

Merging this closes #47, #48, #50, and #51 automatically. Do not merge #48 directly in the meantime; it would reintroduce the react/react-dom skew.

The @playwright/test bump needs newer browser binaries, so run pnpm exec playwright install chromium after pulling or pnpm test:e2e fails with a missing executable.

Move the transitive brace-expansion that eslint pulls in through minimatch
off 5.0.7, which carries GHSA-mh99-v99m-4gvg (high): a crafted brace pattern
expands without bound and crashes the process out of memory. Patched in
5.0.8. minimatch 10.2.5 already declares ^5.0.5, so this is an in-range
resolution refresh and needs no manifest change.

The pending eslint 10.8.0 bump does not fix this on its own. eslint 10.8.0
still resolves @eslint/config-array 0.23.5 and minimatch 10.2.5, so a plain
install would keep the vulnerable resolution.

- brace-expansion 5.0.7 -> 5.0.9 (transitive, via eslint and minimatch)

Dev-only path, no runtime exposure.

Verified locally: pnpm audit reports no known vulnerabilities, and build,
lint, typecheck, and test all pass.
react-dom asserts exact version equality with react at module load and
throws rather than warning, and the guard is compiled into the development
client build that jsdom loads as well as every server build. react-dom
19.2.7 declares a peer of ^19.2.7, which 19.2.8 satisfies, so pnpm reports
no peer problem while the runtime contract is broken.

Dependabot #48 proposed react alone and its lockfile pins
react-dom@19.2.7(react@19.2.8), so merging it would have failed the jsdom
tests and broken SSR. The @types packages move along because
@types/react-dom peers on @types/react.

packages/ui keeps its react and react-dom peerDependencies at ^19.0.0. That
range states what the package supports, not what it was last built against,
and narrowing it would falsely drop 19.0 and 19.1.

- react 19.2.7 -> 19.2.8 (apps/web, packages/ui)
- react-dom 19.2.7 -> 19.2.8 (apps/web, packages/ui)
- @types/react 19.2.17 -> 19.2.18 (apps/web, packages/ui)
- @types/react-dom 19.2.3 -> 19.2.4 (apps/web, packages/ui)

Supersedes Dependabot #48.

Verified locally: the lockfile carries no 19.2.7 reference, and build, lint,
typecheck, and test all pass.
Radix component packages share internal packages (react-primitive,
react-slot, react-context, react-presence, roving-focus, and others), so
bumping one in isolation forks those internals to two versions each. That is
what #49 did on its own: it took react-tabs to 1.1.19 and left 12 shared
internals at two versions apiece, including two copies of react-slot while
packages/ui imports Slot directly in button.tsx.

Moving the whole set to latest collapses every one of them back to a single
version, which is why this commit removes more lockfile lines than it adds.

- @radix-ui/react-avatar 1.2.2 -> 1.2.6 (packages/ui)
- @radix-ui/react-dialog 1.1.19 -> 1.1.23 (packages/ui)
- @radix-ui/react-dropdown-menu 2.1.20 -> 2.1.24 (packages/ui)
- @radix-ui/react-label 2.1.11 -> 2.1.15 (packages/ui)
- @radix-ui/react-slot 1.3.0 -> 1.3.3 (packages/ui)
- @radix-ui/react-tabs 1.1.19 -> 1.1.21 (packages/ui)
- lucide-react 1.25.0 -> 1.28.0 (packages/ui)

Verified locally: every shared Radix internal resolves to a single version,
and build, lint, typecheck, and test all pass.
All patch or minor, all inside the existing ranges. The eslint bump also
raises the tooling/eslint-plugin devDependency, but its peerDependency stays
at ^10.6.0: that range states the supported floor, which has not moved, and
the rules use only the stable Rule and RuleTester APIs. Dependabot #47
narrowed it to ^10.8.0, which would have dropped support the plugin still
has.

- eslint 10.6.0 -> 10.8.0 (root, tooling/eslint-plugin)
- typescript-eslint 8.63.0 -> 8.65.0 (root)
- turbo 2.10.4 -> 2.10.8 (root)
- @playwright/test 1.53.2 -> 1.62.1 (root)
- vite 8.1.5 -> 8.2.0 (apps/web)
- @vitejs/plugin-react 6.0.3 -> 6.0.5 (apps/web)
- tsx 4.23.0 -> 4.23.4 (apps/api, packages/db)
- @types/node 26.1.1 -> 26.1.2 (apps/api, packages/config, packages/db, tooling/eslint-plugin)
- @types/pg 8.20.0 -> 8.20.3 (packages/db)
- hono 4.12.30 -> 4.12.33 (apps/api)
- @hono/node-server 2.0.10 -> 2.0.12 (apps/api)

Supersedes Dependabot #47, #50, and #51. Holds back
@testing-library/jest-dom 7.0.0 (major) and the @tanstack/react-start and
react-router bumps, which need individually verified changes.

Verified locally: routeTree.gen.ts does not drift, and build, lint,
typecheck, and test all pass.
The stock config opened one PR per package, which produced two structurally
broken proposals: a react bump with no react-dom (they assert exact version
equality at runtime), and a single Radix component bump that would have
forked 15 shared internal packages. Grouping the packages that must move
together makes both defects impossible to generate.

The default open-pull-requests-limit of 5 also hid the backlog: 27 packages
were outdated while only 5 were visible. Raising it to 10 surfaces the rest.

Production dependencies outside the three groups keep arriving individually,
as does every major, so each still gets its own review.

Verified: the config parses and the catch-all dev-tooling group sorts last,
which matters because a dependency joins the first group it matches.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant