- Synced 14 capability delta specs to main specs - Created 6 new main specs: api-authentication, error-boundary, input-validation, security-headers, shared-types - Updated 8 existing specs with security, validation, and performance requirements - Archived change to openspec/changes/archive/2026-02-20-code-review-fix/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
76 lines
3.9 KiB
Markdown
76 lines
3.9 KiB
Markdown
## 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" }`
|