From d8a537e7aaf12335932258ebd6097966125dea43 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 11 Apr 2026 16:41:40 +0000 Subject: [PATCH] Forbid slashes in case numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FastAPI path routing can't capture a slash inside a {case_number} segment — %2F gets decoded before route matching, so any case created with "1000/0426" becomes permanently unreachable at GET /api/cases/{case_number}/details. Enforce the hyphen convention used by existing prod cases (1033-25, 1130-25) at the zod layer so the wizard rejects the bad shape before submit. Co-Authored-By: Claude Opus 4.6 (1M context) --- web-ui/src/lib/schemas/case.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web-ui/src/lib/schemas/case.ts b/web-ui/src/lib/schemas/case.ts index d5d2386..39053b1 100644 --- a/web-ui/src/lib/schemas/case.ts +++ b/web-ui/src/lib/schemas/case.ts @@ -11,9 +11,13 @@ import { z } from "zod"; -/* Appeal numbers follow the 1xxx / 8xxx / 9xxx convention from CLAUDE.md — - * permissive regex that still catches obvious typos. */ -const caseNumberRe = /^[1-9]\d{3,}(?:[-/][\w\u0590-\u05FF]+)*$/; +/* Appeal numbers follow the 1xxx / 8xxx / 9xxx convention from CLAUDE.md. + * Slashes are deliberately forbidden: FastAPI path routing can't capture + * a `/` inside a case-number segment even when URL-encoded as %2F, so + * any case created with a slash becomes unreachable at + * GET /api/cases/{case_number}/details. Existing prod cases use hyphens + * (e.g. "1033-25", "1130-25") which is the enforced convention here. */ +const caseNumberRe = /^[1-9]\d{3,}(?:-[\w\u0590-\u05FF]+)*$/; const hebrewPartyRe = /[\u0590-\u05FFA-Za-z]/; @@ -37,7 +41,7 @@ export const caseCreateSchema = z.object({ .string() .trim() .min(1, "שדה חובה") - .regex(caseNumberRe, "מספר תיק לא תקין (למשל 1234 או 8001/2026)"), + .regex(caseNumberRe, "מספר תיק לא תקין — השתמש במקף, לא בקו נטוי (למשל 1033-25)"), title: z.string().trim().min(3, "כותרת קצרה מדי").max(200, "כותרת ארוכה מדי"), appellants: z .array(z.string().trim().min(1).refine((v) => hebrewPartyRe.test(v), "שם לא תקין"))