Feature/validate conversations - #212
Merged
Premshaw23 merged 3 commits intoMay 20, 2026
Merged
Conversation
…y Firebase ID Token in the authorization header- Early reject unauthenticated requests with 401 Unauthorized- Enriched conversations log with userId and userEmail metadata- Added comprehensive Jest unit tests covering all auth outcomes
…ne Zod schema to enforce types and 10k character limits- Enforce maximum raw payload size of 1MB, returning 413- Sanitize string inputs server-side by stripping script tags- Create api documentation file docs/conversations-api.md- Add new Jest tests covering all validation criteria
…into feature/authenticate-conversations Necesssary
Contributor
|
@omnipotentchaos is attempting to deploy a commit to the Prem Shaw's projects Team on Vercel. A member of the Team first needs to authorize it. |
Premshaw23
approved these changes
May 20, 2026
Owner
|
Done 👍 |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the /api/conversations POST route by adding request validation (schema + bounds), basic sanitization, and payload size limiting, along with accompanying documentation and tests, addressing Issue #162.
Changes:
- Added Zod-based schema validation for
userMessage/botMessageand added<script>tag stripping. - Enforced a 1MB payload size cap (header-based and post-read checks) and improved error responses for invalid payloads.
- Added endpoint documentation and a new Jest test suite for auth/validation/size-limit behavior.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Adds zod dependency for runtime schema validation. |
| package-lock.json | Locks zod dependency resolution. |
| app/api/conversations/route.js | Implements auth enforcement, size checks, Zod validation, and sanitization before DB insert. |
| components/tests/conversationsRoute.test.js | Adds tests for auth failures, oversize payloads, invalid JSON, type/required errors, and sanitization. |
| docs/conversations-api.md | Documents the endpoint contract, limits, and response codes. |
Comments suppressed due to low confidence (1)
docs/conversations-api.md:30
- The payload fields table rows start with
||, which creates an unintended empty first column in GitHub-flavored markdown. Switch to a single leading|per row so the table renders as intended.
| Field | Type | Required | Limits | Description |
|---|---|---|---|---|
| `userMessage` | `string` | **Yes** | Min 1 char, Max 10,000 chars | The message sent by the user. Stripped of `<script>` tags. |
| `botMessage` | `string` | **Yes** | Min 1 char, Max 10,000 chars | The message returned by the bot. Stripped of `<script>` tags. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+32
to
+39
| const authorization = req.headers.get("authorization"); | ||
| const token = authorization?.split(" ")[1]; | ||
|
|
||
| const decodedToken = await verifyFirebaseToken(token); | ||
|
|
||
| if (!decodedToken) { | ||
| return jsonError("Unauthorized", 401); | ||
| } |
Comment on lines
+13
to
+27
| userMessage: z.string({ | ||
| required_error: "userMessage is required", | ||
| invalid_type_error: "userMessage must be a string", | ||
| }) | ||
| .min(1, "userMessage cannot be empty") | ||
| .max(10000, "userMessage must not exceed 10,000 characters") | ||
| .transform(sanitizeText), | ||
|
|
||
| botMessage: z.string({ | ||
| required_error: "botMessage is required", | ||
| invalid_type_error: "botMessage must be a string", | ||
| }) | ||
| .min(1, "botMessage cannot be empty") | ||
| .max(10000, "botMessage must not exceed 10,000 characters") | ||
| .transform(sanitizeText), |
| const body = await response.json(); | ||
|
|
||
| expect(response.status).toBe(400); | ||
| expect(body.error).toContain("expected string, received number"); |
| const body = await response.json(); | ||
|
|
||
| expect(response.status).toBe(400); | ||
| expect(body.error).toContain("expected string, received undefined"); |
Comment on lines
+15
to
+18
| | Header | Value | Description | | ||
| |---|---|---| | ||
| | `Authorization` | `Bearer <Firebase_ID_Token>` | **Required.** Firebase authentication token to verify user identity. | | ||
| | `Content-Type` | `application/json` | **Required.** Must be JSON payload. | |
Comment on lines
+35
to
+45
| const decodedToken = await verifyFirebaseToken(token); | ||
|
|
||
| if (!decodedToken) { | ||
| return jsonError("Unauthorized", 401); | ||
| } | ||
|
|
||
| // Enforce maximum document size (1MB = 1048576 bytes) | ||
| const contentLength = req.headers.get("content-length"); | ||
| if (contentLength && parseInt(contentLength, 10) > 1024 * 1024) { | ||
| return jsonError("Payload too large", 413); | ||
| } |
Comment on lines
+32
to
+38
| const authorization = req.headers.get("authorization"); | ||
| const token = authorization?.split(" ")[1]; | ||
|
|
||
| const decodedToken = await verifyFirebaseToken(token); | ||
|
|
||
| if (!decodedToken) { | ||
| return jsonError("Unauthorized", 401); |
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.
What type of PR is this?
Description
Secures the
/api/conversationsendpoint by enforcing strict schema/type checks via Zod, input sanitization, and request payload size limits. These enhancements prevent database bloat and XSS code injection.Related Issues
Closes #162
Changes Made
413 Payload Too Largerejection for request bodies exceeding 1MB.zodschema to ensureuserMessageandbotMessageare required strings with a maximum limit of 10,000 characters (returns400 Bad Requeston type anomalies).<script>tags to prevent XSS script execution.docs/conversations-api.mdoutlining the API inputs, bounds, and responses.components/_tests_/conversationsRoute.test.jscovering large payload size limits (> 1MB), type errors, missing inputs, and script stripping.Testing
How did you test these changes?
Screenshots (if applicable)
N/A
Checklist
.env.localis not committeddocs/conversations-api.md)npm run build)