Backend: - Add MetricItem, StatsCounts, ColumnDescriptionUpdate, MetricDescriptionUpdate DTOs - Add metric_count to DatasetItem and DatasetDetailResponse - Add server-side filtering via ?filter=unmapped|mapped|linked|all - Add PUT endpoints for column/metric description inline-edit - Add HTML stripping validation (max 2000 chars, plain text) - Add WebSocket dataset.updated event on task completion - RBAC: plugin:migration:WRITE for mutations, READ for reads - 14 pytest tests (stats, filter, metrics, inline-edit, validation, 502/503) Frontend: - Rewrite +page.svelte as split-view orchestrator (387 lines) - StatsBar.svelte — 4 metric tiles with aria-pressed, server-side filter dispatch - DatasetList.svelte — card grid with progress bars, checkboxes, search - DatasetPreview.svelte — presentational detail panel (container fetches) - ColumnsTable.svelte — inline-edit with type chips, bold/italic fallback - MetricsTable.svelte — inline-edit with expression hints - 52 vitest tests across 7 test files - i18n: 11 EN + 11 RU keys (with_mapping/с_маппингом) Spec: - 15 issues resolved (semantic label, filtering, endpoints, conflict, metric_count, RBAC, ID types, ports, i18n, validation, a11y, propagation, resize, perf, ownership) Status: 14/14 backend tests pass, 52/52 frontend tests pass, build succeeds Risk: Low — T051 browser validation pending (non-blocking)
5.9 KiB
Implementation Plan: Dataset Lifecycle Workspace
Branch: 030-dataset-lifecycle-workspace | Date: 2026-05-19 | Spec: spec.md
Input: Feature specification from specs/030-dataset-lifecycle-workspace/spec.md
Summary
Переработка страницы датасетов (/datasets) из табличного вида в полноценное split-view рабочее пространство с: (1) Stats Bar с 4 агрегирующими метриками и серверной фильтрацией через ?filter=, (2) split-view с карточками датасетов слева и детальной панелью справа, (3) inline-редактированием описаний колонок и метрик через новые ss-tools API эндпоинты, (4) WebSocket-автообновлением при завершении фоновых задач, (5) отображением метрик из Superset API. Изменения затрагивают бэкенд (3 новых DTO, 2 новых эндпоинта, модификация 2 существующих) и фронтенд (5 новых компонентов, переписанный +page.svelte).
Technical Context
Language/Version: Python 3.9+ (backend), JavaScript/TypeScript — Svelte 5 runes (frontend) Primary Dependencies: FastAPI 0.104+, Pydantic v2, SQLAlchemy (backend); SvelteKit 2.x, Svelte 5.x, Vite 7.x, Tailwind CSS 3.x (frontend) Storage: PostgreSQL 16 (ss-tools own DB); no schema changes in this feature Testing: pytest (backend), vitest + @testing-library/svelte 5.x (frontend) Target Platform: Linux server (Docker), modern browsers Project Type: web application (FastAPI REST + WebSocket backend, SvelteKit SPA frontend) Performance Goals: Split-view loading state <100ms; dataset detail content according to API latency; inline-edit save <1s; initial Stats Bar load <200ms (stats computed in-memory from already-loaded full dataset list) Constraints: <400 lines per module (INV_7), RBAC on all new endpoints, Tailwind-only styling, Svelte 5 runes only Scale/Scope: 33 datasets (current), single environment (dev), 5 new frontend components, 2 new API endpoints
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Principle | Status | Notes |
|---|---|---|
| Library-First | ✅ N/A | No new library extracted |
| Semantic Protocol (ADR-0002) | ✅ PASS | All C4/C5 contracts use belief_scope/reason/reflect markers. All components use @UX_STATE. @RATIONALE/@REJECTED on key decisions. |
| Orchestrator Pattern (ADR-0003) | ✅ PASS | Backend proxies Superset API; no direct frontend-to-Superset calls |
| Plugin Architecture (ADR-0004) | ✅ PASS | No new plugin; mapping/docs reuse existing MapperPlugin/DocumentationPlugin |
| Auth RBAC (ADR-0005) | ✅ PASS | New endpoints gated: has_permission("plugin:migration","READ") for reads, has_permission("plugin:migration","WRITE") for mutations |
| Frontend Svelte 5 Runes (ADR-0006) | ✅ PASS | All components use $state/$derived/$props/$effect |
| Anti-Erosion (INV_7) | ✅ PASS | New components <400 lines each; no monolithic page |
No blocking conflicts detected.
Project Structure
Documentation (this feature)
specs/030-dataset-lifecycle-workspace/
├── plan.md # This file
├── research.md # 10 research decisions
├── data-model.md # Pydantic schemas, frontend types, state machines
├── quickstart.md # Verification commands
├── contracts/
│ └── modules.md # 16 contracts with complexity classes
├── spec.md # Feature specification (7 user stories, 24 FR)
├── ux_reference.md # UX interaction reference
└── checklists/
└── requirements.md # 44 checklist items
Source Code Changes
backend/
├── src/
│ ├── api/routes/
│ │ └── datasets.py # +MetricItem, +StatsCounts, +2 endpoints, MOD DatasetsResponse
│ └── core/
│ ├── superset_client/
│ │ └── _datasets.py # MOD get_dataset_detail (metrics extraction)
│ └── task_manager.py # MOD on_task_complete (WebSocket event)
└── tests/
└── __tests__/
└── test_datasets.py # +tests for new endpoints and metrics
frontend/
├── src/
│ ├── routes/datasets/
│ │ ├── +page.svelte # REWRITE (split-view orchestrator, ~200 lines)
│ │ ├── StatsBar.svelte # NEW (4 metric tiles, ~80 lines)
│ │ ├── DatasetList.svelte # NEW (card grid, pagination, ~250 lines)
│ │ ├── DatasetPreview.svelte # NEW (detail panel, ~150 lines)
│ │ ├── ColumnsTable.svelte # NEW (inline-edit columns, ~180 lines)
│ │ └── MetricsTable.svelte # NEW (inline-edit metrics, ~150 lines)
│ └── lib/i18n/locales/
│ ├── en/datasets.json # +11 keys
│ └── ru/datasets.json # +11 keys
└── tests/
└── routes/datasets/
└── dataset_workspace.test.js # +component tests for new components
Complexity Tracking
No violations. All components adhere to C1-C5 tier rules per ADR-0002.
| Contract | C | Justification |
|---|---|---|
| MetricItem, StatsCounts, *Update DTOs | 1 | Pure data classes, anchors only |
| DatasetDetailResponse, DatasetsResponse (mod) | 2 | DTOs with @PURPOSE |
| get_dataset_detail (mod), StatsBar, DatasetPreview | 3 | Multi-step logic with @RELATION |
| update_*_description endpoints, get_datasets (mod), DatasetList, ColumnsTable, MetricsTable | 4 | Stateful operations with @PRE/@POST/@SIDE_EFFECT |
| DatasetHub (+page.svelte rewrite) | 5 | Orchestrator with @DATA_CONTRACT, @INVARIANT, decision memory |