feat: Zod validation on all API inputs (PRD §5.2)

26 files with Zod schemas, 27 safeParse calls.
All POST/PATCH handlers now validate input:
- Missing required fields → 400 with structured error
- Invalid types (string vs number) → 400
- Out-of-range values (probability >100, negative amounts) → 400
- Valid data still works (behavior preserved)

Pattern: schema.safeParse(await req.json()) → 400 on failure
This commit is contained in:
Z User committed 2026-10-27 21:29:51 +00:00
1 parent 3d56770669
commit 2614ce4e3d
25 files changed
+316 -116

No files matched your search

+12 -5
View File
@@ -1,9 +1,15 @@
import { NextResponse } from 'next/server'
import { z } from 'zod'
import { db } from '@/lib/db'
export const dynamic = 'force-dynamic'
export const maxDuration = 30
const importSchema = z.object({
csv: z.string().min(1),
mapping: z.record(z.string(), z.number()),
})
// POST /api/aos/crm/import
// Import companies + persons from a CSV string.
// Body: { csv: string, mapping: { name: number, vatId: number, ... } }
@@ -13,13 +19,14 @@ export const maxDuration = 30
// Duplicate detection: skips companies with the same name or website.
export async function POST(req: Request) {
try {
const { csv, mapping } = (await req.json()) as {
csv: string
mapping: Record<string, number>
const parsed = importSchema.safeParse(await req.json())
if (!parsed.success) {
return NextResponse.json({ error: 'validation failed', details: parsed.error.flatten() }, { status: 400 })
}
const { csv, mapping } = parsed.data
if (!csv?.trim()) return NextResponse.json({ error: 'csv data required' }, { status: 400 })
if (!mapping?.name && mapping.name !== 0) return NextResponse.json({ error: 'mapping.name required' }, { status: 400 })
if (!csv.trim()) return NextResponse.json({ error: 'csv data required' }, { status: 400 })
if (mapping.name === undefined) return NextResponse.json({ error: 'mapping.name required' }, { status: 400 })
// Parse CSV (simple RFC 4180 parser — handles quoted fields with commas)
const lines = parseCSV(csv)