Description
Some backend routes validate input with Zod schemas, but many routes perform manual checks or no validation at all. Inconsistent validation means some endpoints accept malformed data that causes database errors or unexpected behavior. All routes should use a consistent Zod middleware pattern.
Current Inconsistency
// Some routes — proper Zod validation
const schema = z.object({ name: z.string().min(1), price: z.number().positive() });
const result = schema.safeParse(req.body);
if (\!result.success) return res.status(422).json({ errors: result.error.issues });
// Other routes — no validation
router.post('/', authenticate, async (req, res) => {
const { name, price, billingCycle } = req.body; // ← no validation
await supabase.from('subscriptions').insert({ name, price, billing_cycle: billingCycle });
});
Solution: Shared validation middleware factory
/backend/src/middleware/validate.ts
import { ZodSchema } from 'zod';
import { Request, Response, NextFunction } from 'express';
export function validate(schema: ZodSchema, source: 'body' | 'query' | 'params' = 'body') {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req[source]);
if (\!result.success) {
return res.status(422).json({
type: 'https://syncro.app/errors/validation',
title: 'Validation Error',
status: 422,
errors: result.error.issues.map(i => ({
field: i.path.join('.'),
message: i.message,
})),
});
}
req[source] = result.data; // replace with parsed/coerced data
next();
};
}
Usage
const createSubscriptionSchema = z.object({
name: z.string().min(1).max(100),
price: z.number().positive().max(100000),
currency: z.string().length(3),
billing_cycle: z.enum(['monthly', 'quarterly', 'annual', 'weekly']),
next_renewal_date: z.string().datetime(),
renewal_url: z.string().url().max(2000).optional(),
category: z.string().max(50).optional(),
});
router.post('/', authenticate, validate(createSubscriptionSchema), createSubscription);
All Routes Needing Schemas
POST /api/subscriptions — createSubscriptionSchema
PUT /api/subscriptions/:id — updateSubscriptionSchema
POST /api/team/invite — inviteTeamSchema
POST /api/keys — createApiKeySchema
POST /api/webhooks — createWebhookSchema
- All other POST/PUT endpoints
Acceptance Criteria
Description
Some backend routes validate input with Zod schemas, but many routes perform manual checks or no validation at all. Inconsistent validation means some endpoints accept malformed data that causes database errors or unexpected behavior. All routes should use a consistent Zod middleware pattern.
Current Inconsistency
Solution: Shared validation middleware factory
/backend/src/middleware/validate.tsUsage
All Routes Needing Schemas
POST /api/subscriptions— createSubscriptionSchemaPUT /api/subscriptions/:id— updateSubscriptionSchemaPOST /api/team/invite— inviteTeamSchemaPOST /api/keys— createApiKeySchemaPOST /api/webhooks— createWebhookSchemaAcceptance Criteria
validate()middleware created and exported