No request validation on campaign/ship create/update (zod exists but unused there) #43

Closed
opened 2026-08-23 05:42:07 +00:00 by nasandre · 2 comments
Owner

`createCampaign`/`updateCampaign`/`createShip`/`updateShip` controllers only check `name` presence and pass raw `req.body` into services. Zod schemas exist for users (`models/user.ts`) but not for campaigns/ships/characters payloads.

Consequences:

  • Wrong-typed fields (strings for numbers, unexpected nested objects) go straight into SQL params / JSON columns
  • `startingResources`, `events[]`, etc. can arrive malformed and fail deep inside service loops with generic 500s

Suggested fix

Define zod schemas per entity (shared package would let the frontend reuse them) and parse bodies in controllers before calling services.

\`createCampaign\`/\`updateCampaign\`/\`createShip\`/\`updateShip\` controllers only check \`name\` presence and pass raw \`req.body\` into services. Zod schemas exist for users (\`models/user.ts\`) but not for campaigns/ships/characters payloads. Consequences: - Wrong-typed fields (strings for numbers, unexpected nested objects) go straight into SQL params / JSON columns - \`startingResources\`, \`events\[\]\`, etc. can arrive malformed and fail deep inside service loops with generic 500s ## Suggested fix Define zod schemas per entity (shared package would let the frontend reuse them) and parse bodies in controllers before calling services.
Author
Owner

🔧 Work started — Adding zod schemas for campaign/ship payloads (models/campaign.ts, models/ship.ts), parsing bodies in create/update controllers, returning 400 with field details.

🔧 **Work started** — Adding zod schemas for campaign/ship payloads (`models/campaign.ts`, `models/ship.ts`), parsing bodies in create/update controllers, returning 400 with field details.
Author
Owner

✅ Fixed & verified live (commit 7c0908e):

  • New zod schemas: models/campaign.ts + models/ship.ts — strict type checks on scalar fields, loose object-array validation for nested game entities, unknown keys stripped
  • Wired into createCampaign/updateCampaign/createShip/updateShip → 400 with details: {field: [errors]}

Live test:
POST /campaigns {players:not-an-array,startingResources:{throneGelt:lots}} → 400

{players:[Expected
✅ **Fixed & verified live** (commit `7c0908e`): - New zod schemas: `models/campaign.ts` + `models/ship.ts` — strict type checks on scalar fields, loose object-array validation for nested game entities, unknown keys stripped - Wired into createCampaign/updateCampaign/createShip/updateShip → **400** with `details: {field: [errors]}` Live test: `POST /campaigns {players:not-an-array,startingResources:{throneGelt:lots}}` → 400 ```json {players:[Expected
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nasandre/wh40-rogue-trader#43
No description provided.