Skip to content

chore: refresh dependencies and project tooling - #487

Merged
gabitoesmiapodo merged 17 commits into
developfrom
chore/dependency-and-tooling-refresh
Sep 17, 2026
Merged

gabitoesmiapodo merged 17 commits into
developfrom
chore/dependency-and-tooling-refresh

Conversation

@gabitoesmiapodo

Copy link
Copy Markdown
Collaborator

Summary

Closes #484
Closes #482

Brings the dependency tree current. CI only validated the PR title until now, so this also gives the repo a pipeline that runs the real checks.

Changes

  • Every dependency moves to its latest usable version, pnpm 10 to 12
  • The Node floor is declared and refused at install time
  • TanStack router packages move past the compromised versions
  • Pull requests run biome, typecheck, build, knip, tests on two Node versions, commitlint and a full gitleaks history scan
  • gitleaks scans staged changes on commit and outgoing commits on push
  • knip reports files, exports and dependencies nothing reaches
  • Renovate proposes batched weekly updates once its GitHub App is installed
  • The docs site runs on vocs 2 and deploys through Vercel's Build Output API
  • Token balances go through the LI.FI v4 client API
  • SDLC starter kit updated to v2026.09

Deviations

  • Most of this had no issue; it was asked for as one maintenance sweep
  • .nvmrc names 24.21.0, not the 24.15.0 floor, matching canton-dappbooster
  • The patched TanStack versions the advisory named were never published, so the ranges floor above the bad window instead
  • wagmi stays on 2, graphql on 16, TypeScript on 6 -- each blocked by a dependency, each held in Renovate with its reason
  • conventional-commits-PR-title.yml is gone; commitlint validates the title now, so the type and scope labels it added are gone too
  • Dropped @web3icons/core, ts-node, an unused Chakra tooltip and a dead docs footer
  • pnpm build generates the contract hooks first, because a cached install skips postinstall and broke the Vercel deploy

