356 lines
7.3 KiB
Markdown
356 lines
7.3 KiB
Markdown
# API Contracts: Migration UI Improvements
|
|
|
|
**Date**: 2025-12-27 | **Status**: Implemented
|
|
|
|
## Overview
|
|
|
|
This document defines the API contracts for the Migration UI Improvements feature. All endpoints follow RESTful conventions and use standard HTTP status codes.
|
|
|
|
## Base URL
|
|
|
|
`/api/` - All endpoints are relative to the API base URL
|
|
|
|
## Authentication
|
|
|
|
All endpoints require authentication using the existing session mechanism.
|
|
|
|
## Endpoints
|
|
|
|
### 1. List Migration Tasks
|
|
|
|
**Endpoint**: `GET /api/tasks`
|
|
|
|
**Purpose**: Retrieve a paginated list of migration tasks
|
|
|
|
**Parameters**:
|
|
```
|
|
limit: integer (query, optional) - Number of tasks to return (default: 10, max: 50)
|
|
offset: integer (query, optional) - Pagination offset (default: 0)
|
|
status: string (query, optional) - Filter by task status (PENDING, RUNNING, SUCCESS, FAILED, AWAITING_INPUT, AWAITING_MAPPING)
|
|
```
|
|
|
|
**Response**: `200 OK`
|
|
|
|
**Content-Type**: `application/json`
|
|
|
|
**Response Body**:
|
|
```json
|
|
{
|
|
"tasks": [
|
|
{
|
|
"id": "string (uuid)",
|
|
"type": "string",
|
|
"status": "string (enum)",
|
|
"start_time": "string (iso8601)",
|
|
"end_time": "string (iso8601) | null",
|
|
"requires_input": "boolean"
|
|
}
|
|
],
|
|
"total": "integer",
|
|
"limit": "integer",
|
|
"offset": "integer"
|
|
}
|
|
```
|
|
|
|
**Example Request**:
|
|
```
|
|
GET /api/tasks?limit=5&offset=0
|
|
```
|
|
|
|
**Example Response**:
|
|
```json
|
|
{
|
|
"tasks": [
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"type": "migration",
|
|
"status": "RUNNING",
|
|
"start_time": "2025-12-27T09:47:12.000Z",
|
|
"end_time": null,
|
|
"requires_input": false
|
|
},
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
"type": "migration",
|
|
"status": "AWAITING_INPUT",
|
|
"start_time": "2025-12-27T09:45:00.000Z",
|
|
"end_time": null,
|
|
"requires_input": true
|
|
}
|
|
],
|
|
"total": 2,
|
|
"limit": 5,
|
|
"offset": 0
|
|
}
|
|
```
|
|
|
|
**Error Responses**:
|
|
- `401 Unauthorized` - Authentication required
|
|
- `400 Bad Request` - Invalid parameters
|
|
|
|
### 2. Get Task Logs
|
|
|
|
**Endpoint**: `GET /tasks/{task_id}/logs`
|
|
|
|
**Purpose**: Retrieve detailed logs for a specific task
|
|
|
|
**Parameters**: None
|
|
|
|
**Response**: `200 OK`
|
|
|
|
**Content-Type**: `application/json`
|
|
|
|
**Response Body**:
|
|
```json
|
|
{
|
|
"task_id": "string (uuid)",
|
|
"status": "string (enum)",
|
|
"logs": [
|
|
{
|
|
"timestamp": "string (iso8601)",
|
|
"level": "string",
|
|
"message": "string",
|
|
"context": "object | null"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Example Request**:
|
|
```
|
|
GET /api/tasks/550e8400-e29b-41d4-a716-446655440001/logs
|
|
```
|
|
|
|
**Example Response**:
|
|
```json
|
|
{
|
|
"task_id": "550e8400-e29b-41d4-a716-446655440001",
|
|
"status": "AWAITING_INPUT",
|
|
"logs": [
|
|
{
|
|
"timestamp": "2025-12-27T09:45:00.000Z",
|
|
"level": "INFO",
|
|
"message": "Starting migration",
|
|
"context": null
|
|
},
|
|
{
|
|
"timestamp": "2025-12-27T09:47:12.000Z",
|
|
"level": "ERROR",
|
|
"message": "API error during upload",
|
|
"context": {
|
|
"error": "Must provide a password for the database",
|
|
"database": "PostgreSQL"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Error Responses**:
|
|
- `401 Unauthorized` - Authentication required
|
|
- `404 Not Found` - Task not found
|
|
- `403 Forbidden` - Access denied to this task
|
|
|
|
### 3. Resume Task with Input
|
|
|
|
**Endpoint**: `POST /tasks/{task_id}/resume`
|
|
|
|
**Purpose**: Provide required input and resume a paused task
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"passwords": {
|
|
"database_name": "password"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response**: `200 OK`
|
|
|
|
**Content-Type**: `application/json`
|
|
|
|
**Response Body**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Task resumed successfully"
|
|
}
|
|
```
|
|
|
|
**Example Request**:
|
|
```
|
|
POST /api/tasks/550e8400-e29b-41d4-a716-446655440001/resume
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"passwords": {
|
|
"PostgreSQL": "securepassword123"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Example Response**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Task resumed successfully"
|
|
}
|
|
```
|
|
|
|
**Error Responses**:
|
|
- `401 Unauthorized` - Authentication required
|
|
- `404 Not Found` - Task not found
|
|
- `400 Bad Request` - Invalid request body or missing required fields
|
|
- `409 Conflict` - Task not in AWAITING_INPUT state or already completed
|
|
- `422 Unprocessable Entity` - Invalid password provided
|
|
|
|
### 4. Get Task Details (Optional)
|
|
|
|
**Endpoint**: `GET /tasks/{task_id}`
|
|
|
|
**Purpose**: Get detailed information about a specific task
|
|
|
|
**Parameters**: None
|
|
|
|
**Response**: `200 OK`
|
|
|
|
**Content-Type**: `application/json`
|
|
|
|
**Response Body**:
|
|
```json
|
|
{
|
|
"id": "string (uuid)",
|
|
"type": "string",
|
|
"status": "string (enum)",
|
|
"start_time": "string (iso8601)",
|
|
"end_time": "string (iso8601) | null",
|
|
"requires_input": "boolean",
|
|
"input_request": "object | null"
|
|
}
|
|
```
|
|
|
|
**Example Response**:
|
|
```json
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
"type": "migration",
|
|
"status": "AWAITING_INPUT",
|
|
"start_time": "2025-12-27T09:45:00.000Z",
|
|
"end_time": null,
|
|
"requires_input": true,
|
|
"input_request": {
|
|
"type": "database_password",
|
|
"databases": ["PostgreSQL"],
|
|
"error_message": "Must provide a password for the database"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Data Types
|
|
|
|
### TaskStatus Enum
|
|
|
|
```
|
|
PENDING
|
|
RUNNING
|
|
SUCCESS
|
|
FAILED
|
|
AWAITING_INPUT
|
|
```
|
|
|
|
### LogLevel Enum
|
|
|
|
```
|
|
INFO
|
|
WARNING
|
|
ERROR
|
|
DEBUG
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### Standard Error Format
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "string",
|
|
"message": "string",
|
|
"details": "object | null"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Common Error Codes
|
|
|
|
- `invalid_task_id`: Task ID is invalid or not found
|
|
- `task_not_awaiting_input`: Task is not in AWAITING_INPUT state
|
|
- `invalid_password`: Provided password is invalid
|
|
- `unauthorized`: Authentication required
|
|
- `bad_request`: Invalid request parameters
|
|
|
|
## WebSocket Integration
|
|
|
|
### Task Status Updates
|
|
|
|
**Channel**: `/ws/tasks/{task_id}/status`
|
|
|
|
**Message Format**:
|
|
```json
|
|
{
|
|
"event": "status_update",
|
|
"task_id": "string (uuid)",
|
|
"status": "string (enum)",
|
|
"timestamp": "string (iso8601)"
|
|
}
|
|
```
|
|
|
|
### Task Log Updates
|
|
|
|
**Channel**: `/ws/tasks/{task_id}/logs`
|
|
|
|
**Message Format**:
|
|
```json
|
|
{
|
|
"event": "log_update",
|
|
"task_id": "string (uuid)",
|
|
"log": {
|
|
"timestamp": "string (iso8601)",
|
|
"level": "string",
|
|
"message": "string",
|
|
"context": "object | null"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Rate Limiting
|
|
|
|
- Maximum 10 requests per minute per user for task list endpoint
|
|
- Maximum 30 requests per minute per user for task details/logs endpoints
|
|
- No rate limiting for WebSocket connections
|
|
|
|
## Versioning
|
|
|
|
All endpoints are versioned using the `Accept` header:
|
|
- `Accept: application/vnd.api.v1+json` - Current version
|
|
|
|
## Security Considerations
|
|
|
|
1. **Authentication**: All endpoints require valid session authentication
|
|
2. **Authorization**: Users can only access their own tasks
|
|
3. **Password Handling**: Passwords are not stored permanently, only used for immediate task resumption
|
|
4. **Input Validation**: All inputs are validated according to defined schemas
|
|
5. **Rate Limiting**: Prevents abuse of API endpoints
|
|
|
|
## Implementation Notes
|
|
|
|
1. **Pagination**: Default limit of 10 tasks, maximum of 50
|
|
2. **Sorting**: Tasks are sorted by start_time descending by default
|
|
3. **Caching**: Task list responses can be cached for 5 seconds
|
|
4. **WebSocket**: Use existing WebSocket infrastructure for real-time updates
|
|
5. **Error Recovery**: Failed task resumptions can be retried with corrected input
|
|
|
|
## OpenAPI Specification
|
|
|
|
A complete OpenAPI 3.0 specification is available in the repository at `specs/008-migration-ui-improvements/contracts/openapi.yaml`. |