From a7d0dd95e2b3385361bccecb8bbc46b990f8cee1 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 12 May 2026 17:23:19 +0200 Subject: [PATCH] =?UTF-8?q?audit:=20append=20Context7-assisted=20dependenc?= =?UTF-8?q?y=20upgrade=20analysis=20(=C2=A734)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Companion to the deps-auditor report. Per-major pros/cons informed by upstream changelogs queried via Context7. Sequencing: - Tier A (patches + esbuild minor) → do now - Zod 4 + @hookform/resolvers 5 → couple together, codemod-able - Next 15 → 16 (incl. middleware → proxy.ts rename) → 2-4 weeks - Tailwind 4 → afternoon project, visual review pages - Defer indefinitely: archiver 8 (failed last try), react-day-picker 10 Top-line baseline: 0 known vulns; no GPL/AGPL; lockfile reproducible. Everything below is dev-experience/perf, not security-blocker. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/AUDIT-2026-05-12.md | 198 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) diff --git a/docs/AUDIT-2026-05-12.md b/docs/AUDIT-2026-05-12.md index 01c9bba7..b6dffd08 100644 --- a/docs/AUDIT-2026-05-12.md +++ b/docs/AUDIT-2026-05-12.md @@ -6506,3 +6506,201 @@ No CDN / `s-maxage` fronts hot reads. Per-page avatar GET burns a presign + S3 r 4. **H1 + H2** port-binding plumbing (small refactor, big invariant). 5. **H3 + H4 + M2** streaming pass over backup + migrator + email attachments. 6. Remainder during next storage-config UI sweep. + +--- + +## 34. Dependency upgrade analysis — Context7-assisted (follow-up after deps-auditor) + +_Post-session follow-up. Where the original `deps-auditor` covered abandonment + vulnerabilities, this section queries upstream changelogs via Context7 to weigh the pros/cons of pulling every available major. Use this as your bump roadmap._ + +# Dependency upgrade analysis (Context7-assisted) + +Companion to the deps-auditor report from the original 33-agent run. +That auditor checked vulnerabilities + abandonment + license risk; this +follow-up adds **per-dep pros/cons of bumping to the latest stable**, +informed by upstream changelogs/docs queried via Context7. + +**Top-line baseline:** `pnpm audit` reports **0 known vulnerabilities**. +No GPL/AGPL contamination. Lockfile reproducible. We are safe TODAY +without any upgrade; everything below is "should we pull the next +major in?" prioritization. + +--- + +## At a glance — what's outdated + +| Package | Current | Latest | Bump size | +|---|---|---|---| +| `next` | 15.5.18 | 16.2.6 | major | +| `eslint-config-next` | 15.5.18 | 16.2.6 | major (matches next) | +| `zod` | 3.25.76 | 4.4.3 | major | +| `tailwindcss` | 3.4.19 | 4.3.0 | major | +| `@hookform/resolvers` | 3.10.0 | 5.2.2 | TWO majors | +| `archiver` | 7.0.1 | 8.0.0 | major | +| `react-day-picker` | 9.14.0 | 10.0.0 | major | +| `eslint` | 9.39.4 | 10.3.0 | major | +| `esbuild` | 0.27.7 | 0.28.0 | pre-1.0 minor (effectively major) | +| `@playwright/test` | 1.59.1 | 1.60.0 | minor | +| `libphonenumber-js` | 1.12.43 | 1.13.1 | minor | +| `tailwind-merge` | 3.5.0 | 3.6.0 | minor | +| `bullmq` | 5.76.6 | 5.76.8 | patch | +| `@tanstack/react-query` | 5.100.9 | 5.100.10 | patch | +| `better-auth` | 1.6.9 | 1.6.10 | patch | +| `vitest` | 4.1.5 | 4.1.6 | patch | +| `lint-staged` | 17.0.3 | 17.0.4 | patch | +| `@vitest/coverage-v8` | 4.1.5 | 4.1.6 | patch | + +`@types/node` deliberately pinned to ^20.19 to match Node 20 runtime +(audit findings — was previously ^25 against a Node 20 runtime, which +greenlit non-existent APIs). + +--- + +## Tier A — Pull the patches in now (zero-risk wins) + +`bullmq`, `@tanstack/react-query` + `react-query-devtools`, +`better-auth`, `vitest` + `@vitest/coverage-v8`, `lint-staged`, +`@playwright/test`, `libphonenumber-js`, `tailwind-merge`. + +**Pros:** patch / minor bumps, bug fixes only, no API changes documented. +**Cons:** none material — pin-bumps after a 30-second `pnpm install` +verify and full vitest run. +**Recommended:** **DO** as one batch commit. ~5 minutes. + +--- + +## Tier B — Per-major analysis + +### B-1 — Next.js 15.5 → 16.2 *(touches every API route + middleware)* + +**Upstream summary (via Context7):** + +- **`middleware.ts` is renamed to `proxy.ts`** in Next 16. The named export `middleware` → `proxy`. Config flags rename (`skipMiddlewareUrlNormalize` → `skipProxyUrlNormalize`). **Edge runtime is NOT supported in `proxy`** — if you need edge runtime you must keep `middleware.ts` (we already use the Node runtime, so this is just a rename for us). +- Async `cookies()` / `headers()` / `params` / `searchParams` was the Next-15 change; Next 16 hardens the warning into an error. We're already async-safe (CLAUDE.md confirms the upgrade landed). +- Automated codemod: `npx @next/codemod@canary upgrade latest` handles the rename + most boilerplate. + +**Risk for us:** +- `src/middleware.ts` rename is a 30-second edit; no semantic change for us because we don't depend on edge runtime. +- The Documenso webhook + websocket server custom-server path (`src/server.ts`) needs to be retested — Next 16 changed some internals around the custom-server contract. +- `eslint-config-next` must bump in lockstep (already at 15.5.18 → 16.2.6). +- Turbopack defaults shifted; our dev script (`next dev --turbopack -H 0.0.0.0`) needs a quick smoke run. + +**Recommended:** **WAIT 2-4 weeks.** Next 16 dropped recently; let the field's bug reports settle. Then run the codemod + a full playwright smoke. Effort: 1-2h. + +--- + +### B-2 — Zod 3 → 4 *(touches every validator file)* + +**Upstream summary (via Context7):** + +- Top-level format helpers — `z.email()` / `z.uuid()` / `z.url()` etc. replace `z.string().email()` / `.uuid()` / `.url()`. Old form is **deprecated** but still works. +- Error customization unified: `{ message: '...' }` → `{ error: '...' }`. Old form deprecated. +- `z.function()` API completely redesigned — now takes `input`/`output` schemas upfront, returns a function factory (not a schema). +- ~14× perf improvement on parse paths. +- TypeScript server perf improvement (generic-class-signature simplification). + +**Risk for us:** +- We have ~30 validator files using `z.string().email()` / `.uuid()` style and `{ message: '...' }` style throughout. Both still work in 4.x but produce deprecation warnings on every parse — noisy in logs. +- `@hookform/resolvers` v5 supports **both** Zod 3 and Zod 4 natively (auto-detects), so this couples cleanly with B-4 below. +- We don't use `z.function()` anywhere, so the biggest breaking change is a non-issue for us. + +**Recommended:** **GO once Tier A is in.** Codemod-friendly: a single Find/Replace pass on `z.string().email()` → `z.email()` etc. covers ~95% of the churn. Effort: 2-3h including running full vitest + writing replacement codemods. + +--- + +### B-3 — Tailwind CSS 3 → 4 *(touches `tailwind.config.ts`, `globals.css`, every dynamic-class site)* + +**Upstream summary (via Context7):** + +- **All-new Oxide engine** — 5× faster full builds, 100× faster incremental. +- **CSS-first config:** `tailwind.config.ts` is gone. Theme defined in `globals.css` via `@theme` + CSS custom properties (`--color-brand: …`). +- **PostCSS plugin consolidation:** `postcss.config.mjs` switches from `tailwindcss + autoprefixer + postcss-import` plugins to single `@tailwindcss/postcss`. +- Built on native cascade layers, OKLCH colors, container queries, `@starting-style`, popovers. +- Official automated upgrade tool: `npx @tailwindcss/upgrade` (requires Node 20+, which we already use). + +**Risk for us:** +- We have a custom `tailwind.config.ts` with brand tokens, CVA + tailwind-merge + clsx, plus the `tailwindcss-animate` plugin. The upgrade tool migrates most of this automatically; the manual review is the design-token spread across `globals.css`. +- shadcn/ui components (`components/ui/*`) use `cn()` + arbitrary values heavily. Some `[--variable]` syntax has changed in v4. +- `tailwindcss-animate` may not yet support v4 — need to confirm or swap for `tailwindcss-animated` (the v4 successor). + +**Recommended:** **HIGH-RISK / HIGH-REWARD.** Park until you have a clear afternoon. The build-time speedup is genuinely meaningful for dev experience. Run the official upgrade tool on a throwaway branch first; visually diff a handful of critical pages before merging. Effort: 3-4h on a focused day; visual regressions are the variable. + +--- + +### B-4 — `@hookform/resolvers` 3 → 5 *(touches every form file)* + +**Upstream summary (via Context7):** + +- v5 supports **both Zod 3 and Zod 4** simultaneously via auto-detection — pulls `zod/v4` if you opt into it explicitly. +- Resolver options shape is the same as v3 (`{ mode: 'async' | 'sync', raw?: boolean }`). +- v4 was a transitional version with the same external API; v5 is the stable cut. + +**Risk for us:** +- Coupled with the Zod 4 upgrade — if we stay on Zod 3, v5 still works (the resolver detects Zod-3 schemas via shape probing). Bumping resolvers without bumping Zod is safe. + +**Recommended:** **GO IN LOCKSTEP with B-2 (Zod 4).** Effort: 5 min once Zod 4 is in. + +--- + +### B-5 — `archiver` 7 → 8 *(touches GDPR-export bundle + backup-restore)* + +**Upstream summary:** Library "/gajus/archiver" not found in Context7 — fallback to npm changelog. We previously rolled back archiver@8 to archiver@7 (in commit `04a5949` per CLAUDE.md history) because of dropped default-export changes that broke our TS types. v8 stabilised since then. + +**Risk for us:** +- Last time we tried this it broke. Read the v8 changelog before retrying. +- Used only for GDPR export + backup-restore — narrow blast radius. A failed upgrade is non-customer-facing. + +**Recommended:** **DEFER.** Stay on 7 until either v8 demonstrably fixes a CVE / bug we care about, or until we have a green test suite to verify nothing regressed. Re-attempt only when there's a forcing function. + +--- + +### B-6 — `react-day-picker` 9 → 10 *(touches every date-picker site)* + +**Upstream summary:** v10 is a recent cut. Without Context7 returning a hit on its changelog, treat as "investigate before pulling". + +**Risk for us:** +- Used in ~6 surfaces (reminder form, EOI date fields, expense date, invoice due-date, dashboard date-range picker). A breaking change to the calendar render path would affect every form. + +**Recommended:** **DEFER 2-3 weeks** to let bug reports surface. Effort to actually do it: ~1h once the spec is reviewed. + +--- + +### B-7 — `eslint` 9 → 10 + `eslint-config-next` *(touches CI)* + +**Risk for us:** +- ESLint 10 likely drops support for some legacy rule configs. +- `eslint-config-next` should bump in lockstep with `next` (B-1). + +**Recommended:** **PAIR WITH B-1.** No standalone value to bumping eslint without bumping Next. + +--- + +### B-8 — `esbuild` 0.27 → 0.28 *(touches build pipeline)* + +**Risk for us:** +- We use esbuild via `pnpm.overrides` plus directly in `build:server` and `build:worker` scripts. +- Pre-1.0 minors at esbuild are typically very safe (Evan Wallace ships tight changelogs), but they do occasionally drop deprecated flags. + +**Recommended:** **GO.** Bundle the bump with the Tier A patches. Effort: 1 min + a `pnpm build` smoke. + +--- + +## Tier C — Things to leave alone + +- **`drizzle-orm 0.45.2`** — current major. No upgrade needed. +- **`react 19.2.6` / `react-dom 19.2.6`** — current React 19. Stable. +- **`@radix-ui/*`** — all current. These ship patch updates frequently; consider a quarterly sweep but not blocking. +- **`@dnd-kit/*`, `@pdfme/*`, `socket.io`, `bullmq`, `pino`, `postgres`, `minio`, `ioredis`, `pdf-lib`, `pdfkit`, `sharp`, `tesseract.js`, `recharts`, `cmdk`, `vaul`, `sonner`, `zustand`, `next-themes`, `date-fns`, `clsx`, `class-variance-authority`, `jose`, `nodemailer`, `mailparser`, `imapflow`, `openai`, `lucide-react`, `react-easy-crop`, `react-hook-form`** — all current within their major lines and either no risk-worthy bump available or already bumped. + +--- + +## Recommended sequencing + +1. **Now** — pull Tier A patches as one commit (~5 min). +2. **Now** — `esbuild` 0.27 → 0.28 in same commit. +3. **Next focused half-day** — Zod 4 + `@hookform/resolvers` v5 together. Coupled because resolvers v5 supports both. Codemod-able. +4. **2–4 weeks** — Next 15 → 16 + `eslint-config-next` 16 + `eslint` 10. Lockstep. Run `@next/codemod` first. +5. **When a tester-friendly afternoon opens up** — Tailwind 4 via the official upgrade tool, with visual review across critical pages. +6. **Defer indefinitely** — archiver 8, react-day-picker 10 (neither is delivering us anything we need). + +**Non-goal:** chasing the bleeding edge on every dep. The audit's baseline finding stands — we are secure today. These are mostly developer-experience and perf wins, not security blockers.