# API Contracts: Superset-Style UX Redesign **Feature**: 019-superset-ux-redesign **Date**: 2026-02-09 ## Overview This document defines the API contracts for new endpoints required by the Resource-Centric UI. All endpoints follow existing patterns in the codebase. ## New Endpoints ### 1. Dashboard Hub API #### GET /api/dashboards **Purpose**: Fetch list of dashboards from a specific environment for the Dashboard Hub grid. **Query Parameters**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | env_id | string | Yes | Environment ID to fetch dashboards from | | search | string | No | Filter by title/slug | **Response**: ```json { "dashboards": [ { "id": "uuid-string", "title": "Sales Report", "slug": "sales-2023", "url": "/superset/dashboard/sales-2023", "git_status": { "branch": "main", "sync_status": "OK" | "DIFF" | null }, "last_task": { "task_id": "task-uuid", "status": "SUCCESS" | "RUNNING" | "ERROR" | "WAITING_INPUT" | null } } ] } ``` **Errors**: - `404`: Environment not found - `503`: Superset connection error --- ### 2. Dataset Hub API #### GET /api/datasets **Purpose**: Fetch list of datasets from a specific environment for the Dataset Hub grid. **Query Parameters**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | env_id | string | Yes | Environment ID to fetch datasets from | | search | string | No | Filter by table name | **Response**: ```json { "datasets": [ { "id": "uuid-string", "table_name": "fact_orders", "schema": "public", "database": "Production DB", "mapped_fields": { "total": 20, "mapped": 15 }, "last_task": { "task_id": "task-uuid", "status": "SUCCESS" | null } } ] } ``` --- ### 3. Activity API #### GET /api/activity **Purpose**: Fetch summary of active and recent tasks for the navbar indicator. **Response**: ```json { "active_count": 3, "recent_tasks": [ { "task_id": "task-uuid", "resource_name": "Sales Report", "resource_type": "dashboard", "status": "RUNNING", "started_at": "2026-02-09T10:00:00Z" } ] } ``` --- ### 4. Consolidated Settings API #### GET /api/settings **Purpose**: Fetch all settings categories for the consolidated settings page. **Response**: ```json { "environments": [ { "id": "1", "name": "Development", "url": "http://dev...", "status": "OK" } ], "connections": [ { "id": "1", "name": "Prod Clickhouse", "type": "clickhouse" } ], "llm": { "provider": "openai", "model": "gpt-4", "enabled": true }, "logging": { "level": "INFO", "task_log_level": "DEBUG", "belief_scope_enabled": false } } ``` --- ## WebSocket Events (Existing) The Task Drawer subscribes to existing WebSocket events: ### task:status ```json { "task_id": "uuid", "status": "RUNNING" | "SUCCESS" | "ERROR" | "WAITING_INPUT" } ``` ### task:log ```json { "task_id": "uuid", "timestamp": "2026-02-09T10:00:00Z", "level": "INFO", "source": "plugin", "message": "Starting migration..." } ``` ### task:input_required ```json { "task_id": "uuid", "input_type": "password" | "mapping_selection", "prompt": "Enter database password" } ``` --- ## Module Contracts (Semantic Protocol) ### SidebarStore (frontend/src/lib/stores/sidebar.js) ```javascript // [DEF:SidebarStore:Store] // @TIER: STANDARD // @PURPOSE: Manage sidebar visibility and navigation state // @LAYER: UI // @INVARIANT: isExpanded state is always synced with localStorage // @UX_STATE: Idle -> Sidebar visible with current state // @UX_STATE: Toggling -> Animation plays for 200ms export const sidebarStore = writable({ isExpanded: true, activeCategory: 'dashboards', activeItem: '/dashboards', isMobileOpen: false }); export function toggleSidebar() { /* ... */ } export function setActiveItem(path) { /* ... */ } // [/DEF:SidebarStore] ``` ### TaskDrawerStore (frontend/src/lib/stores/taskDrawer.js) ```javascript // [DEF:TaskDrawerStore:Store] // @TIER: CRITICAL // @PURPOSE: Manage Task Drawer visibility and resource-to-task mapping // @LAYER: UI // @INVARIANT: resourceTaskMap always reflects current task associations // @UX_STATE: Closed -> Drawer hidden, no active task // @UX_STATE: Open -> Drawer visible, logs streaming // @UX_STATE: InputRequired -> Interactive form rendered in drawer export const taskDrawerStore = writable({ isOpen: false, activeTaskId: null, resourceTaskMap: {} }); export function openDrawerForTask(taskId) { /* ... */ } export function closeDrawer() { /* ... */ } export function updateResourceTask(resourceId, taskId, status) { /* ... */ } // [/DEF:TaskDrawerStore] ``` ### ActivityStore (frontend/src/lib/stores/activity.js) ```javascript // [DEF:ActivityStore:Store] // @TIER: STANDARD // @PURPOSE: Track active task count for navbar indicator // @LAYER: UI // @RELATION: DEPENDS_ON -> WebSocket connection export const activityStore = derived(taskDrawerStore, ($drawer) => { const activeCount = Object.values($drawer.resourceTaskMap) .filter(t => t.status === 'RUNNING').length; return { activeCount }; }); // [/DEF:ActivityStore] ```