> ## Documentation Index
> Fetch the complete documentation index at: https://system.muzemus.online/llms.txt
> Use this file to discover all available pages before exploring further.

# Validation

> Input validation patterns, DTO design, and sanitization

## Global validation pipeline

MUZE uses NestJS's `ValidationPipe` applied globally in `main.ts`:

```typescript theme={null}
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  }),
);
```

| Option                       | Effect                                                            |
| ---------------------------- | ----------------------------------------------------------------- |
| `whitelist: true`            | Strips any property not decorated in the DTO class                |
| `forbidNonWhitelisted: true` | Returns 400 if unknown properties are present in the request body |
| `transform: true`            | Automatically transforms plain objects to DTO class instances     |

## DTO pattern

All request bodies are validated against DTO classes using `class-validator` decorators:

```typescript theme={null}
export class CreateEmployeeDto {
  @IsString()
  @IsNotEmpty()
  name: string;

  @IsEmail()
  email: string;

  @IsEnum(EmploymentType)
  employmentType: EmploymentType;

  @IsOptional()
  @IsString()
  jobTitle?: string;

  @IsString()
  @IsNotEmpty()
  storeId: string;
}
```

## Validation rules by type

### String fields

| Decorator           | Purpose                                         |
| ------------------- | ----------------------------------------------- |
| `@IsString()`       | Must be a string                                |
| `@IsNotEmpty()`     | Cannot be empty string                          |
| `@Matches(/regex/)` | Must match a pattern (e.g. order number format) |

### Numeric fields

| Decorator     | Purpose            |
| ------------- | ------------------ |
| `@IsNumber()` | Must be a number   |
| `@Min(0)`     | Minimum value      |
| `@Max(n)`     | Maximum value      |
| `@IsInt()`    | Must be an integer |

### Enum fields

| Decorator           | Purpose                        |
| ------------------- | ------------------------------ |
| `@IsEnum(EnumType)` | Must be one of the enum values |

### Date fields

| Decorator         | Purpose                              |
| ----------------- | ------------------------------------ |
| `@IsDateString()` | Must be a valid ISO 8601 date string |

### Nested objects

| Decorator                | Purpose                                           |
| ------------------------ | ------------------------------------------------- |
| `@ValidateNested()`      | Validates nested DTO objects                      |
| `@Type(() => NestedDto)` | Specifies the nested DTO class for transformation |

### Arrays

| Decorator                         | Purpose                             |
| --------------------------------- | ----------------------------------- |
| `@IsArray()`                      | Must be an array                    |
| `@ValidateNested({ each: true })` | Validates each element in the array |

## Query parameter validation

Query parameters are also validated via DTOs:

```typescript theme={null}
@Get()
async findAll(@Query() query: ListEmployeesDto) {
  // query is validated and transformed
}
```

```typescript theme={null}
export class ListEmployeesDto {
  @IsOptional()
  @IsString()
  search?: string;

  @IsOptional()
  @IsEnum(SortOrder)
  sortOrder?: SortOrder;

  @IsOptional()
  @Min(1)
  page?: number;
}
```

## File upload validation

File uploads use `multipart/form-data` and are validated at the service level:

* File type checking (CSV for imports, PDF for documents)
* File size limits enforced by the 20MB Express body limit
* CSV column headers validated against expected schema
* Invalid rows are skipped with error reporting (imports are partial-failure tolerant)

## Error response format

Validation errors return a consistent 400 response:

```json theme={null}
{
  "statusCode": 400,
  "message": [
    "name should not be empty",
    "email must be an email"
  ],
  "error": "Bad Request"
}
```

## What is not validated

| Area              | Current state                                          |
| ----------------- | ------------------------------------------------------ |
| Request body size | Limited to 20MB by `express.json({ limit: '20mb' })`   |
| URL length        | No explicit limit; browser/server defaults apply       |
| Rate limiting     | 100 requests/minute via `@nestjs/throttler`            |
| SQL injection     | Prevented by Prisma's parameterized queries            |
| XSS               | Prevented by React's default escaping + Helmet headers |
