from __future__ import annotations from datetime import datetime from typing import Literal from uuid import UUID from pydantic import BaseModel SourceFreshnessStatus = Literal["current", "due", "review_required", "local"] SourceRefreshPolicy = Literal["rolling_snapshot", "annual_release", "edition", "scenario", "archive", "local"] class SourceIntegritySummary(BaseModel): missing_version_count: int = 0 checksum_mismatch_count: int = 0 missing_storage_file_count: int = 0 size_mismatch_count: int = 0 @property def issue_count(self) -> int: return ( self.missing_version_count + self.checksum_mismatch_count + self.missing_storage_file_count + self.size_mismatch_count ) class SourceFreshnessItem(BaseModel): source_name: str display_name: str dataset_count: int ready_count: int version_count: int latest_imported_at: datetime | None = None latest_observed_at: datetime | None = None latest_source_version: str | None = None refresh_policy: SourceRefreshPolicy review_interval_days: int | None = None next_review_at: datetime | None = None status: SourceFreshnessStatus historical_series: bool auto_refresh_supported: bool = False reason: str recommended_action: str integrity: SourceIntegritySummary class SourceFreshnessSummary(BaseModel): source_count: int dataset_count: int current_count: int due_count: int review_required_count: int local_count: int sources_with_integrity_issues: int integrity_issue_count: int class SourceFreshnessReport(BaseModel): project_id: UUID generated_at: datetime summary: SourceFreshnessSummary items: list[SourceFreshnessItem] limitations: list[str]