Bump zod from 3.25.76 to 4.5.4 - #35
Merged
Merged
Conversation
Bumps [zod](https://github.com/colinhacks/zod) from 3.25.76 to 4.5.4. - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](colinhacks/zod@v3.25.76...v4.5.4) --- updated-dependencies: - dependency-name: zod dependency-version: 4.5.4 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
dependabot
Bot
force-pushed
the
dependabot/npm_and_yarn/zod-4.5.4
branch
from
September 7, 2026 10:27
92e2639 to
887ce24
Compare
zod v4 requires z.record(keySchema, valueSchema); the single-argument form used for the error-details bag no longer compiles.
zod v4 tightened z.ZodTypeAny's inferred output from any to unknown,
which surfaced two latent typing gaps that zod v3 had been silently
papering over:
- singleObjectEnvelope<T> and the test suite's duplicated
z.object({ data: schema }).parse(...).data pattern couldn't
statically resolve `.data` on a generic schema's parsed output.
Consolidated the test-side duplication into one parseEnvelopeData
helper and gave singleObjectEnvelope an explicit cast-backed return
type; both keep the runtime behavior identical.
- mutationVariantsToSchemas returned z.ZodTypeAny for both schemas,
so every mutation tool's parsed output was effectively `any` and
none of its status/outcome/data union members were ever checked.
Made it generic over the variant tuple so callers get the real
discriminated union back. This caught a genuine pre-existing bug in
workflow.ts: addDependency/removeDependency shared one
implementation typed to return the union of both outcomes, silently
assignable to each specific one only because of the `any` leak.
…le wrappers Under zod v4, .describe(X).optional() (and .nullable()/.nullish()) silently drops the description entirely instead of erroring — the wrapper doesn't forward it. This affected 28 fields across ticket_inputs.ts, comments.ts, and tools/tickets.ts, all part of the public MCP tool schemas shown to calling agents, and only 2 of the 28 had test coverage that happened to catch it. Reordered every affected chain to .optional().describe(...) (verified via a full-codebase scan). Added a permanent regression test that scans src/ for the dangerous ordering, since this class of bug is silent at both the type and runtime level.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Dependabot's mechanical bump alone didn't compile — zod v4 has real breaking changes this codebase relied on. Fixed all of them:
z.record()signature change: now requires an explicit key schema (z.record(z.string(), z.unknown())), not just the value schema.z.ZodTypeAny's inferred output tightened fromanytounknown, surfacing two latent typing gaps zod v3 had silently papered over:singleObjectEnvelope<T>and a duplicatedz.object({ data: schema }).parse(...).datapattern across 6 test files couldn't statically resolve.dataon a generic schema's parsed output. Consolidated the test-side duplication into oneparseEnvelopeDatahelper; gavesingleObjectEnvelopean explicit, cast-backed return type. Runtime behavior unchanged.mutationVariantsToSchemasreturnedz.ZodTypeAnyfor both schemas, so every mutation tool's parsed output was effectivelyany— none of its status/outcome/data union members were ever type-checked. Made it generic over the variant tuple so callers get the real discriminated union back. This caught a genuine pre-existing bug inworkflow.ts:addDependency/removeDependencyshared one implementation typed to return the union of both outcomes, silently assignable to each specific one only because of theanyleak..describe(X).optional()(and.nullable()/.nullish()) silently drops the description entirely under zod v4 — no type error, no runtime error, just an undocumented field. This affected 28 fields acrossticket_inputs.ts,comments.ts, andtools/tickets.ts— real descriptions in the public MCP tool schemas that agents read to know how to call these tools. Only 2 of the 28 had test coverage that happened to catch it. Reordered every affected chain to.optional().describe(...)(verified via a full-codebase scan) and added a permanent regression test (tests/zod_describe_order.test.ts) that scanssrc/for this ordering, since the bug is silent at both the type and runtime level — verified the test actually catches the pattern before relying on it.Test plan
npm run typechecknpm run lintnpm test(371 tests passing, including the new describe-order regression test)npm run build