chore(server): add Zod request validation to all document endpoints - #88
Merged
Conversation
Document routes accepted unvalidated bodies and params: malformed ids surfaced Prisma errors as 500s, non-boolean flags reached the DB layer, and title/permission values were never length- or enum-checked. Auth schemas also lagged client-side bounds (server allowed 6-char passwords while the client requires 8). Add body/param/query schemas wired through the existing validate() middleware for every /document route, replace the manual share-link permission check with a query enum schema, and harden register/login/ addCollaborator bounds (email <=254, username <=50 + charset, password 8..128, fullName <=100). Mirror those bounds in the client (zod schemas + maxLength attributes) so users never hit a 400. Closes #52. Related: #37 (rate limiting), #83 (enumeration hardening).
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.
Closes #52.
Extends the validation pattern introduced for auth + collaborators (#50/#80) to every document route, so malformed input returns clean 400/404s instead of Prisma-driven 500s. Validation audit findings (2026-08-25) below — this PR implements all of them.
Server plan
1. Body schemas (new files in
server/src/validations/)createDocument.schema.ts:{ title: string(1..200), content?: string(max ~1MB), isPublic?: boolean(default false) }— use.trim()on titleupdateDocument.schema.ts: partial variant (all optional, same bounds)updateDocSettings.schema.ts:{ allowSelfJoin: boolean }.max()to existing schemas while here: email ≤254, username ≤50 + charset regex/^[a-zA-Z0-9_.-]+$/, password ≤128, fullName ≤100; align server password floor 6 → 8 to match client (client/src/lib/auth.ts)permissioncheck withvalidate({ query })enum2. Param schemas
z.string().uuid()param objects forid,requestId,userId→ wire viavalidate({ params })on routes 9–19 ofdocument.router.ts(kills non-UUID → 500 class)3. Router wiring
Apply
validate({ body, params, query })per route indocument.router.ts. Keep controller destructuring as-is where it already matches parsed output.Client plan (matching constraints so users never hit a 400)
maxLengthattributes: title inputs 200, email 254, username 50, password 128 (register/login forms, NewDocumentFormBody, rename-modal, collaborators-dropdown email input)client/src/lib/auth.ts) and add title max to new-document/rename flowsTest plan
server/test/document.test.ts; keep suite serial-compatibleOut of scope