Sync user-accounts delta specs to main specs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marko Djordjevic 2026-02-20 18:50:14 +01:00
parent 34d58948a3
commit 448b67199f
9 changed files with 703 additions and 6 deletions

View file

@ -230,3 +230,117 @@ All `fetch()` calls in frontend components (`page.tsx`, `CandleChart.tsx`) SHALL
#### Scenario: Error response handled
- **WHEN** a fetch call returns HTTP 500
- **THEN** the code detects `!response.ok` and shows an error message instead of attempting JSON parse
## MODIFIED Requirements (user-accounts)
### 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 (user-accounts)
### 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