From 4953bb82b77f31445fead4b45c3bd0b4c3f0b389 Mon Sep 17 00:00:00 2001 From: ygd58 Date: Sun, 30 Aug 2026 19:23:48 +0000 Subject: [PATCH] fix(validation): remove unreachable limit refine branches in search schemas SearchRequestSchema and Searchv4RequestSchema both chain .positive().optional().default(10) before their limit refine, so by the time the refine runs the value can never be undefined (default() substitutes 10) and can never be <= 0 (positive() already rejects it). The v === undefined || (v > 0 && ...) guard was therefore dead code -- only the upper bound (v <= 100) check had any effect. Simplified both to just the meaningful check and added tests covering the default, the accepted range, and both still-rejected boundaries (0 and 101), plus a source-level guard extending the existing search-threshold dead-code check. No behavior change: same values are accepted/rejected before and after, confirmed by the added tests. Refs #1205 --- packages/validation/api.test.ts | 35 +++++++++++++++++++++++++++++++++ packages/validation/api.ts | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/validation/api.test.ts b/packages/validation/api.test.ts index fa52ed890..dbd39983d 100644 --- a/packages/validation/api.test.ts +++ b/packages/validation/api.test.ts @@ -18,6 +18,41 @@ describe("search threshold schemas", () => { expect(searchSchemas).not.toContain(".transform(Number)") expect(searchSchemas).not.toContain("v === undefined || (v >= 0 && v <= 1)") + expect(searchSchemas).not.toContain( + "v === undefined || (v > 0 && v <= 100)", + ) + }) + + it.each([ + 1, 50, 100, + ])("accepts in-range limit value %p on search schemas", (limit) => { + expect(SearchRequestSchema.parse({ q: "memory", limit }).limit).toBe(limit) + expect(Searchv4RequestSchema.parse({ q: "memory", limit }).limit).toBe( + limit, + ) + }) + + it("preserves the limit default of 10 on search schemas", () => { + expect(SearchRequestSchema.parse({ q: "memory" }).limit).toBe(10) + expect(Searchv4RequestSchema.parse({ q: "memory" }).limit).toBe(10) + }) + + it("still rejects a limit above 100 on search schemas", () => { + expect( + SearchRequestSchema.safeParse({ q: "memory", limit: 101 }).success, + ).toBe(false) + expect( + Searchv4RequestSchema.safeParse({ q: "memory", limit: 101 }).success, + ).toBe(false) + }) + + it("still rejects a non-positive limit on search schemas", () => { + expect( + SearchRequestSchema.safeParse({ q: "memory", limit: 0 }).success, + ).toBe(false) + expect( + Searchv4RequestSchema.safeParse({ q: "memory", limit: -1 }).success, + ).toBe(false) }) it("preserves threshold defaults", () => { diff --git a/packages/validation/api.ts b/packages/validation/api.ts index ae6ac3191..43f6db943 100644 --- a/packages/validation/api.ts +++ b/packages/validation/api.ts @@ -432,7 +432,7 @@ export const SearchRequestSchema = z.object({ .positive() .optional() .default(10) - .refine((v) => v === undefined || (v > 0 && v <= 100), { + .refine((v) => v <= 100, { message: "limit must be between 1 and 100", params: { max: 100, @@ -527,7 +527,7 @@ export const Searchv4RequestSchema = z.object({ .positive() .optional() .default(10) - .refine((v) => v === undefined || (v > 0 && v <= 100), { + .refine((v) => v <= 100, { message: "limit must be between 1 and 100", params: { max: 100,