Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Data Validation - Input Sanitisation & Schema Patterns
Validation patterns ensuring all data entering the system is validated at boundaries: user input via Zod (frontend), API requests via Pydantic (backend). No unvalidated data crosses a trust boundary.
Description
Defines Zod and Pydantic validation patterns for all data entering the system at trust boundaries. Covers form validation, API request schemas, type-safe contracts, Australian-specific validators (ABN, phone, postcode), and schema composition strategies.
When to Apply
Positive Triggers
Creating or modifying form inputs with user data
Defining API request/response schemas (Pydantic models)
Adding Zod schemas for frontend validation
Reviewing code for missing input validation
Building new API endpoints that accept POST/PUT/PATCH data
User mentions: "validation", "Zod", "Pydantic", "schema", "sanitise", "input"
Working on database model definitions (that is ORM schema, not input validation)
Core Directives
Validate at Boundaries, Trust Internally
[User Input] --Zod--> [Frontend] --fetch--> [API] --Pydantic--> [Service Layer]
^ ^
| |
VALIDATE HERE VALIDATE HERE
Frontend boundary: Every form field validated with Zod before submission
API boundary: Every request body validated with Pydantic before processing
Internal code: Trust validated data — no redundant re-validation inside services
Naming Conventions
Layer
Convention
Example
Frontend Zod schema
camelCase + Schema suffix
loginFormSchema
Frontend inferred type
PascalCase via z.infer
type LoginForm = z.infer<typeof loginFormSchema>
Backend Pydantic model
PascalCase + purpose suffix
DocumentCreateRequest
Shared contract
Same field names both sides
email, password, title
Frontend Patterns (Zod + react-hook-form)
Basic Form Schema
The project already uses this pattern in apps/web/components/auth/login-form.tsx:
import * as z from'zod';
import { zodResolver } from'@hookform/resolvers/zod';
import { useForm } from'react-hook-form';
// 1. Define schemaconst loginFormSchema = z.object({
email: z.string().email('Please enter a valid email address'),
password: z.string().min(6, 'Password must be at least 6 characters'),
});
// 2. Infer type (never define manually)typeLoginForm = z.infer<typeof loginFormSchema>;
// 3. Use with react-hook-formconst form = useForm<LoginForm>({
resolver: zodResolver(loginFormSchema),
defaultValues: { email: '', password: '' },
});
Schema Composition
Build complex schemas from reusable parts:
// Base schemas (reusable)const emailSchema = z.string().email('Please enter a valid email address');
const passwordSchema = z.string().min(6, 'Password must be at least 6 characters');
const abnSchema = z.string().regex(/^\d{11}$/, 'ABN must be 11 digits');
// Composed schemasconst registerFormSchema = z
.object({
email: emailSchema,
password: passwordSchema,
confirmPassword: z.string(),
})
.refine((data) => data.password === data.confirmPassword, {
message: 'Passwords do not match',
path: ['confirmPassword'],
});
API Request Validation
Validate data before sending to the backend:
const documentCreateSchema = z.object({
title: z.string().min(1, 'Title is required').max(255),
content: z.string().min(1, 'Content is required'),
metadata: z.record(z.unknown()).optional(),
});
asyncfunctioncreateDocument(input: unknown): Promise<Document> {
// Validate before sending — fail fast on the clientconst validated = documentCreateSchema.parse(input);
return apiClient.post('/api/documents', validated);
}
Australian-Specific Validators
// Australian Business Number (ABN) with checksumconst abnSchema = z.string().refine(
(val) => {
if (!/^\d{11}$/.test(val)) returnfalse;
const weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
const digits = val.split('').map(Number);
digits[0] -= 1;
const sum = digits.reduce((acc, d, i) => acc + d * weights[i], 0);
return sum % 89 === 0;
},
{ message: 'Invalid ABN' }
);
// Australian phone numberconst auPhoneSchema = z.string().regex(
/^(\+61|0)[2-478]\d{8}$/,
'Please enter a valid Australian phone number'
);
// Australian postcodeconst postcodeSchema = z.string().regex(/^\d{4}$/, 'Postcode must be 4 digits');
// Date in DD/MM/YYYY formatconst auDateSchema = z.string().regex(
/^\d{2}\/\d{2}\/\d{4}$/,
'Date must be in DD/MM/YYYY format'
);
Backend Patterns (Pydantic)
Request Model Convention
The project defines request models in route files or apps/backend/src/api/schemas/: