Description:
All API route handlers call req.json() and use the values directly with no type checking, no input sanitization, and no schema validation:
// ❌ src/app/api/rent/pay/route.ts
const { landlordId, amount } = await req.json()
// amount could be negative, NaN, a string, or undefined
This allows malformed requests to reach business logic silently, causes confusing runtime errors, and is a potential injection vector once the database layer is implemented.
Fix: Add Zod schemas to all POST/PUT routes:
import { z } from "zod"
const PayRentSchema = z.object({
landlordId: z.string().uuid(),
amount: z.number().positive(),
goalId: z.string().uuid().optional()
})
const body = PayRentSchema.safeParse(await req.json())
if (!body.success) return NextResponse.json({ message: body.error.flatten() }, { status: 400 })
Scope: All API routes under /api/auth, /api/savings, /api/rent, /api/landlords, /api/notifications.
Acceptance criteria:
Zod installed as a dependency
Each POST/PUT route has a corresponding Zod schema
Validation errors return structured 400 responses with field-level details
Stellar public key format validated on routes that accept wallet addresses
Numeric amounts validated to be positive and within reasonable bounds
Description:
All API route handlers call req.json() and use the values directly with no type checking, no input sanitization, and no schema validation:
// ❌ src/app/api/rent/pay/route.ts
const { landlordId, amount } = await req.json()
// amount could be negative, NaN, a string, or undefined
This allows malformed requests to reach business logic silently, causes confusing runtime errors, and is a potential injection vector once the database layer is implemented.
Fix: Add Zod schemas to all POST/PUT routes:
import { z } from "zod"
const PayRentSchema = z.object({
landlordId: z.string().uuid(),
amount: z.number().positive(),
goalId: z.string().uuid().optional()
})
const body = PayRentSchema.safeParse(await req.json())
if (!body.success) return NextResponse.json({ message: body.error.flatten() }, { status: 400 })
Scope: All API routes under /api/auth, /api/savings, /api/rent, /api/landlords, /api/notifications.
Acceptance criteria:
Zod installed as a dependency
Each POST/PUT route has a corresponding Zod schema
Validation errors return structured 400 responses with field-level details
Stellar public key format validated on routes that accept wallet addresses
Numeric amounts validated to be positive and within reasonable bounds