Adds Zod-validated input schemas for all /api/webhooks endpoints, replacing inline ad-hoc validation with centralized, reusable validators. Follows the established pattern from src/validators/markets.ts and src/validators/predictions.ts.
listWebhooksQuerySchema-- validatesGET /api/webhooksquery params (cursor,limit). Uses.strict()to reject unknown params. Coerces string limits to integers with range 1-100.dlqQuerySchema-- validatesGET /api/admin/webhooks/dlqquery params (same shape as above).dlqReplayParamsSchema-- validatesPOST /api/admin/webhooks/dlq/:id/replayroute params using Zod's.uuid()validator.
- Removed inline
webhooksQuerySchema(regex-based string limit validation). - Imported
listWebhooksQuerySchemafrom centralized validators. - Schema now uses
z.coerce.number()for type-safe limit parsing with proper integer and range validation.
- Added Zod validation for
GET /dlqquery params viadlqQuerySchema(previously rawreq.querywith no validation). - Added Zod validation for
POST /dlq/:id/replayparams viadlqReplayParamsSchema(replaced manual UUID regex). - Added structured pino logging with correlation IDs to both handlers.
- Removed
/* eslint-disable @typescript-eslint/no-explicit-any */and replacedanycast with typedReplayResultinterface.
src/index.ts-- Fixed brokenwebhooksRouterimport (exportedcreateWebhooksRouter, notwebhooksRouter). Router is now conditionally created via factory whenoptions.webhooksis provided.src/routes/predictions.ts-- Added missingaccessLogmiddleware import that blocked all tests usingcreateApp.
38 tests, all passing:
Schema unit tests (19):
listWebhooksQuerySchema-- valid inputs, empty cursor, zero/negative/non-integer/max limit, unknown paramsdlqQuerySchema-- empty query, valid params, unknown params, zero/max limitdlqReplayParamsSchema-- valid UUID, invalid format, empty string, wrong length, non-hex chars
Integration tests (19):
GET /api/webhooks-- auth (403 without/with non-admin), validation (400 for bad limit/cursor/unknown params), success (200 with valid params, pagination, requestId in errors)GET /api/admin/webhooks/dlq-- auth, validation for limit and unknown paramsPOST /api/admin/webhooks/dlq/:id/replay-- auth, 400 for invalid UUID, 404 for non-existent row
All endpoints now return a standardized error envelope on invalid input:
{
"error": {
"code": "validation_error",
"message": "<specific Zod error message>",
"requestId": "<correlation ID>"
}
}Unknown query parameters are rejected (.strict() mode) to keep route boundaries explicit and avoid silently ignoring malformed input.
| File | Action | Lines changed |
|---|---|---|
src/validators/webhooks.ts |
Added | +75 |
src/routes/webhooks.ts |
Modified | -15, +5 |
src/routes/adminWebhooks.ts |
Modified | -15, +68 |
src/routes/predictions.ts |
Modified | +1 |
src/index.ts |
Modified | -4, +7 |
tests/webhooksValidation.test.ts |
Added | +379 |
- Implementation matches the description
- Tests added and passing (38/38)
- ESLint clean
- Follows repo conventions (factory pattern, error response shape, log events)
- Input validation at the boundary with standardized error envelope
- Structured logging with correlation IDs
- Clear documentation and inline comments
Closes #433