fix: validate request body in POST /projects/:projectId/chat

🟢 open · #155 · Open-Legal-Products/mike ← Shawnaldinho/mike · opened 2mo ago by Shawnaldinho · +118-8 across 1 file · ↗ on GitHub

From the PR description

Summary

projectChat.ts:32-39 reads `req.body` via a bare `as { ... }` cast, while sibling routes (`chat.ts`, `user.ts`) use hand-written parsers. A misshapen body - wrong types for `messages`, `displayed_doc`, `attached_documents` - therefore reaches the DB writes and the LLM call.

Changes

  • Add per-field parsers in `backend/src/routes/projectChat.ts` matching the `parseFoo(value: unknown): { ok: true; ... } | { ok: false; detail }` pattern already used by `routes/chat.ts`: `parseChatMessages`, `parseOptionalChatId`, `parseOptionalModel`, `parseDocRef`, `parseOptionalDisplayedDoc`, `parseOptionalAttachedDocuments`.
  • Validate every field before any DB or LLM work; return `400` with the parser's `detail` message on the first failure.
  • Downstream variable names (`messages`, `chat_id`, `model`, `displayed_doc`, `attached_documents`) are preserved so the rest of the handler is unchanged.

Why

Concrete failures the previous cast permitted:

  • `messages` as a non-array → `[...messages].reverse()` throws inside the handler after the chat row has already been inserted.
  • `attached_documents` containing non-object entries → `.map((d) => ...)` crashes on `d.document_id`.
  • `displayed_doc` as a string → the route builds a malformed user message and sends it to the model.

Matches the existing style rather than introducing a new validation library, per CONTRIBUTING.md guidance to keep changes targeted.

Testing

  • `npm run build --prefix backend` passes.
  • Walked each parser through the previously crash-inducing shapes and confirmed each now returns a 400 with a useful `detail`.

Addresses the input-validation concern from https://insights.flank.ai/where-mikeoss-falls-short.html (gap 7) for this specific route. Other routes already validate by hand.

Our analysis

Add hand-written body validation to the project chat route — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-155.md from inside the repo you want the changes in.

⬇ Download capture-pull-155.md