Acceptance criteria

  • package.json declares engines.node as >=24.15.0
  • .nvmrc names the same version
  • Starting the project on an older Node reports the requirement
  • CI runs on that version
  • Bump direct deps in package.json to the patched releases (or higher)
  • Regenerate pnpm-lock.yaml and confirm no transitive @tanstack/* version falls in a vulnerable range
  • Run pnpm wagmi-generate, pnpm routes:generate, pnpm lint, pnpm test, and pnpm build to confirm the bump is non-breaking
  • Once the GHSA-listed patched versions land on npm, replace the exact pins with caret ranges floored above the malicious window

Test plan

Automated tests

1. Run `pnpm install`
2. Run `pnpm lint`, `pnpm typecheck`, `pnpm test` and `pnpm knip`
3. Expect 213 passing tests and no findings

Manual verification

1. Check out this branch and run `pnpm install`
2. Run `pnpm dev` and open http://localhost:5173
3. Open the Token dropdown demo and pick a token
4. Click Connect and check the wallet list appears
5. Run `pnpm docs:build`, then `pnpm docs:preview`, and open http://localhost:4173
6. Expect the docs site to render and its deep links to resolve

Breaking changes

For projects tracking this template: lifiConfig is now lifiClient, styles.ts files no longer export styles by name, and vocs.config.ts moved into docs/.

Checklist

  • Self-reviewed my own diff
  • Tests added or updated
  • Docs updated (if applicable)
  • No unrelated changes bundled in

Screenshots

None.

Until now the only hint at a Node version was `.nvmrc`, which nothing reads
at install time. Anyone on an older Node hit a confusing failure later
instead of being told up front.

- `package.json` declares `engines.node` as `>=24.15.0`, the same floor
  canton-dappbooster and the installer use
- `.nvmrc` names 24.21.0, the version we develop and test on
- `pnpm-workspace.yaml` sets `engineStrict: true`, so `pnpm install` stops
  with a clear message on an older Node
- README, docs and CLAUDE.md say 24.15.0 instead of the stale v20

Refs #484
pnpm 10 to 12. Two settings had to move, because pnpm 12 stopped reading them
where they were:

- `onlyBuiltDependencies` in pnpm-workspace.yaml is now `allowBuilds`, a map of
  package name to true or false
- the `pnpm.overrides` block in package.json is now `overrides` in
  pnpm-workspace.yaml; without the move the @graphql-codegen/cli override was
  silently dropped and we installed two copies

pnpm now tracks its own version in the lockfile, which is where the new
`@pnpm/exe.*` entries come from.
The npm supply-chain attack on @tanstack/* left these four pinned to exact
versions just below the malicious window, so a fresh resolve could not drift
into it. The versions the advisory named as patched were never published, but
the registry has since moved well past the bad range, so the pins are no longer
needed.

- `@tanstack/react-router` -> `^1.170.36`
- `@tanstack/react-router-devtools` -> `^1.167.2`
- `@tanstack/router-cli` -> `^1.167.36`
- `@tanstack/router-plugin` -> `^1.168.38`

Each floor sits above every version the advisory listed, and the regenerated
lockfile resolves every transitive `@tanstack/*` package above its bad range
too. Routes generate, lint, tests and build all pass.

Closes #482
Everything moves to the newest release that its existing range allows, plus
react, react-dom and biome, which are pinned exactly and were bumped by hand.

Two knock-on fixes:

- `@reown/appkit-adapter-wagmi` and `porto` leave `@wagmi/core` and
  `@wagmi/connectors` as open peers, so pnpm filled them with 3.x and 8.x
  while wagmi 2 ships 2.x and 6.x. That gave two copies of the connector
  registry, a type error at `createConfig` and a build that could not resolve
  `@wagmi/core/tempo`. pnpm-workspace.yaml now holds both to the pair wagmi 2
  ships.
- biome 2.5 reads SVG files, which the repo's logos and favicons all fail on
  aesthetic grounds. biome.json excludes `*.svg` and turns on `ignoreUnknown`,
  matching canton-dappbooster. One real finding, a redundant `!!` in
  TokenSelect, is fixed.
- commitlint 20 to 21
- @graphql-codegen/cli 6 to 7
- @testing-library/jest-dom 6 to 7
- @uniswap/default-token-list 18 to 22
- jsdom 29 to 30
- lint-staged 16 to 17
- vitest and @vitest/coverage-v8 4 to 5

graphql-codegen 7 stopped falling back to `any` for scalars it has no mapping
for, so every subgraph `id`, `Bytes` and `BigInt` came out as `unknown` and
three call sites stopped compiling. `src/subgraphs/codegen.ts` now names the
scalar types The Graph uses, which is what the generated code always meant.

graphql itself stays on 16: @bootnodedev/db-subgraph asks for ^16, and a second
copy of graphql in the tree breaks schema identity checks at runtime.
Version 4 splits the SDK in two. The global `createConfig` is gone: you now
build a client with `createClient` and hand it to every action as its first
argument. The EVM provider moved out of the core package into
`@lifi/sdk-provider-ethereum`, where `EVM()` is now `EthereumProvider()`.

`useTokens` follows: `lifiConfig` becomes `lifiClient`, and `getChains`,
`getTokens` and `getTokenBalances` all take it.
@gabitoesmiapodo gabitoesmiapodo self-assigned this Sep 17, 2026
@vercel

vercel Bot commented Sep 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
components.dappbooster Ready Ready Preview Sep 17, 2026 2:25pm UTC
demo.dappbooster Ready Ready Preview Sep 17, 2026 2:25pm UTC
docs.dappbooster Ready Ready Preview Sep 17, 2026 2:25pm UTC

Request Review

Vocs 2 is a rewrite on top of Waku and React Server Components, so the docs
setup had to move with it:

- `vocs.config.ts` lives in `docs/` now and the `docs:*` scripts run from
  there. Vocs 2 always uses the working directory as its root and ignores the
  `rootDir` you give it, so run from the repo root it treated the whole dApp
  as its source and failed to bundle it.
- the config imports `defineConfig` from `vocs/config`. The `vocs` root entry
  now pulls in React components that only resolve inside Vite.
- `srcDir: '.'` keeps pages at `docs/pages`, and `renderStrategy:
  'full-static'` keeps the output a static site. Vocs 2 defaults to a dynamic
  server build.
- `waku` is a new dev dependency. Vocs declares it optional but its build
  fails without it.

The built site moves from `docs/dist` to `docs/dist/public`, so whoever owns
the docs deployment has to update the output directory.
gitleaks now runs in three places, all on the same pinned version so local and
CI agree:

- `scripts/install-gitleaks.sh` downloads the version named in
  `.gitleaks-version` into `bin/`, checks its sha256, and does nothing if it is
  already there
- pre-commit scans the staged changes
- pre-push scans the commits being pushed, so a bypassed pre-commit still gets
  caught

The pre-push scan resolves its range carefully. A remote sha the local repo
does not have, after a teammate force-push or a fetch that never happened,
would otherwise make gitleaks scan zero commits and pass. It falls back to
everything not already on the remote being pushed to, and refuses the push if
the range still will not resolve.

A full history scan turns up one hit: the Anvil test account private key in a
test file on an old branch. It is a published key, so `.gitleaksignore` records
it.

While in the hooks:

- dropped the `#!/bin/sh` lines husky 9 warns about and husky 10 rejects
- lint-staged runs in two passes. The formatter writes files that the test run
  reads, and lint-staged runs globs concurrently, so one pass let a rewrite
  land mid-read. `.lintstagedrc.format.mjs` writes, `.lintstagedrc.mjs` reads.
- the formatter pass covers every file biome handles, not just `src/`
- pre-push calls the new `typecheck` script instead of a long inline `tsc`.
  `tsconfig.json` sets `incremental`, so that stays as fast as the old inline
  command and `pnpm build` and CI get it too.
`pnpm knip` reports files, exports and dependencies nothing reaches.

The config treats the template's public surface as entry points, because that
is what it is for: shared components, hooks, the wagmi CLI config and the
alternative wallet configs are all meant to be unused until a project picks
them up.

What it found, and what was done about it:

- dropped `@web3icons/core` and `ts-node`, neither of which anything imports
- added `@graphql-codegen/client-preset`, which the subgraph codegen loads by
  name through `preset: 'client'` and only resolved by luck
- deleted `src/components/ui/tooltip.tsx`, a Chakra snippet nothing used
- deleted `docs/footer.tsx`. Vocs has no footer setting and the component's
  text never reaches the built site.
- 19 `styles.ts` files exported `styles` both by name and as the default, and
  every importer used the default. The named half is gone.

`@rainbow-me/rainbowkit`, `@graphql-typed-document-node/core` and `buffer` are
in `ignoreDependencies`: the first two are reached from commented-out and
generated code, the third through a vite alias.

Unused exports, unused types and duplicate named/default exports are warnings,
not errors. What is left is components and helpers the template offers on
purpose, plus the `export const X` / `export default X` pair they use.
Until now CI only validated the PR title. A pull request could land with a
broken build, failing tests or a leaked secret.

`pr.yml` adds, in the same shape canton-dappbooster uses:

- biome
- typecheck, build, knip, typedoc and the docs site
- tests on the Node in `.nvmrc` and again on Node 26
- commitlint over both the PR commits and the PR title
- a gitleaks scan of the full history

Every action is pinned to a commit, not a tag.

The typecheck job needs the subgraph types, which are generated and not
committed, so it runs `pnpm subgraph-codegen` first and is skipped for pull
requests from forks, which get no secrets. The other jobs run everywhere.

Two workflows go away:

- `pr-self-assign.yml` is replaced by `pr-assign.yml`, which skips fork and bot
  authors instead of failing on them
- `conventional-commits-PR-title.yml` is replaced by the commitlint job, so the
  rules come from `commitlint.config.js` instead of a second list inside a
  third-party action. The type and scope labels it used to add are gone.
Renovate opens one batched pull request a week for minor and patch updates and
a separate one per major. Releases have to be three days old before it will
propose them, so a compromised publish has time to be pulled first. Nothing
auto-merges.

Three majors are held back, each with the reason in the config:

- wagmi, because connectkit and rainbowkit have no wagmi 3 release
- graphql, because @bootnodedev/db-subgraph asks for ^16
- typescript, because typedoc cannot run on the Go-native compiler

GitHub Actions are pinned to commit digests and Renovate keeps them current.

The file does nothing until the Renovate GitHub App is installed on the repo.
- the issue skill is now `create-issue`, matching the name the kit ships and
  the `/sdlc:create-issue` reference in CLAUDE.md
- the create-pr skill and its two helper scripts are refreshed
- the PR template gains a Deviations section, for anything a reviewer would
  read as a surprise, and shorter prompts in the rest
- the bug template keeps the repo's Node 24 example instead of the kit's 22
- CLAUDE.md carries the version stamp, so `head -n1 CLAUDE.md` says which
  release it came from

AGENTS.md and the other issue templates were already current.
CLAUDE.md:

- pnpm 12, and the Node floor is now enforced at install time
- the git hooks section describes what they actually run: two lint-staged
  passes and gitleaks on pre-commit, typecheck and gitleaks on pre-push
- new sections for the dependency holds, gitleaks and knip
- the validation checklist gains `pnpm typecheck` and `pnpm knip`, and says
  what CI runs

architecture.md:

- the tech stack table lists knip, gitleaks, Renovate, vocs, typedoc and pnpm
- the tree shows `docs/`, `scripts/` and the workflows
- the scripts table is complete again
- new sections for dependency resolution, with a table of the three overrides
  and why each exists, and for what CI runs

The stack page claimed the project uses SWC for fast refresh. It uses
`@vitejs/plugin-react`. The manual installation guide gains removal steps for
knip and Renovate, warns that dropping Husky also drops secret scanning, and
points at the files that actually exist now.
The script ran `routes:watch & vite`, and `routes:watch` is not a command, so
only Vite started and route files stopped regenerating on change.
Both were held with a caret, which widened the range wagmi itself chose: wagmi
2.19.5 depends on exactly 2.22.1 and 6.2.0. The override is there to dedupe the
tree, not to allow newer versions, so it now names those two exactly.

Renovate is told to leave both alone. They are not ours to bump; they move when
wagmi moves.

Verified on a clean resolve with no lockfile and no node_modules: without the
overrides pnpm installs @wagmi/core 2.22.1 and 3.6.5 side by side, and
@wagmi/connectors 6.2.0 and 8.2.0. With them, one of each.

This branch was successfully deployed

3 active deployments
Preview – docs.dappbooster 3e55b96f Deployed Sep 17, 2026 by vercel[bot]
Preview – demo.dappbooster 3e55b96f Deployed Sep 17, 2026 by vercel[bot]
Preview – components.dappbooster 3e55b96f Deployed Sep 17, 2026 by vercel[bot]
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.

Declare the Node version dAppBooster needs Update TanStack router packages to patched versions after npm supply-chain compromise

1 participant