Skip to content

Reference: DTOs

Request and response data structures.

Overview

DTOs (Data Transfer Objects) are frozen dataclasses used for communication between layers. They contain no business logic and use primitive types for serialization compatibility. String fields for enum-like values (status, severity, intent, etc.) are intentional for JSON/API compatibility.


Query Request DTOs

QueryRequest

Stability: Stable

High-level query request from UI/API. Supports multi-data-product queries with combine operations.

@dataclass(frozen=True)
class QueryRequest:
    intent: QueryIntentStr  # "NUMBER" | "CHART" | "TABLE" | "MAP"
    selections: tuple[DataProductSelectionRequest, ...]
    combine: CombineRequest | None = None
    presentation: PresentationRequest | None = None

    @property
    def is_cross_dataset(self) -> bool:
        """Check if this request involves multiple data products."""

DataProductSelectionRequest

Stability: Stable

Selection from a single data product within a query.

@dataclass(frozen=True)
class DataProductSelectionRequest:
    data_product_id: str
    dimensions: tuple[str, ...]      # Variable names
    metrics: tuple[MetricRequest, ...]
    filters: tuple[FilterRequest, ...]
    group_by: tuple[str, ...]        # Variable names (defaults to dimensions)

MetricRequest

Stability: Stable

@dataclass(frozen=True)
class MetricRequest:
    variable: str
    aggregation: AggregationStr  # "SUM" | "AVG" | "MIN" | "MAX" | "COUNT" | "NONE"

FilterRequest

Stability: Stable

@dataclass(frozen=True)
class FilterRequest:
    variable: str
    op: FilterOpStr  # "EQ" | "IN" | "GT" | "GTE" | "LT" | "LTE"
    values: tuple[str, ...]

CombineRequest

Stability: Stable

Request to combine multiple data product selections.

@dataclass(frozen=True)
class CombineRequest:
    mode: CombineModeStr  # "COMPARE" | "JOIN"
    on: tuple[str, ...]   # Semantic join keys (dimension names)
    labels: tuple[str, ...] | None = None

PresentationRequest

Stability: Stable

@dataclass(frozen=True)
class PresentationRequest:
    format: PresentationFormatStr  # "NUMBER" | "SERIES" | "CHOROPLETH" | "TABLE"
    units: str | None = None
    include_disclosures: bool = True

Semantic Query DTOs

SemanticQueryRequest (alias: QuerySpec)

Stability: Stable

Domain representation of a semantic query specification.

@dataclass(frozen=True)
class QuerySpec:
    metrics: tuple[str, ...]           # Metric names (deduplicated)
    group_by: tuple[GroupBySpec, ...]
    filters: tuple[FilterSpec, ...]
    order_by: tuple[OrderBySpec, ...]
    limit: int | None
    options: QueryOptions

GroupBySpec

Stability: Stable

@dataclass(frozen=True)
class GroupBySpec:
    dimension: str
    attribute: str
    level: str | None      # For geo dimensions
    grain: str | None      # For time dimensions

FilterSpec

Stability: Stable

@dataclass(frozen=True)
class FilterSpec:
    dimension: str
    attribute: str
    op: FilterOperator  # EQ, NE, IN, NOT_IN, BETWEEN, GT, GTE, LT, LTE
    value: FilterValue  # ScalarValue | Sequence | tuple[ScalarValue, ScalarValue]

OrderBySpec

Stability: Stable

@dataclass(frozen=True)
class OrderBySpec:
    field: str
    direction: SortOrder  # ASC | DESC

QueryOptions

Stability: Stable

@dataclass(frozen=True)
class QueryOptions:
    strict: bool = False           # Elevate warnings to errors
    explain: bool = False          # Include explain information
    allow_incomparable: bool = False

Validation DTOs

ValidationResultDTO

Stability: Stable

Result of validating a query plan.

@dataclass(frozen=True)
class ValidationResultDTO:
    query_id: str
    status: SeverityLevel      # "ALLOW" | "WARN" | "REQUIRE_ACK" | "BLOCK"
    issues: tuple[IssueDTO, ...]
    disclosures: tuple[DisclosureDTO, ...]
    can_execute: bool          # Computed: status in (ALLOW, WARN, REQUIRE_ACK)
    requires_acknowledgment: bool  # Computed: status == REQUIRE_ACK

IssueDTO

Stability: Stable

@dataclass(frozen=True)
class IssueDTO:
    code: str
    severity: SeverityLevel  # "ALLOW" | "WARN" | "REQUIRE_ACK" | "BLOCK"
    message: str
    details: dict[str, IssueDetail]  # IssueDetail = str | int | float | bool | None
    remediations: tuple[RemediationDTO, ...]

DisclosureDTO

Stability: Stable

@dataclass(frozen=True)
class DisclosureDTO:
    disclosure_type: str
    text: str

RemediationDTO

Stability: Stable

@dataclass(frozen=True)
class RemediationDTO:
    action: str
    label: str
    required_fields: tuple[str, ...]

AcknowledgmentRequest

Stability: Stable

@dataclass(frozen=True)
class AcknowledgmentRequest:
    query_id: str
    acknowledged_issue_codes: tuple[str, ...]
    user_id: str | None = None

AcknowledgmentResultDTO

Stability: Stable

@dataclass(frozen=True)
class AcknowledgmentResultDTO:
    query_id: str
    acknowledged: bool
    can_execute: bool
    message: str | None = None

SemanticValidationResultDTO

Stability: Stable

Result for semantic query validation.

@dataclass(frozen=True)
class SemanticValidationResultDTO:
    is_valid: bool
    errors: tuple[SemanticIssueDTO, ...]    # Blocking issues
    warnings: tuple[SemanticIssueDTO, ...]  # Non-blocking issues
    resolved_metrics: tuple[str, ...]

SemanticIssueDTO

Stability: Stable

@dataclass(frozen=True)
class SemanticIssueDTO:
    code: str
    severity: str
    message: str
    details: dict[str, Any]

Result DTOs

QueryResultDTO

Stability: Stable

Query execution result.

@dataclass(frozen=True)
class QueryResultDTO:
    query_id: str
    columns: tuple[ColumnDTO, ...]
    rows: tuple[dict[str, CellValue], ...]  # CellValue = str | int | float | bool | None
    disclosures: tuple[DisclosureDTO, ...]
    metadata: ResultMetadataDTO

    @property
    def row_count(self) -> int: ...
    @property
    def column_names(self) -> list[str]: ...

ColumnDTO

Stability: Stable

@dataclass(frozen=True)
class ColumnDTO:
    name: str
    label: str
    data_type: DataTypeStr    # "STRING" | "INT" | "FLOAT" | "DATE" | "BOOL"
    role: VariableRoleStr     # "DIMENSION" | "MEASURE" | "INDICATOR"
    unit: str | None = None
    is_suppressed_column: bool = False

ResultMetadataDTO

Stability: Stable

@dataclass(frozen=True)
class ResultMetadataDTO:
    total_rows: int
    execution_time_ms: int
    data_sources: tuple[str, ...]
    reference_periods: tuple[str, ...]
    suppressed_count: int = 0

QueryErrorDTO

Stability: Stable

@dataclass(frozen=True)
class QueryErrorDTO:
    query_id: str
    error_code: str
    message: str
    details: dict[str, CellValue] | None = None

SemanticQueryResultDTO

Stability: Stable

Response for semantic queries.

@dataclass(frozen=True)
class SemanticQueryResultDTO:
    data: tuple[dict[str, Any], ...]
    schema: ResultSchemaDTO
    provenance: ProvenanceDTO
    warnings: tuple[SemanticIssueDTO, ...]
    explain: QueryExplainInfoDTO | None

ResultSchemaDTO

Stability: Stable

@dataclass(frozen=True)
class ResultSchemaDTO:
    fields: tuple[ResultFieldSchema, ...]

ResultFieldSchema

Stability: Stable

@dataclass(frozen=True)
class ResultFieldSchema:
    name: str
    type: str
    unit: str | None

ProvenanceDTO

Stability: Stable

@dataclass(frozen=True)
class ProvenanceDTO:
    metrics: dict[str, MetricProvenanceDTO]
    datasets: tuple[str, ...]
    materialization_used: str | None

MetricProvenanceDTO

Stability: Stable

@dataclass(frozen=True)
class MetricProvenanceDTO:
    definition_hash: str
    methodology_id: str | None
    methodology_version: str | None

Explain DTOs

ExplainResultDTO

Stability: Stable

Response for ExplainSemanticQueryUseCase.

@dataclass(frozen=True)
class ExplainResultDTO:
    validation_trace: str
    logical_plan_json: dict[str, Any]
    logical_plan_pretty: str
    compiled_sql: str
    materialization_decision: MaterializationDecision

QueryExplainInfoDTO

Stability: Stable

@dataclass(frozen=True)
class QueryExplainInfoDTO:
    validation_trace: str
    logical_plan_summary: str
    compiled_sql: str
    materialization_decision: str

Catalog Read DTOs

StudyDTO

Stability: Stable

@dataclass(frozen=True)
class StudyDTO:
    id: str
    name: str
    publisher: str
    description: str | None
    dataset_count: int

UniverseDTO

Stability: Stable

@dataclass(frozen=True)
class UniverseDTO:
    id: str
    name: str
    definition: str
    inclusions: tuple[str, ...]
    exclusions: tuple[str, ...]

ConceptDTO

Stability: Stable

@dataclass(frozen=True)
class ConceptDTO:
    id: str
    name: str
    definition: str
    unit: str | None
    aliases: tuple[str, ...]

GeographyVersionDTO

Stability: Stable

@dataclass(frozen=True)
class GeographyVersionDTO:
    id: str
    system_id: str
    name: str
    levels: tuple[str, ...]
    valid_from: date | None
    valid_to: date | None

DatasetSummaryDTO

Stability: Stable

@dataclass(frozen=True)
class DatasetSummaryDTO:
    id: str
    name: str
    study_id: str
    study_name: str
    geography_system_id: str
    data_product_count: int

DataProductSummaryDTO

Stability: Stable

@dataclass(frozen=True)
class DataProductSummaryDTO:
    id: str
    name: str
    kind: DataProductKindStr  # "FACT" | "INDICATOR"
    variable_count: int
    is_public: bool

VariableSummaryDTO

Stability: Stable

@dataclass(frozen=True)
class VariableSummaryDTO:
    id: str
    name: str
    role: VariableRoleStr   # "DIMENSION" | "MEASURE" | "INDICATOR"
    data_type: DataTypeStr  # "STRING" | "INT" | "FLOAT" | "DATE" | "BOOL"
    has_indicator_definition: bool

DatasetDocDTO

Stability: Stable

Full dataset documentation.

@dataclass(frozen=True)
class DatasetDocDTO:
    id: str
    name: str
    description: str | None
    study: StudyDTO
    universe: UniverseDTO | None
    geography_system_id: str
    geography_version: GeographyVersionDTO | None
    collection_start: date | None
    collection_end: date | None
    reference_date: date | None
    quality_notes: tuple[QualityNoteDTO, ...]
    data_products: tuple[DataProductSummaryDTO, ...]

DataProductDocDTO

Stability: Stable

@dataclass(frozen=True)
class DataProductDocDTO:
    id: str
    dataset_id: str
    name: str
    kind: DataProductKindStr
    description: str | None
    grain: tuple[str, ...]  # Variable names
    variables: tuple[VariableSummaryDTO, ...]
    default_time_dimension: str | None
    is_public: bool

VariableDocDTO

Stability: Stable

@dataclass(frozen=True)
class VariableDocDTO:
    id: str
    name: str
    role: VariableRoleStr
    data_type: DataTypeStr
    description: str | None
    unit: str | None
    domain: VariableDomainDTO | None
    concept: ConceptDTO | None
    indicator_definition: IndicatorDefinitionDTO | None

VariableDomainDTO

Stability: Stable

@dataclass(frozen=True)
class VariableDomainDTO:
    values: tuple[str, ...]
    is_exhaustive: bool

IndicatorDefinitionDTO

Stability: Stable

@dataclass(frozen=True)
class IndicatorDefinitionDTO:
    variable_id: str
    indicator_type: str
    aggregation_policy: str
    numerator_ref: str | None    # "data_product_name.variable_name"
    denominator_ref: str | None
    formula: str | None
    allowed_aggregations: tuple[str, ...] | None
    weighting_method: str | None

QualityNoteDTO

Stability: Stable

@dataclass(frozen=True)
class QualityNoteDTO:
    category: QualityNoteCategoryStr  # "COVERAGE" | "METHODOLOGY" | "COMPARABILITY" | "OTHER"
    note: str

ConceptDocDTO

Stability: Stable

@dataclass(frozen=True)
class ConceptDocDTO:
    id: str
    name: str
    definition: str
    unit: str | None
    aliases: tuple[str, ...]
    used_by_variables: tuple[VariableSummaryDTO, ...]

CatalogIndexDTO

Stability: Stable

@dataclass(frozen=True)
class CatalogIndexDTO:
    studies: tuple[StudyDTO, ...]
    datasets: tuple[DatasetSummaryDTO, ...]
    concepts: tuple[ConceptDTO, ...]
    total_data_products: int
    total_variables: int

Catalog Write DTOs

CreateStudyRequest

Stability: Stable

@dataclass(frozen=True)
class CreateStudyRequest:
    name: str
    publisher: str
    description: str | None = None

UpdateStudyRequest

Stability: Stable

@dataclass(frozen=True)
class UpdateStudyRequest:
    study_id: str
    name: str | None = None
    publisher: str | None = None
    description: str | None = None

CreateDatasetRequest

Stability: Stable

@dataclass(frozen=True)
class CreateDatasetRequest:
    study_id: str
    name: str
    geography_system_id: str
    geography_version_id: str | None = None
    universe_id: str | None = None
    description: str | None = None
    collection_start: date | None = None
    collection_end: date | None = None
    reference_date: date | None = None

UpdateDatasetRequest

Stability: Stable

@dataclass(frozen=True)
class UpdateDatasetRequest:
    dataset_id: str
    name: str | None = None
    geography_version_id: str | None = None
    universe_id: str | None = None
    description: str | None = None
    collection_start: date | None = None
    collection_end: date | None = None
    reference_date: date | None = None

CreateDataProductRequest

Stability: Stable

@dataclass(frozen=True)
class CreateDataProductRequest:
    dataset_id: str
    name: str
    kind: DataProductKindStr  # "FACT" | "INDICATOR"
    grain_variable_names: list[str]
    variables: list[CreateVariableRequest]
    description: str | None = None
    is_public: bool = False

UpdateDataProductRequest

Stability: Stable

@dataclass(frozen=True)
class UpdateDataProductRequest:
    data_product_id: str
    name: str | None = None
    description: str | None = None
    is_public: bool | None = None

CreateVariableRequest

Stability: Stable

@dataclass(frozen=True)
class CreateVariableRequest:
    name: str
    role: VariableRoleStr    # "DIMENSION" | "MEASURE" | "INDICATOR"
    data_type: DataTypeStr   # "STRING" | "INT" | "FLOAT" | "DATE" | "BOOL"
    description: str | None = None
    unit: str | None = None
    concept_id: str | None = None

CreateIndicatorDefinitionRequest

Stability: Stable

@dataclass(frozen=True)
class CreateIndicatorDefinitionRequest:
    variable_id: str
    indicator_type: IndicatorTypeStr  # "PERCENT" | "RATE" | "MEAN" | "INDEX" | "OTHER"
    aggregation_policy: AggregationPolicyStr  # "NOT_AGGREGATABLE" | "RECOMPUTE" | "ALLOW_LIST"
    numerator_data_product_id: str | None = None
    numerator_variable_id: str | None = None
    denominator_data_product_id: str | None = None
    denominator_variable_id: str | None = None
    formula: str | None = None
    allowed_aggregations: list[str] | None = None
    weighting_method: WeightingMethodStr | None = None  # "POP_WEIGHTED" | "DENOM_WEIGHTED" | "NONE"

CreateUniverseRequest

Stability: Stable

@dataclass(frozen=True)
class CreateUniverseRequest:
    name: str
    definition: str
    inclusions: list[str] | None = None
    exclusions: list[str] | None = None

CreateConceptRequest

Stability: Stable

@dataclass(frozen=True)
class CreateConceptRequest:
    name: str
    definition: str
    unit: str | None = None
    aliases: list[str] | None = None

CreateGeographyVersionRequest

Stability: Stable

@dataclass(frozen=True)
class CreateGeographyVersionRequest:
    system_id: str
    name: str
    levels: list[str]
    valid_from: date | None = None
    valid_to: date | None = None

CreateCrosswalkRequest

Stability: Stable

@dataclass(frozen=True)
class CreateCrosswalkRequest:
    source_version_id: str
    target_version_id: str
    method: CrosswalkMethodStr  # "ADMIN_MAP" | "AREA_WEIGHTED" | "POP_WEIGHTED"
    coverage_note: str | None = None

Indicator Search DTOs

IndicatorSearchRequest

Stability: Stable

@dataclass(frozen=True)
class IndicatorSearchRequest:
    text_query: str | None
    tags: tuple[str, ...]
    time_grains: tuple[TimeGrain, ...]
    geo_levels: tuple[str, ...]
    dataset_name: str | None
    metric_kind: MetricKind | None
    limit: int = 50      # Must be > 0
    offset: int = 0      # Must be >= 0

IndicatorSummaryDTO

Stability: Stable

@dataclass(frozen=True)
class IndicatorSummaryDTO:
    name: str
    kind: MetricKind
    description: str | None
    tags: tuple[str, ...]
    dataset_name: str | None
    unit_name: str | None

IndicatorSearchResultDTO

Stability: Stable

@dataclass(frozen=True)
class IndicatorSearchResultDTO:
    items: tuple[IndicatorSummaryDTO, ...]
    total_count: int
    limit: int
    offset: int
    has_more: bool  # Computed: offset + len(items) < total_count

IndicatorDetailsDTO

Stability: Stable

@dataclass(frozen=True)
class IndicatorDetailsDTO:
    # Summary fields
    name: str
    kind: MetricKind
    description: str | None
    tags: tuple[str, ...]
    dataset_name: str | None
    unit_name: str | None

    # Detail fields
    valid_time_grains: tuple[TimeGrain, ...]
    valid_geo_levels: tuple[str, ...]
    additivity: AdditivityDTO
    comparability: ComparabilityDTO | None
    spec_details: dict[str, Any]
    dependencies: tuple[str, ...]

AdditivityDTO

Stability: Stable

@dataclass(frozen=True)
class AdditivityDTO:
    type: str
    across_time: bool
    across_geo: bool
    rollup_policy: str

ComparabilityDTO

Stability: Stable

@dataclass(frozen=True)
class ComparabilityDTO:
    methodology_id: str
    methodology_version: str
    population_definition: str | None

Catalog Export DTOs

CatalogExportDTO

Stability: Stable

Export DTO for the complete semantic catalog.

@dataclass(frozen=True)
class CatalogExportDTO:
    datasets: tuple[DatasetExportDTO, ...]
    indicators: tuple[IndicatorExportDTO, ...]
    generated_at: str  # ISO timestamp string

    def to_dict(self) -> dict: ...

DatasetExportDTO

Stability: Stable

@dataclass(frozen=True)
class DatasetExportDTO:
    name: str
    kind: str
    physical_schema: str
    physical_table: str
    grain_keys: GrainKeysExportDTO
    time_series: tuple[TimeSeriesExportDTO, ...]
    columns: tuple[ColumnExportDTO, ...]

    def to_dict(self) -> dict: ...

GrainKeysExportDTO

Stability: Stable

@dataclass(frozen=True)
class GrainKeysExportDTO:
    geo: tuple[str, ...]
    time: tuple[str, ...]
    other: tuple[str, ...]

    def to_dict(self) -> dict: ...

ColumnExportDTO

Stability: Stable

@dataclass(frozen=True)
class ColumnExportDTO:
    name: str
    data_type: str
    description: str | None
    nullable: bool
    stats: ColumnStatsExportDTO | None

    def to_dict(self) -> dict: ...

ColumnStatsExportDTO

Stability: Stable

@dataclass(frozen=True)
class ColumnStatsExportDTO:
    row_count: int | None
    null_count: int | None
    non_null_count: int | None
    distinct_count: int | None
    sample_values: tuple[str, ...]

    def to_dict(self) -> dict: ...

TimeSeriesExportDTO

Stability: Stable

@dataclass(frozen=True)
class TimeSeriesExportDTO:
    base_name: str
    grain: str
    start_period: str  # ISO date string
    end_period: str    # ISO date string
    columns: tuple[TimeSeriesColumnExportDTO, ...]

    def to_dict(self) -> dict: ...

TimeSeriesColumnExportDTO

Stability: Stable

@dataclass(frozen=True)
class TimeSeriesColumnExportDTO:
    column_name: str
    period: str  # ISO date string
    grain: str

    def to_dict(self) -> dict: ...

IndicatorExportDTO

Stability: Stable

@dataclass(frozen=True)
class IndicatorExportDTO:
    name: str
    kind: str
    description: str | None
    tags: tuple[str, ...]
    unit: str | None
    valid_time_grains: tuple[str, ...]
    valid_geo_levels: tuple[str, ...]
    additivity: AdditivityExportDTO
    spec_summary: dict  # Kind-specific spec info
    dependencies: tuple[str, ...]  # For RATIO/DERIVED

    def to_dict(self) -> dict: ...

AdditivityExportDTO

Stability: Stable

@dataclass(frozen=True)
class AdditivityExportDTO:
    type: str
    across_time: bool
    across_geo: bool
    rollup_policy: str

    def to_dict(self) -> dict: ...

Enums and Type Aliases

SeverityLevel

SeverityLevel = Literal["ALLOW", "WARN", "REQUIRE_ACK", "BLOCK"]

FilterOperator

class FilterOperator(str, Enum):
    EQ = "EQ"
    NE = "NE"
    IN = "IN"
    NOT_IN = "NOT_IN"
    BETWEEN = "BETWEEN"
    GT = "GT"
    GTE = "GTE"
    LT = "LT"
    LTE = "LTE"

SortOrder

class SortOrder(str, Enum):
    ASC = "ASC"
    DESC = "DESC"

MaterializationDecision

class MaterializationDecision(str, Enum):
    NOT_EVALUATED = "NOT_EVALUATED"
    NO_MATCH = "NO_MATCH"
    MATCH_SKIPPED_PHASE1 = "MATCH_SKIPPED_PHASE1"

Type Aliases (Query Request)

FilterOpStr = Literal["EQ", "IN", "GT", "GTE", "LT", "LTE"]
AggregationStr = Literal["SUM", "AVG", "MIN", "MAX", "COUNT", "NONE"]
CombineModeStr = Literal["COMPARE", "JOIN"]
PresentationFormatStr = Literal["NUMBER", "SERIES", "CHOROPLETH", "TABLE"]
QueryIntentStr = Literal["NUMBER", "CHART", "TABLE", "MAP"]

Type Aliases (Catalog)

DataProductKindStr = Literal["FACT", "INDICATOR"]
VariableRoleStr = Literal["DIMENSION", "MEASURE", "INDICATOR"]
DataTypeStr = Literal["STRING", "INT", "FLOAT", "DATE", "BOOL"]
QualityNoteCategoryStr = Literal["COVERAGE", "METHODOLOGY", "COMPARABILITY", "OTHER"]
IndicatorTypeStr = Literal["PERCENT", "RATE", "MEAN", "INDEX", "OTHER"]
AggregationPolicyStr = Literal["NOT_AGGREGATABLE", "RECOMPUTE", "ALLOW_LIST"]
WeightingMethodStr = Literal["POP_WEIGHTED", "DENOM_WEIGHTED", "NONE"]
CrosswalkMethodStr = Literal["ADMIN_MAP", "AREA_WEIGHTED", "POP_WEIGHTED"]