Skip to content

feat: bump zod 3.25 → 4.3#24

Merged
theagenticguy merged 1 commit into
mainfrom
feat/zod-4
Apr 23, 2026
Merged

feat: bump zod 3.25 → 4.3#24
theagenticguy merged 1 commit into
mainfrom
feat/zod-4

Conversation

@theagenticguy
Copy link
Copy Markdown
Owner

Summary

Closes #21. Much smaller migration than anticipated — the codebase never used the Zod 3 APIs that changed incompatibly in Zod 4.

  • zod: 3.25.764.3.6 in @opencodehub/mcp + @opencodehub/sarif
  • packages/sarif/src/schemas.ts: z.record(z.string())z.record(z.string(), z.string()) (Zod 4 requires an explicit key schema)

What we didn't have to touch

The issue flagged these as migration hazards — none of them apply:

  • .merge() — not used anywhere in the codebase (the one .merge() match in packages/cli/src/commands/setup.ts is a custom writer.merge, not Zod).
  • .partial() / .deepPartial() — not used.
  • z.coerce.* — not used.
  • z.string().email() / .url() — not used.
  • .format() / .flatten() on ZodError — not used.
  • .safeParse(x) / .parse(x) — both still return/throw the same shapes in Zod 4.

On .passthrough()

Used 11 times in packages/sarif/src/schemas.ts. It's deprecated in Zod 4 but still functional and is the smallest-diff migration path. A separate cleanup PR can migrate these to z.looseObject(...) or .loose() if we want.

Dep-tree note

zod@3.25.76 remains in the tree transitively via @graphty/algorithmspuptzod. Our direct deps are exclusively on 4.3.6; no source-level mixing. The two versions coexist harmlessly.

Test plan

  • pnpm -r build clean
  • pnpm -r exec tsc --noEmit clean
  • pnpm -r test952 pass / 0 fail
  • pnpm -F @opencodehub/sarif run validate-schema → 4 pass / 0 fail
  • biome ci . clean
  • bash scripts/check-banned-strings.sh clean
  • license-checker-rseidelsohn clean
  • CI: all jobs green on the PR
  • End-to-end smoke: MCP server list_repos / query / context / impact against live Claude Code client (recommend before merge; can't automate locally)

Follow-up (out of scope)

  • Migrate the 11 .passthrough() call sites to z.looseObject(...) when convenient.

Closes #21. Smaller migration than the issue anticipated because the
codebase never used the APIs that changed incompatibly (`.merge()`,
`.deepPartial()`, coerce, `.email()`/`.url()`, `.format()` on ZodError).

- zod: 3.25.76 → 4.3.6 in @opencodehub/mcp + @opencodehub/sarif
- sarif schemas: `z.record(z.string())` → `z.record(z.string(), z.string())`
  (Zod 4 drops the single-arg form and requires an explicit key schema)

`.passthrough()` is deprecated in Zod 4 but still functional and the
recommended smallest-diff path; all 11 SARIF call sites continue to work
against the Zod 4 runtime. A separate cleanup PR can migrate them to
`z.looseObject(...)` or `.loose()` if/when we want.

Zod 3.25.76 remains in the dep tree transitively via
@graphty/algorithms → pupt. Direct deps are exclusively on 4.3.6; no
source-level mixing.

Verified locally under @types/node@20.19.16 / Node 22:
- pnpm -r build: clean
- pnpm -r exec tsc --noEmit: clean
- pnpm -r test: 952 pass / 0 fail
- pnpm -F @opencodehub/sarif run validate-schema: 4 pass / 0 fail
- biome ci, banned-strings, license-checker: green
@theagenticguy theagenticguy merged commit 86df8c7 into main Apr 23, 2026
14 checks passed
@theagenticguy theagenticguy deleted the feat/zod-4 branch April 23, 2026 03:02
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.

deps: bump zod 3.25 → 4.x

1 participant