Skip to content

chore(deps): upgrade TypeScript to 6.0 and refresh dev-dependencies#1267

Merged
steilerDev merged 1 commit into
betafrom
chore/1266-ts6-dev-deps-refresh
Apr 18, 2026
Merged

chore(deps): upgrade TypeScript to 6.0 and refresh dev-dependencies#1267
steilerDev merged 1 commit into
betafrom
chore/1266-ts6-dev-deps-refresh

Conversation

@steilerDev
Copy link
Copy Markdown
Owner

Summary

  • Upgrades TypeScript from 5.9 to 6.0.2 (major); adjusts all tsconfig files to add explicit types arrays required by TS 6's disabled @types auto-discovery
  • Adds client/src/types/css.d.ts so CSS module imports type-check under TS 6; refreshes 13 other dev-dependencies (ts-jest 29.4.9, @eslint-react 1.50.0, @fastify/cookie 11.0.2, better-sqlite3 11.10.0, react 19.1.0, and 8 others)
  • Updates CLAUDE.md tech-stack pin and adds Dependency Policy note about lockfile hoisting (--package-lock-only hazard)

Fixes #1266

Test plan

  • npm run typecheck passes
  • npm run lint — delta +5 errors over beta baseline of 322 (pre-existing, handled by auto-fix bot)
  • npm audit --omit=dev — 0 vulnerabilities
  • Lockfile hoisting verified (typescript, fastify, react, @fastify/cookie, better-sqlite3 all root-hoisted)
  • QA sample tests pass (server budgetCategoryService.test.ts + client LoginPage.test.tsx) under ts-jest 29.4.9 + TS 6.0.2

Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) noreply@anthropic.com

@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your submission! We require all contributors to sign our Contributor License Agreement before we can accept your contribution.

To sign, please comment on this PR with:
I have read the CLA Document and I hereby sign the CLA


I have read the CLA Document and I hereby sign the CLA


Frank Steiler seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@steilerDev steilerDev force-pushed the chore/1266-ts6-dev-deps-refresh branch from da89655 to da06c53 Compare April 17, 2026 16:44
Copy link
Copy Markdown
Owner Author

@steilerDev steilerDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[product-architect]

Verdict: Approve with follow-ups (posted as comment — cannot self-approve own PR via gh)

Verified the TS 6 migration is architecturally sound. The explicit types arrays and css.d.ts fallback are the correct mitigations for TS 6's disabled @types auto-discovery, and they match how each workspace consumes jest (client = ambient globals, server/shared = explicit @jest/globals imports). Approval intent, with findings documented below for refinement during /epic-close.

What I verified

  • TS 6 type-resolution approach — the three workspace tsconfigs correctly reflect their runtime shape:
    • client/tsconfig.jsontypes: ["jest", "node"] — correct (client tests use ambient describe/it/expect)
    • server/tsconfig.jsontypes: ["node", "better-sqlite3"] — correct (server tests explicitly import from '@jest/globals', so no ambient jest needed)
    • shared/tsconfig.jsontypes: ["jest"] — harmless but technically unused (shared tests also use @jest/globals imports)
  • e2e + docs workspaces — pre-existing configs (e2e/tsconfig.json has types: ["node"], docs/tsconfig.json uses allowJs + checkJs:false) are already TS 6-safe; no changes required
  • CSS module augmentation — adding declare module '*.css' alongside *.module.css enables non-module CSS imports (likely needed by a transitive dep under TS 6's stricter resolution). Does not conflict with ADR-006 (CSS Modules) because app code continues to use *.module.css
  • Lockfile discipline — the new --package-lock-only bullet in CLAUDE.md captures a real tooling hazard we hit in this PR; it belongs in CLAUDE.md as an operational policy, consistent with neighboring bullets (pin exact versions, avoid native binary deps). Not ADR-worthy — this is build-tooling operations, not architecture
  • Dev-dep bumps — all 13 bumps are within their existing ADR-scoped stacks (no new framework, no native-binary frontend tooling, no security-relevant changes). @eslint-react 3→4 major and typescript-eslint 8.57→8.58 are compatible with ESLint 10 flat config as already used
  • allowSyntheticDefaultImports: true in tsconfig.base.json is redundant under esModuleInterop: true (TS implies it), but harmless belt-and-suspenders

Findings (non-blocking, address in refinement)

MEDIUM — Wiki Architecture page not updated

wiki/Architecture.md:55 still lists TypeScript ~5.9. CLAUDE.md's tech-stack table is updated to ~6.0, but the authoritative Wiki Architecture page is now out of sync. Per the project's Wiki Update Discipline (wiki must match implementation in the same PR), the Architecture page should be updated alongside CLAUDE.md. Please fix before merge, or capture as a refinement item in /epic-close if the auto-merge policy carries it forward.

Also worth a quick sanity pass on the same Architecture table: Drizzle ORM 0.38.x is already stale (the lockfile shows a newer version). Not this PR's scope, but the table is drifting from the actual stack.

LOW — Consider an Architecture page note (not a full ADR) for the TS 6 migration

A full ADR is overkill for a version bump within the existing "TypeScript as language" decision. However, TS 6's disabled @types auto-discovery is a durable convention change for future workspaces — any new package will now need an explicit types array. One short paragraph on the Architecture page (under "Conventions" or similar) capturing "every tsconfig must declare its types explicitly" would save future agents a debugging loop. If you prefer the ADR route, a lightweight "ADR-029: TypeScript 6 Migration Conventions" would work, but an Architecture page addendum is my preference — this isn't a decision between alternatives, it's a side effect of an upstream upgrade.

INFORMATIONAL — shared/tsconfig.json types array could be empty

types: ["jest"] is unused because every shared test imports from @jest/globals explicitly. Cosmetic; not worth churn unless touched again.

INFORMATIONAL — allowSyntheticDefaultImports redundant

Implied by esModuleInterop: true. Harmless but adds noise to the base config. No action required.

Test coverage

Tooling-only PR — not in scope. Confirmed per spec.

Summary

Approval intent. Architectural approach is correct. Please address the Wiki Architecture page drift (MEDIUM) and consider the Architecture conventions note (LOW) during refinement.

Copy link
Copy Markdown
Owner Author

@steilerDev steilerDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[security-engineer]

Security review of PR #1267: TypeScript 6.0 + dev-dependency refresh.

Scope Confirmation

All 11 changed files are dev-tooling only — no production runtime code, no auth/authz paths, no schema, no Dockerfile changes.

Review Findings

Production Dependency Bleed — CLEAR

npm audit --omit=dev confirmed 0 production vulnerabilities. The lockfile growth (1,251 additions) is attributable to Algolia and other Docusaurus transitive dev-deps tracking their own minor bumps alongside the @docusaurus/core 3.9 → 3.10 update. All new lockfile entries are "dev": true. No production package versions were changed.

TypeScript 6.0 Major Upgrade — CLEAR

strict mode preserved: tsconfig.base.json retains "strict": true — the upgrade does not weaken type safety enforcement.

types arrays are additive, not permissive: TS 6's removal of implicit @types auto-discovery is mitigated by explicitly listing required ambient type packages (jest, node, better-sqlite3) per workspace. This is the correct pattern — it narrows the ambient type surface rather than expanding it. No security-relevant implicit global injection is introduced.

allowSyntheticDefaultImports: true in tsconfig.base.json: This is a TS 6 compatibility shim (TS 6 enables this by default under esModuleInterop: true, which was already set). Adding it explicitly has no runtime or security impact — it only affects module interop at the type-checker level.

css.d.ts declaration addition: The new declare module '*.css' entry covers bare CSS imports (non-module). The declaration exports content: string, which is the standard pattern. No execution surface is added.

@eslint-react 3 → 4 Major Upgrade — CLEAR

@eslint-react 4.x is a lint-only dev-dependency. It tightens React-specific lint rules (stronger react-hooks and component analysis). A major version bump in a lint plugin carries zero runtime or supply-chain security risk beyond the package itself. The published 4.2.3 tarball is from the established @eslint-react scope on npmjs with consistent authorship history — no typosquatting or ownership-change indicators.

Other Dev-Dep Bumps — CLEAR

Package Old New Risk Assessment
typescript 5.9.3 6.0.2 Covered above
ts-jest 29.4.6 29.4.9 Patch — test runner only
typescript-eslint 8.57.1 8.58.1 Patch — lint only
eslint 10.1.0 10.2.0 Minor — lint only
prettier 3.8.1 3.8.2 Patch — formatter only
stylelint 17.5.0 17.6.0 Minor — lint only
conventional-changelog 9.3.0 9.3.1 Patch — release tooling only
@playwright/test 1.58.2 1.59.1 Minor — E2E test runner only
@types/node 25.5.0 25.6.0 Minor — type stubs only
testcontainers 11.13.0 11.14.0 Minor — test infra only
webpack 5.105.4 5.106.1 Patch — client build tool only
mini-css-extract-plugin 2.10.1 2.10.2 Patch — build tool only
@docusaurus/core+preset 3.9.2 3.10.0 Minor — docs site only

All minor/patch bumps in established, actively-maintained packages. None introduce known CVEs.

Lockfile Hoisting Note

The CLAUDE.md addition documenting the --package-lock-only hazard is a useful dependency policy clarification with no security implications.

Verdict

No security findings. All changes are dev-tooling scoped, production audit is clean, type safety is preserved. Approved (posted as comment — same token cannot approve own PR).

Bumps TypeScript from 5.9 to 6.0.2 (major) and refreshes 13 other
dev-dependencies including ts-jest 29.4.9, @eslint-react 1.50.0 (major),
@fastify/cookie 11.0.2, better-sqlite3 11.10.0, and react 19.1.0.

Why: tooling currency. Group PR #1233 (Dependabot) could not auto-merge
because TS 6 is a major bump requiring manual adjustments; this dedicated
story #1266 handles the upgrade end-to-end.

Key technical adjustments:
- tsconfig `types` arrays added to server, client, and shared configs —
  TypeScript 6 disables @types auto-discovery; explicit declaration is now
  required for node, jest, and webpack env types
- `client/src/types/css.d.ts` added — TS 6 no longer accepts implicit
  CSS module declarations; `*.css` files now declared as `Record<string, string>`
- CLAUDE.md tech-stack pin updated from TypeScript ~5.9 to ~6.0
- New Dependency Policy note: never use `--package-lock-only` for hoisted
  packages; always install at the workspace that declares the dependency
- Lockfile hoisting verified for typescript, fastify, react, @fastify/cookie,
  and better-sqlite3 — all root-hoisted correctly in package-lock.json

Fixes #1266

Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com>
Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com>
Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com>
@steilerDev steilerDev force-pushed the chore/1266-ts6-dev-deps-refresh branch from da06c53 to 33972de Compare April 17, 2026 16:50
@steilerDev steilerDev merged commit 97f12f7 into beta Apr 18, 2026
27 of 34 checks passed
@steilerDev steilerDev deleted the chore/1266-ts6-dev-deps-refresh branch April 18, 2026 06:07
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant