Related spec: ./spec.md Parent plan: ../plan.md Last synced with code: 2026-04-10
| Layer | Component | File |
|---|---|---|
| Domain Entities | Dataset, CachedData |
domain/entities/dataset/ |
| Domain Port | IDatasetRepository |
domain/ports/dataset/dataset_repository.py |
| Infrastructure Adapter | DatasetRepositorySQLA |
infrastructure/adapters/dataset/dataset_repository_sqla.py |
| Presentation | datasets_router.py |
presentation/http/controllers/datasets/datasets_router.py |
@dataclass
class Dataset:
id: UUID
source_id: str
title: str
description: str
organization: str
portal: str
url: str
download_url: str
format: str
columns: dict # JSON
sample_rows: list[dict] # JSON
tags: str
is_cached: bool
row_count: int | None
created_at: datetime
updated_at: datetime
@dataclass
class CachedData:
id: UUID
dataset_id: UUID
status: str # pending | downloading | ready | error | permanently_failed
table_name: str | None
s3_key: str | None
row_count: int | None
columns_json: dict
retry_count: int
cached_at: datetime | None
updated_at: datetime
DatasetChunk(embedding chunks) lives in006b-ingestion/— it is produced and consumed by the embedding pipeline, not by the catalog endpoints.
| Method | Path | Behavior |
|---|---|---|
| GET | /api/v1/datasets/ |
List indexed datasets (pagination, filter by portal). Returns DatasetSummary rows with columns: list[str] | None parsed from the JSON-array text stored in datasets.columns (helper _parse_columns). Powers the frontend column-aware "ask in chat" prompt. |
| GET | /api/v1/datasets/stats |
Count per portal |
| POST | /api/v1/datasets/scrape/{portal} |
Trigger scrape (admin) — dispatches worker owned by 006b-ingestion |
| GET | /api/v1/datasets/{id}/download |
Download file (redirect to S3 or upstream) |
IDatasetRepository exposes:
save(dataset)— persist a new row.get_by_id(id)— fetch by UUID.get_by_source_id(source_id, portal)— fetch by natural key.list_by_portal(portal, limit, offset)— listing endpoint backing query.upsert(dataset)— idempotent by(source_id, portal)UNIQUE.
Implemented by DatasetRepositorySQLA using async SQLAlchemy 2.0.
datasets(UNIQUEsource_id + portal)cached_datasets(UNIQUEtable_name) — state of the physically cached copy
domain/entities/dataset/domain/ports/dataset/dataset_repository.pyinfrastructure/adapters/dataset/dataset_repository_sqla.pypresentation/http/controllers/datasets/datasets_router.py
None in the catalog sub-module itself. The cache_* dynamic-table exception is owned by 006b-ingestion.
End of plan.md