Skip to content

Consider using Zod for validation #25

Description

@Readpato

Describe the feature

API routes currently have no runtime validation on incoming data. Request bodies and cookie payloads are destructured directly from JSON.parse() and request.json() without any shape or type checks. A malformed cookie or unexpected request body results in an unhandled error and a generic 500 response instead of a clean 400.

Examples:

  • app/src/app/api/challenges/route.ts: JSON.parse(tokenCookie) is destructured as { eventId } with no validation
  • app/src/app/api/auth/signup/route.ts: request.json() is destructured as { firstName, lastName, email, eventCode } with no validation
  • Same pattern across awards, leaderboard, webhook, and admin routes

Proposal

Add Zod schemas to validate:

  1. Cookie payloads - validate user_token and supervisor_token shape after JSON.parse()
  2. Request bodies - validate POST/PATCH payloads in signup, challenge redeem, award redeem, admin verify, and webhook routes
  3. Sanity query params - validate that IDs and codes have the expected format before sending queries

Benefits

  • Malformed input returns a descriptive 400 instead of a cryptic 500
  • Schemas serve as documentation for the expected data shapes
  • Catches bugs earlier (e.g., missing fields, wrong types, empty strings)
  • Pairs well with the existing TypeScript types in src/types/ by providing runtime enforcement

Scope

  • Define shared schemas in a src/lib/schemas/ directory (e.g., cookiePayload, signupBody, challengeRedeemBody)
  • Add validation at the top of each API route handler
  • Return structured error responses on validation failure
  • We could (and should) approach this step by step instead of outright migrating everything (so we can already benefit of using Zod)

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions