## ADDED Requirements

### Requirement: Zod validation on proxy routes
All Next.js proxy routes SHALL validate request bodies using Zod schemas before forwarding to the ML service. If validation fails, the route SHALL return HTTP 400 with `{ "error": "<zod error message>" }` without contacting the ML service.

#### Scenario: Valid predict request
- **WHEN** POST `/api/predict` receives `{ pair: "EURUSD", timeframe: "1H", candles: [{time: 1, open: 1, high: 2, low: 0.5, close: 1.5}] }`
- **THEN** the request passes validation and is forwarded to the ML service

#### Scenario: Invalid predict request
- **WHEN** POST `/api/predict` receives `{ pair: 123, candles: "not-an-array" }`
- **THEN** the route returns HTTP 400 with a Zod validation error message

#### Scenario: Valid training start request
- **WHEN** POST `/api/training/start` receives `{ model_type: "random_forest" }`
- **THEN** the request passes validation and is forwarded

#### Scenario: Valid model load request
- **WHEN** POST `/api/model/load` receives `{ run_id: "abc-123" }`
- **THEN** the request passes validation and is forwarded

#### Scenario: Valid pattern detection request
- **WHEN** POST `/api/patterns/detect` receives `{ candles: [...], patterns: ["CDLENGULFING"] }`
- **THEN** the request passes validation and is forwarded

### Requirement: run_id format validation
All routes and endpoints that accept a `run_id` parameter SHALL validate that the value matches the pattern `/^[a-zA-Z0-9_-]+$/`. If validation fails, the route SHALL return HTTP 400 with `{ "error": "Invalid run_id format" }`.

#### Scenario: Valid run_id in URL path
- **WHEN** DELETE `/api/training/runs/abc-123_v2` is called
- **THEN** the request proceeds normally

#### Scenario: Path traversal attempt in run_id
- **WHEN** DELETE `/api/training/runs/../../admin/delete-all` is called
- **THEN** the route returns HTTP 400 with `{ "error": "Invalid run_id format" }`

#### Scenario: Python service run_id validation
- **WHEN** POST `/model/load` receives `{ run_id: "../../../etc/passwd" }`
- **THEN** the FastAPI endpoint returns HTTP 400 with `{ "detail": "Invalid run_id format" }`

### Requirement: File upload size limit
The `POST /api/upload` route SHALL reject files larger than 10MB. The route SHALL check `file.size` before processing and return HTTP 413 with `{ "error": "File too large. Maximum size is 10MB." }` if exceeded. The route SHALL also limit the number of rows inserted to 500,000.

#### Scenario: File within size limit
- **WHEN** a 5MB CSV file is uploaded
- **THEN** the upload proceeds normally

#### Scenario: File exceeds size limit
- **WHEN** a 15MB CSV file is uploaded
- **THEN** the route returns HTTP 413 with `{ "error": "File too large. Maximum size is 10MB." }`

#### Scenario: Row count limit
- **WHEN** a CSV file contains 600,000 rows
- **THEN** the route returns HTTP 400 with `{ "error": "Too many rows. Maximum is 500,000." }`

### Requirement: Batch prediction input size limit
The FastAPI `/predict/batch` endpoint SHALL validate that the requested date range does not exceed 1 year. If exceeded, the endpoint SHALL return HTTP 400.

#### Scenario: Date range within limit
- **WHEN** POST `/predict/batch` requests a 6-month range
- **THEN** the request proceeds normally

#### Scenario: Date range exceeds limit
- **WHEN** POST `/predict/batch` requests a 2-year range
- **THEN** the endpoint returns HTTP 400 with `{ "detail": "Date range exceeds maximum of 1 year" }`

### Requirement: File type validation on upload
The `POST /api/upload` route SHALL validate that the uploaded file has a `.csv` extension and a text-based MIME type. Other file types SHALL be rejected with HTTP 400.

#### Scenario: Valid CSV upload
- **WHEN** a file named `data.csv` with MIME type `text/csv` is uploaded
- **THEN** the upload proceeds normally

#### Scenario: Invalid file type
- **WHEN** a file named `model.pkl` is uploaded
- **THEN** the route returns HTTP 400 with `{ "error": "Only CSV files are accepted" }`
