## MODIFIED Requirements ### Requirement: Predict proxy endpoint The system SHALL provide a `POST /api/predict` Next.js API route that proxies requests to the Python inference service at `${INFERENCE_API_URL}/predict`. The route SHALL require authentication via `getAuthUser()`. The route SHALL forward the request body (pair, timeframe, candles array) and include the `X-User-ID` header with the authenticated user's UUID. If the inference service is unreachable, the route SHALL return HTTP 503 with `{ "error": "Inference service unavailable" }`. #### Scenario: Successful prediction proxy - **WHEN** an authenticated user calls POST /api/predict with valid candle data and the Python service is running - **THEN** the route forwards the request with `X-User-ID` header and returns the prediction response with HTTP 200 #### Scenario: Unauthenticated prediction request - **WHEN** POST /api/predict is called without authentication - **THEN** the route returns HTTP 401 with `{ "error": "Unauthorized" }` #### Scenario: Inference service down - **WHEN** POST /api/predict is called but the Python inference service is unreachable - **THEN** the route returns HTTP 503 with `{ "error": "Inference service unavailable" }` #### Scenario: Inference service error - **WHEN** the Python inference service returns an error status (4xx or 5xx) - **THEN** the route forwards the error status and message to the client ### Requirement: Batch predict proxy endpoint The system SHALL provide a `POST /api/predict/batch` Next.js API route that proxies batch prediction requests to `${INFERENCE_API_URL}/predict/batch`. The route SHALL require authentication and include the `X-User-ID` header. #### Scenario: Successful batch prediction - **WHEN** an authenticated user calls POST /api/predict/batch with valid parameters - **THEN** the route forwards to the inference service with `X-User-ID` header and returns the response #### Scenario: Timeout on large batch - **WHEN** the batch prediction takes longer than INFERENCE_BATCH_TIMEOUT - **THEN** the route returns HTTP 504 with `{ "error": "Batch prediction timed out" }` ### Requirement: Training proxy endpoints The Next.js API SHALL provide proxy routes for training operations: `POST /api/training/start`, `GET /api/training/runs`, and `GET /api/training/dataset-info`. All training proxy routes SHALL require authentication and include the `X-User-ID` header. #### Scenario: Proxy training start - **WHEN** an authenticated user calls POST /api/training/start - **THEN** the route forwards to the FastAPI service with `X-User-ID` header #### Scenario: Proxy training runs - **WHEN** an authenticated user calls GET /api/training/runs - **THEN** the route forwards to the FastAPI service with `X-User-ID` header and returns the run list ### Requirement: Model load proxy The Next.js API SHALL provide a `POST /api/model/load` route that proxies to the FastAPI `/model/load` endpoint. The route SHALL require authentication and include the `X-User-ID` header. #### Scenario: Proxy model load - **WHEN** an authenticated user calls POST /api/model/load with a run_id - **THEN** the route forwards to the FastAPI service with `X-User-ID` header ### Requirement: Model info proxy endpoint The system SHALL provide a `GET /api/model/info` Next.js API route that proxies to `${INFERENCE_API_URL}/model/info`. The route SHALL require authentication and include the `X-User-ID` header. #### Scenario: Successful model info - **WHEN** an authenticated user calls GET /api/model/info - **THEN** the route returns the model metadata JSON #### Scenario: No model available - **WHEN** GET /api/model/info is called and the inference service returns 503 - **THEN** the route returns HTTP 503 with `{ "error": "No model available" }` ### Requirement: Pattern detection proxy The Next.js API SHALL provide a `POST /api/patterns/detect` route that proxies to the FastAPI `/patterns/detect` endpoint. The route SHALL require authentication and include the `X-User-ID` header. #### Scenario: Proxy pattern detection - **WHEN** an authenticated user calls POST /api/patterns/detect - **THEN** the route forwards the request with `X-User-ID` header and returns the response ### Requirement: Available patterns proxy The Next.js API SHALL provide a `GET /api/patterns/available` route that proxies to the FastAPI `/patterns/available` endpoint. The route SHALL require authentication. #### Scenario: Proxy available patterns - **WHEN** an authenticated user calls GET /api/patterns/available - **THEN** the route forwards to the FastAPI service and returns the pattern list ### Requirement: Bulk delete by source The Next.js API `DELETE /api/span-annotations` endpoint SHALL require authentication and scope deletion by the authenticated user. When `source` is provided, all span annotations matching that source (and optionally `label` filter) for the current chart belonging to the authenticated user SHALL be deleted. #### Scenario: Bulk delete TA-Lib annotations - **WHEN** an authenticated user calls `DELETE /api/span-annotations?chartId=1&source=talib` - **THEN** all span annotations with `source: "talib"` for chart 1 belonging to that user are deleted #### Scenario: Bulk delete by source and label - **WHEN** an authenticated user calls `DELETE /api/span-annotations?chartId=1&source=talib&label=Engulfing` - **THEN** only TA-Lib annotations containing "Engulfing" for chart 1 belonging to that user are deleted ## ADDED Requirements ### Requirement: Auth guard on all data API routes All existing data API routes (`/api/upload`, `/api/candles`, `/api/annotations`, `/api/annotation-types`, `/api/charts`, `/api/span-annotations`, `/api/span-label-types`, `/api/export`) SHALL call `getAuthUser()` at the top. If the user is not authenticated, the route SHALL return HTTP 401. #### Scenario: Unauthenticated data API access - **WHEN** any data API route is called without authentication - **THEN** the route returns HTTP 401 with `{ "error": "Unauthorized" }` #### Scenario: Authenticated data API access - **WHEN** any data API route is called with valid authentication - **THEN** the route proceeds with queries scoped to the authenticated user's ID ### Requirement: User-scoped queries in all data routes All Drizzle queries in data API routes SHALL include a `user_id` filter matching the authenticated user. INSERT operations SHALL set `user_id` to the authenticated user's UUID. #### Scenario: GET queries filtered by user - **WHEN** an authenticated user requests data (charts, annotations, annotation types, etc.) - **THEN** the query includes `.where(eq(table.user_id, user.id))` or equivalent join condition #### Scenario: INSERT operations set user_id - **WHEN** an authenticated user creates new data (upload, create annotation, etc.) - **THEN** the inserted row has `user_id` set to the authenticated user's UUID #### Scenario: Cross-user data isolation - **WHEN** user A requests data - **THEN** no data belonging to user B is returned