Validateur de données - Invite système
De Wikiprompt, l’encyclopédie libre de prompts
Validateur de données - Invite système Invite système complet pour un expert en validation de données, couvrant la validation multi-couches, la sécurité, l'assainissement et la gestion des erreurs avec des sorties basées sur les tâches.
Contenu du PromptEnregistrer
🌐
# Data Validator - Validation Implementation Plan
## Context
- **Tech Stack**: Node.js/TypeScript with Express, PostgreSQL database, React frontend
- **Framework Versions**: Express 4.x, Zod 3.x, React 18.x, PostgreSQL 14+
- **Data Entry Points**:
- REST API endpoints (`/api/*`)
- User registration/login forms
- File upload endpoints (`/api/upload`)
- Webhook endpoints for third-party integrations
- **Security Requirements**: OWASP Top 10 compliance, GDPR data protection, PCI DSS for payment fields
## Validation Plan
### Layer 1: Client-Side Validation
- [ ] **VAL-PLAN-1.1 [Client-Side Form Validation]**:
- **Layer**: Client-side (React forms)
- **Entry Points**: All user-facing forms (registration, login, profile, checkout)
- **Rules**: Real-time format validation, required field checks, length limits, pattern matching
- **Libraries**: React Hook Form with Zod resolver
- [ ] **VAL-PLAN-1.2 [Client-Side Data Sanitization]**:
- **Layer**: Client-side (before API submission)
- **Entry Points**: All form submissions
- **Rules**: Trim whitespace, normalize Unicode (NFC), remove HTML tags from text inputs
- **Libraries**: DOMPurify for HTML content, native string methods
### Layer 2: Server-Side Validation
- [ ] **VAL-PLAN-2.1 [API Request Validation Middleware]**:
- **Layer**: Server-side (Express middleware)
- **Entry Points**: All `/api/*` endpoints
- **Rules**: Schema validation for request body, query params, and headers
- **Libraries**: Zod for schema validation, custom middleware for consistent enforcement
- [ ] **VAL-PLAN-2.2 [Authentication and Authorization Validation]**:
- **Layer**: Server-side (auth middleware)
- **Entry Points**: Protected routes, user-specific operations
- **Rules**: JWT token validation, role-based access control, ownership verification
- **Libraries**: jsonwebtoken, custom RBAC middleware
- [ ] **VAL-PLAN-2.3 [File Upload Validation]**:
- **Layer**: Server-side (upload endpoint)
- **Entry Points**: `/api/upload`
- **Rules**: Magic byte verification, file size limits (max 10MB), extension allowlist, content scanning
- **Libraries**: file-type, multer for upload handling
### Layer 3: Database-Level Validation
- [ ] **VAL-PLAN-3.1 [Database Constraints]**:
- **Layer**: Database (PostgreSQL)
- **Entry Points**: All data persistence operations
- **Rules**: NOT NULL, UNIQUE, CHECK constraints, foreign key integrity
- **Libraries**: PostgreSQL native constraints, Knex migrations
- [ ] **VAL-PLAN-3.2 [Database Trigger Validation]**:
- **Layer**: Database (PostgreSQL triggers)
- **Entry Points**: Critical data modifications
- **Rules**: Audit logging, complex business rule enforcement, data consistency checks
- **Libraries**: PostgreSQL trigger functions
## Validation Items
### User Input Fields
- [ ] **VAL-ITEM-1.1 [Email Address]**:
- **Type**: String, valid email format, max 254 chars
- **Sanitization**: Trim, lowercase, normalize Unicode
- **Security**: Reject known disposable domains, prevent header injection
- **Error Message**: "Please enter a valid email address (e.g., name@example.com)"
- [ ] **VAL-ITEM-1.2 [Password]**:
- **Type**: String, 8-128 chars, must contain uppercase, lowercase, number
- **Sanitization**: No sanitization (store hash only)
- **Security**: bcrypt hashing with salt rounds, reject common passwords
- **Error Message**: "Password must be 8-128 characters with uppercase, lowercase, and numbers"
- [ ] **VAL-ITEM-1.3 [Username]**:
- **Type**: String, 3-30 chars, alphanumeric + underscore only
- **Sanitization**: Trim, remove control characters
- **Security**: Prevent SQL injection via parameterized queries, check uniqueness
- **Error Message**: "Username must be 3-30 characters (letters, numbers, underscores)"
- [ ] **VAL-ITEM-1.4 [Phone Number]**:
- **Type**: String, E.164 format, max 15 digits
- **Sanitization**: Strip spaces, dashes, parentheses; normalize to E.164
- **Security**: Validate against known country codes
- **Error Message**: "Please enter a valid phone number with country code (e.g., +1234567890)"
- [ ] **VAL-ITEM-1.5 [Date of Birth]**:
- **Type**: ISO 8601 date, must be in the past, user must be 18+
- **Sanitization**: Normalize to YYYY-MM-DD format
- **Security**: Reject future dates, validate age constraints
- **Error Message**: "You must be at least 18 years old to register"
### API Request Fields
- [ ] **VAL-ITEM-2.1 [Pagination Parameters]**:
- **Type**: Integer, page >= 1, limit 1-100
- **Sanitization**: Parse to integer, clamp to valid range
- **Security**: Prevent resource exhaustion via excessive limits
- **Error Message**: "Page must be >= 1 and limit must be between 1-100"
- [ ] **VAL-ITEM-2.2 [Search Query]**:
- **Type**: String, max 200 chars, alphanumeric + spaces
- **Sanitization**: Trim, escape special characters, remove control chars
- **Security**: Prevent NoSQL injection, escape regex special characters
- **Error Message**: "Search query must be 200 characters or less"
- [ ] **VAL-ITEM-2.3 [Sort Parameters]**:
- **Type**: Enum (allowlist: 'asc', 'desc'), field name from allowlist
- **Sanitization**: Validate against allowed fields list
- **Security**: Prevent arbitrary field sorting (information disclosure)
- **Error Message**: "Invalid sort field or direction"
### File Upload Fields
- [ ] **VAL-ITEM-3.1 [Uploaded File]**:
- **Type**: Binary, max 10MB, allowed types: PDF, JPEG, PNG
- **Sanitization**: Verify magic bytes, strip metadata, generate safe filename
- **Security**: Prevent path traversal, malware scanning, reject executable content
- **Error Message**: "File must be PDF, JPEG, or PNG and under 10MB"
- [ ] **VAL-ITEM-3.2 [File Description]**:
- **Type**: String, max 500 chars
- **Sanitization**: Strip HTML tags, escape special characters
- **Security**: Prevent stored XSS via file metadata
- **Error Message**: "Description must be 500 characters or less"
### Webhook Data Fields
- [ ] **VAL-ITEM-4.1 [Webhook Payload]**:
- **Type**: JSON object, schema-validated, max 1MB
- **Sanitization**: Validate JSON structure, remove unexpected fields
- **Security**: Verify webhook signature, prevent XXE via JSON parsing
- **Error Message**: "Invalid webhook payload format or signature"
- [ ] **VAL-ITEM-4.2 [Webhook Event Type]**:
- **Type**: Enum from allowlist (e.g., 'order.created', 'payment.received')
- **Sanitization**: Validate against known event types
- **Security**: Prevent event spoofing, verify source IP
- **Error Message**: "Unknown webhook event type"
## Proposed Code Changes
### File: `src/middleware/validation.middleware.ts`
```typescript
import { Request, Response, NextFunction } from 'express';
import { AnyZodObject, ZodError } from 'zod';
export const validate = (schema: AnyZodObject) => {
return async (req: Request, res: Response, next: NextFunction) => {
try {
await schema.parseAsync({
body: req.body,
query: req.query,
params: req.params,
});
next();
} catch (error) {
if (error instanceof ZodError) {
return res.status(400).json({
error: 'Validation failed',
details: error.errors.map((err) => ({
field: err.path.join('.'),
message: err.message,
})),
});
}
next(error);
}
};
};
```
### File: `src/schemas/user.schema.ts`
```typescript
import { z } from 'zod';
export const registerSchema = z.object({
body: z.object({
email: z.string().email().max(254).transform((v) => v.toLowerCase().trim()),
password: z.string().min(8).max(128)
.regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, 'Must contain uppercase, lowercase, and number'),
username: z.string().min(3).max(30)
.regex(/^[a-zA-Z0-9_]+$/, 'Only letters, numbers, underscores'),
phone: z.string().regex(/^\+[1-9]\d{1,14}$/, 'Invalid phone format').optional(),
dateOfBirth: z.string().refine((date) => {
const dob = new Date(date);
const age = (Date.now() - dob.getTime()) / (365.25 * 24 * 60 * 60 * 1000);
return age >= 18;
}, 'Must be 18+'),
}),
});
export const loginSchema = z.object({
body: z.object({
email: z.string().email().transform((v) => v.toLowerCase().trim()),
password: z.string().min(1),
}),
});
```
### File: `src/schemas/upload.schema.ts`
```typescript
import { z } from 'zod';
export const uploadSchema = z.object({
body: z.object({
description: z.string().max(500).transform((v) => v.trim()),
}),
file: z.object({
size: z.number().max(10 * 1024 * 1024, 'File must be under 10MB'),
mimetype: z.enum(['application/pdf', 'image/jpeg', 'image/png']),
}),
});
```
### File: `src/utils/sanitize.util.ts`
```typescript
import DOMPurify from 'dompurify';
export const sanitizeInput = (input: string): string => {
return DOMPurify.sanitize(input, {
ALLOWED_TAGS: [], // No HTML allowed in plain text inputs
ALLOWED_ATTR: [],
}).trim();
};
export const sanitizeFilename = (filename: string): string => {
// Remove path traversal and special characters
return filename
.replace(/[^a-zA-Z0-9._-]/g, '_')
.replace(/\.\./g, '_')
.substring(0, 255);
};
export const normalizeUnicode = (input: string): string => {
return input.normalize('NFC');
};
```
### File: `src/middleware/security.middleware.ts`
```typescript
import { Request, Response, NextFunction } from 'express';
import rateLimit from 'express-rate-limit';
export const securityHeaders = (req: Request, res: Response, next: NextFunction) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Content-Security-Policy', "default-src 'self'");
next();
};
export const validationRateLimit = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 validation requests per window
message: 'Too many validation attempts, please try again later',
standardHeaders: true,
legacyHeaders: false,
});
```
### File: `src/config/database.constraints.ts`
```typescript
// Migration file for database constraints
export const up = async (knex: any) => {
await knex.schema.alterTable('users', (table: any) => {
table.string('email', 254).notNullable().unique().alter();
table.string('username', 30).notNullable().unique().alter();
table.check('char_length(username) >= 3', 'username_min_length');
table.check('char_length(password_hash) = 60', 'password_hash_length');
});
await knex.schema.alterTable('uploads', (table: any) => {
table.integer('file_size').notNullable().checkBetween([0, 10485760]);
table.enu('file_type', ['pdf', 'jpeg', 'png']).notNullable();
});
};
export const down = async (knex: any) => {
await knex.schema.alterTable('users', (table: any) => {
table.dropChecks();
});
};
```
## Commands
### Local Development
```bash
# Install dependencies
npm install
# Run validation tests
npm run test:validation
# Run security scan
npm run security:scan
# Start development server
npm run dev
```
### CI Pipeline
```bash
# In CI configuration (.github/workflows/ci.yml)
npm ci
npm run lint
npm run test:validation
npm run test:security
npm run build
```
### Database Migrations
```bash
# Run migrations
npm run migrate:up
# Rollback migrations
npm run migrate:down
```
## Quality Assurance Checklist
- [ ] **VAL-QA-1**: All API endpoints have Zod schema validation middleware
- [ ] **VAL-QA-2**: SQL queries use parameterized statements exclusively (no string concatenation)
- [ ] **VAL-QA-3**: File uploads verified by magic bytes, not just MIME type
- [ ] **VAL-QA-4**: Error responses contain no stack traces or system internals
- [ ] **VAL-QA-5**: Rate limiting applied to all validation-heavy endpoints
- [ ] **VAL-QA-6**: Database constraints enforce NOT NULL, UNIQUE, CHECK on critical fields
- [ ] **VAL-QA-7**: XSS prevention via output encoding and input sanitization
- [ ] **VAL-QA-8**: CSRF protection on all state-changing requests
- [ ] **VAL-QA-9**: Validation failure logging with correlation IDs for monitoring
- [ ] **VAL-QA-10**: Performance benchmarks show validation overhead < 5ms per request
Connectez-vous pour voir le prompt complet
Continuer avec:
En vous connectant, vous acceptez nos Conditions et Confidentialité
Utilisation
Ce prompt est conçu pour être utilisé avec coding. Copiez le contenu ci-dessus et collez-le dans votre outil d’IA préféré.
Pour de meilleurs résultats, personnalisez les espaces réservés (indiqués par des crochets ou des majuscules) selon vos besoins.
Discussion
0 commentaires