Skip to content

STAC

STAC catalog management, item builders, validators, and backends.

Backend Protocol

fair.stac.backend

StacBackend

Bases: Protocol

Structural interface for STAC catalog operations.

StacCatalogManager (local JSON) and PgStacBackend (pgstac) both conform without explicit inheritance.

Catalog Manager

fair.stac.catalog_manager

StacCatalogManager(catalog_path)

CRUD on a pystac Catalog persisted as local JSON.

Source code in fair/stac/catalog_manager.py
def __init__(self, catalog_path: str):
    self.catalog = pystac.Catalog.from_file(catalog_path)

PgSTAC Backend

fair.stac.pgstac_backend

PgStacBackend(dsn, stac_api_url)

STAC backend using pypgstac Loader and pystac-client.

Writes use pypgstac's Loader (bulk upsert via COPY + pgstac SQL). Reads use pystac-client against the STAC API. Delete uses pgstac's delete_item() SQL function directly since Loader has no delete API.

Source code in fair/stac/pgstac_backend.py
def __init__(self, dsn: str, stac_api_url: str) -> None:
    self._dsn = dsn
    self._stac_api_url = stac_api_url
    self._bootstrap_collections()

Builders

fair.stac.builders

Collections

fair.stac.collections

create_base_models_collection()

base-models: model blueprints contributed via PR.

Source code in fair/stac/collections.py
def create_base_models_collection() -> pystac.Collection:
    """base-models: model blueprints contributed via PR."""
    return pystac.Collection(
        id=BASE_MODELS_COLLECTION,
        description="Model blueprints contributed via PR. Each item is a complete model card.",
        extent=pystac.Extent(
            spatial=pystac.SpatialExtent(bboxes=[[-180, -90, 180, 90]]),
            temporal=pystac.TemporalExtent(intervals=[[datetime(2026, 1, 1, tzinfo=UTC), None]]),
        ),
        license="various",
        stac_extensions=BASE_MODEL_EXTENSIONS,
    )

create_local_models_collection()

local-models: finetuned models, only promoted versions.

Source code in fair/stac/collections.py
def create_local_models_collection() -> pystac.Collection:
    """local-models: finetuned models, only promoted versions."""
    return pystac.Collection(
        id=LOCAL_MODELS_COLLECTION,
        description="Finetuned models produced by ZenML pipelines. Only promoted versions appear here.",
        extent=pystac.Extent(
            spatial=pystac.SpatialExtent(bboxes=[[-180, -90, 180, 90]]),
            temporal=pystac.TemporalExtent(intervals=[[datetime(2026, 1, 1, tzinfo=UTC), None]]),
        ),
        license="various",
        stac_extensions=LOCAL_MODEL_EXTENSIONS,
    )

create_datasets_collection()

datasets: training data registered via fAIr UI/backend.

Source code in fair/stac/collections.py
def create_datasets_collection() -> pystac.Collection:
    """datasets: training data registered via fAIr UI/backend."""
    return pystac.Collection(
        id=DATASETS_COLLECTION,
        description="Training data registered via fAIr UI/backend.",
        extent=pystac.Extent(
            spatial=pystac.SpatialExtent(bboxes=[[-180, -90, 180, 90]]),
            temporal=pystac.TemporalExtent(intervals=[[datetime(2026, 1, 1, tzinfo=UTC), None]]),
        ),
        license="various",
        stac_extensions=DATASET_EXTENSIONS,
    )

initialize_catalog(catalog_path)

Create catalog.json + 3 empty collections. Saves to disk.

returns existing catalog if already present.

Source code in fair/stac/collections.py
def initialize_catalog(catalog_path: str) -> pystac.Catalog:
    """Create catalog.json + 3 empty collections. Saves to disk.

    returns existing catalog if already present.
    """
    if os.path.exists(catalog_path):
        return pystac.Catalog.from_file(catalog_path)

    catalog = pystac.Catalog(
        id="fair-models",
        description="fAIr model registry and dataset catalog",
    )

    catalog.add_child(create_base_models_collection())
    catalog.add_child(create_local_models_collection())
    catalog.add_child(create_datasets_collection())

    catalog_dir = os.path.dirname(catalog_path) or "."
    catalog.normalize_hrefs(catalog_dir)
    catalog.save(catalog_type=CatalogType.SELF_CONTAINED)

    return catalog

Validators

fair.stac.validators

Constants

fair.stac.constants

BASE_MODELS_COLLECTION = 'base-models' module-attribute

BASE_MODEL_EXTENSIONS = [MLM_SCHEMA, VERSION_SCHEMA, CLASSIFICATION_SCHEMA, FILE_SCHEMA, RASTER_SCHEMA, FAIR_BASE_MODEL_SCHEMA] module-attribute

CLASSIFICATION_SCHEMA = 'https://stac-extensions.github.io/classification/v2.0.0/schema.json' module-attribute

CONTAINER_REGISTRIES = ('ghcr.io', 'docker.io', 'quay.io') module-attribute

DATASETS_COLLECTION = 'datasets' module-attribute

DATASET_EXTENSIONS = [LABEL_SCHEMA, FILE_SCHEMA, VERSION_SCHEMA, FAIR_DATASET_SCHEMA] module-attribute

FAIR_BASE_MODEL_SCHEMA = 'https://hotosm.github.io/fAIr-models/schemas/v1.0.0/base-model/schema.json' module-attribute

FAIR_DATASET_SCHEMA = 'https://hotosm.github.io/fAIr-models/schemas/v1.0.0/dataset/schema.json' module-attribute

FAIR_LOCAL_MODEL_SCHEMA = 'https://hotosm.github.io/fAIr-models/schemas/v1.0.0/local-model/schema.json' module-attribute

FILE_SCHEMA = 'https://stac-extensions.github.io/file/v2.1.0/schema.json' module-attribute

LABEL_SCHEMA = 'https://stac-extensions.github.io/label/v1.0.1/schema.json' module-attribute

LOCAL_MODELS_COLLECTION = 'local-models' module-attribute

LOCAL_MODEL_EXTENSIONS = [MLM_SCHEMA, VERSION_SCHEMA, CLASSIFICATION_SCHEMA, FILE_SCHEMA, RASTER_SCHEMA, FAIR_LOCAL_MODEL_SCHEMA] module-attribute

MLM_SCHEMA = 'https://stac-extensions.github.io/mlm/v1.5.1/schema.json' module-attribute

MODEL_EXTENSIONS = BASE_MODEL_EXTENSIONS module-attribute

OCI_IMAGE_INDEX_TYPE = 'application/vnd.oci.image.index.v1+json' module-attribute

RASTER_SCHEMA = 'https://stac-extensions.github.io/raster/v1.1.0/schema.json' module-attribute

VERSION_SCHEMA = 'https://stac-extensions.github.io/version/v1.2.0/schema.json' module-attribute