# Data Model: Migration UI Improvements **Date**: 2025-12-27 | **Status**: Draft ## Entities ### 1. Task (Extended) **Source**: `backend/src/core/task_manager.py` **Fields**: - `id: UUID` - Unique task identifier - `type: str` - Task type (e.g., "migration") - `status: TaskStatus` - Current status (extended enum) - `start_time: datetime` - When task was created - `end_time: datetime | None` - When task completed (if applicable) - `logs: List[LogEntry]` - Task execution logs - `context: Dict` - Task-specific data - `input_required: bool` - Whether task is awaiting user input - `input_request: Dict | None` - Details about required input (for AWAITING_INPUT state) **New Status Values**: - `AWAITING_INPUT` - Task is paused waiting for user input (e.g., password) **Relationships**: - Has many: `LogEntry` - Belongs to: `Migration` (if migration task) **Validation Rules**: - `id` must be unique and non-null - `status` must be valid TaskStatus enum value - `start_time` must be set on creation - `input_request` required when status is `AWAITING_INPUT` **State Transitions**: ```mermaid graph LR PENDING --> RUNNING RUNNING --> SUCCESS RUNNING --> FAILED RUNNING --> AWAITING_INPUT AWAITING_INPUT --> RUNNING AWAITING_INPUT --> FAILED ``` ### 2. LogEntry **Source**: Existing in codebase **Fields**: - `timestamp: datetime` - When log entry was created - `level: str` - Log level (INFO, WARNING, ERROR, etc.) - `message: str` - Log message - `context: Dict | None` - Additional context data **Validation Rules**: - `timestamp` must be set - `level` must be valid log level - `message` must be non-empty ### 3. DatabasePasswordRequest (New) **Source**: New entity for password prompts **Fields**: - `database_name: str` - Name of database requiring password - `connection_string: str | None` - Partial connection string (without password) - `error_message: str | None` - Original error message - `attempt_count: int` - Number of password attempts **Validation Rules**: - `database_name` must be non-empty - `attempt_count` must be >= 0 **Relationships**: - Embedded in: `Task.input_request` ### 4. TaskListResponse (API DTO) **Fields**: - `tasks: List[TaskSummary]` - List of task summaries - `total: int` - Total number of tasks - `limit: int` - Pagination limit - `offset: int` - Pagination offset ### 5. TaskSummary (API DTO) **Fields**: - `id: UUID` - Task ID - `type: str` - Task type - `status: str` - Current status - `start_time: datetime` - Start time - `end_time: datetime | None` - End time (if completed) - `requires_input: bool` - Whether task needs user input ### 6. TaskLogResponse (API DTO) **Fields**: - `task_id: UUID` - Task ID - `logs: List[LogEntry]` - Task logs - `status: str` - Current task status ### 7. PasswordPromptRequest (API DTO) **Fields**: - `task_id: UUID` - Task ID - `passwords: Dict[str, str]` - Database name to password mapping **Validation Rules**: - `task_id` must exist and be in AWAITING_INPUT state - All required databases must be provided ## API Contracts ### 1. GET /api/tasks - List Tasks **Purpose**: Retrieve list of recent migration tasks **Parameters**: - `limit: int` (query, optional) - Pagination limit (default: 10) - `offset: int` (query, optional) - Pagination offset (default: 0) - `status: str` (query, optional) - Filter by status **Response**: `TaskListResponse` **Example**: ```json { "tasks": [ { "id": "abc-123", "type": "migration", "status": "RUNNING", "start_time": "2025-12-27T09:47:12Z", "end_time": null, "requires_input": false } ], "total": 1, "limit": 10, "offset": 0 } ``` ### 2. GET /api/tasks/{task_id}/logs - Get Task Logs **Purpose**: Retrieve detailed logs for a specific task **Parameters**: None **Response**: `TaskLogResponse` **Example**: ```json { "task_id": "abc-123", "status": "AWAITING_INPUT", "logs": [ { "timestamp": "2025-12-27T09:47:12Z", "level": "ERROR", "message": "Must provide a password for the database", "context": { "database": "PostgreSQL" } } ] } ``` ### 3. POST /api/tasks/{task_id}/resume - Resume Task with Input **Purpose**: Provide required input and resume a paused task **Request Body**: `PasswordPromptRequest` **Response**: ```json { "success": true, "message": "Task resumed successfully" } ``` **Error Responses**: - `404 Not Found` - Task not found - `400 Bad Request` - Invalid input or task not in AWAITING_INPUT state - `409 Conflict` - Task already completed or failed ## Database Schema Changes ### Task Persistence (SQLite) **Table**: `persistent_tasks` **Columns**: - `id TEXT PRIMARY KEY` - Task ID - `status TEXT NOT NULL` - Task status - `created_at TEXT NOT NULL` - Creation timestamp - `updated_at TEXT NOT NULL` - Last update timestamp - `input_request JSON` - Serialized input request data - `context JSON` - Serialized task context **Indexes**: - `idx_status` on `status` column - `idx_created_at` on `created_at` column ## Event Flow ### Normal Task Execution ```mermaid sequenceDiagram participant UI participant API participant TaskManager participant MigrationPlugin UI->>API: Start migration API->>TaskManager: Create task TaskManager->>MigrationPlugin: Execute MigrationPlugin->>TaskManager: Update status (RUNNING) MigrationPlugin->>TaskManager: Add logs MigrationPlugin->>TaskManager: Update status (SUCCESS/FAILED) ``` ### Task with Password Requirement ```mermaid sequenceDiagram participant UI participant API participant TaskManager participant MigrationPlugin UI->>API: Start migration API->>TaskManager: Create task TaskManager->>MigrationPlugin: Execute MigrationPlugin->>TaskManager: Update status (RUNNING) MigrationPlugin->>TaskManager: Detect password error TaskManager->>TaskManager: Update status (AWAITING_INPUT) TaskManager->>API: Persist task (if needed) API->>UI: Task status update UI->>API: Get task logs API->>UI: Return logs with error UI->>User: Show password prompt User->>UI: Provide password UI->>API: POST /tasks/{id}/resume API->>TaskManager: Resume task with password TaskManager->>MigrationPlugin: Continue execution MigrationPlugin->>TaskManager: Update status (RUNNING) MigrationPlugin->>TaskManager: Complete task ``` ## Validation Rules ### Task Creation - Task ID must be unique - Start time must be set - Initial status must be PENDING ### Task State Transitions - Only RUNNING tasks can transition to AWAITING_INPUT - Only AWAITING_INPUT tasks can be resumed - Completed tasks (SUCCESS/FAILED) cannot be modified ### Password Input - All required databases must be provided - Passwords must meet minimum complexity requirements - Invalid passwords trigger new error and prompt again ## Implementation Notes 1. **Task Persistence**: Only tasks in AWAITING_INPUT state will be persisted to handle backend restarts 2. **Error Detection**: Specific pattern matching for Superset "Must provide a password" errors 3. **UI Integration**: Real-time updates using existing WebSocket infrastructure 4. **Security**: Passwords are not permanently stored, only used for immediate task resumption 5. **Performance**: Basic pagination for task history to handle growth ## Open Questions None - All design decisions have been documented and validated against requirements.