{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://climate-assessment-europe-2026.kocour04.chatgpt.site/climate/data/hydroretention_index.schema.json",
  "title": "PHRI v0.1 exchange bundle",
  "description": "Schema for Prototype Humidity and Hydroretention Index observation and score bundles.",
  "oneOf": [
    {"$ref": "#/$defs/observation_bundle"},
    {"$ref": "#/$defs/score_bundle"}
  ],
  "$defs": {
    "bundle_metadata": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "dataset_id",
        "dataset_type",
        "index_version",
        "created_at",
        "created_by",
        "reference_period",
        "is_synthetic"
      ],
      "properties": {
        "dataset_id": {"type": "string", "minLength": 1, "maxLength": 200},
        "dataset_type": {"enum": ["observations", "scores"]},
        "index_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
        "created_at": {"type": "string", "format": "date-time"},
        "created_by": {"type": "string", "minLength": 1},
        "reference_period": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{4}$"},
        "config_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
        "licence": {"type": "string", "minLength": 1},
        "is_synthetic": {"type": "boolean"},
        "notes": {"type": "string"}
      }
    },
    "observation_bundle": {
      "type": "object",
      "additionalProperties": false,
      "required": ["metadata", "observations"],
      "properties": {
        "metadata": {
          "allOf": [
            {"$ref": "#/$defs/bundle_metadata"},
            {"properties": {"dataset_type": {"const": "observations"}}}
          ]
        },
        "observations": {
          "type": "array",
          "minItems": 1,
          "items": {"$ref": "#/$defs/observation"}
        }
      }
    },
    "score_bundle": {
      "type": "object",
      "additionalProperties": false,
      "required": ["metadata", "scores"],
      "properties": {
        "metadata": {
          "allOf": [
            {"$ref": "#/$defs/bundle_metadata"},
            {"properties": {"dataset_type": {"const": "scores"}}}
          ]
        },
        "scores": {
          "type": "array",
          "minItems": 1,
          "items": {"$ref": "#/$defs/score"}
        }
      }
    },
    "observation": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "record_id",
        "spatial_id",
        "spatial_name",
        "spatial_type",
        "country_iso3",
        "geometry_version",
        "time_start",
        "time_end",
        "temporal_resolution",
        "variable_id",
        "raw_value",
        "unit",
        "direction",
        "normalization_method",
        "reference_period",
        "benchmark_scope",
        "source_id",
        "source_url",
        "source_version",
        "retrieved_at",
        "processing_level",
        "quality_flag",
        "license_or_terms",
        "is_synthetic"
      ],
      "properties": {
        "record_id": {"type": "string", "minLength": 1, "maxLength": 200},
        "spatial_id": {"type": "string", "minLength": 1, "maxLength": 100},
        "spatial_name": {"type": "string", "minLength": 1, "maxLength": 300},
        "spatial_type": {"enum": ["basin", "subbasin", "grid", "administrative"]},
        "country_iso3": {"type": "string", "pattern": "^([A-Z]{3}|MULTI)$"},
        "geometry_version": {"type": "string", "minLength": 1},
        "time_start": {"type": "string", "format": "date-time"},
        "time_end": {"type": "string", "format": "date-time"},
        "temporal_resolution": {"enum": ["event", "daily", "dekadal", "monthly", "quarterly", "annual", "static"]},
        "variable_id": {
          "enum": [
            "spei_3",
            "spei_12",
            "precip_concentration",
            "groundwater_pct",
            "lowflow_pct",
            "flashiness",
            "rootzone_sm_pct",
            "awc",
            "soc",
            "erosion_risk",
            "fapar_anomaly",
            "perennial_cover",
            "bare_soil_frequency",
            "imperviousness",
            "land_take_rate",
            "retention_landcover",
            "drainage_connectivity"
          ]
        },
        "raw_value": {"type": "number"},
        "unit": {
          "enum": ["1", "%", "percentile", "mm", "kg_m-2", "t_ha-1_yr-1", "%_per_3yr"]
        },
        "direction": {"enum": ["positive", "negative"]},
        "normalization_method": {
          "enum": [
            "empirical_monthly_percentile",
            "inverse_empirical_monthly_percentile",
            "winsorized_linear",
            "inverse_winsorized_linear",
            "pre_normalized"
          ]
        },
        "reference_period": {"type": "string", "minLength": 1},
        "benchmark_scope": {"enum": ["basin_history", "hydroclimate_region", "country", "europe", "physical_thresholds"]},
        "norm_p05": {"type": ["number", "null"]},
        "norm_p50": {"type": ["number", "null"]},
        "norm_p95": {"type": ["number", "null"]},
        "normalized_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100},
        "uncertainty_low": {"type": ["number", "null"]},
        "uncertainty_high": {"type": ["number", "null"]},
        "source_id": {"type": "string", "minLength": 1},
        "source_url": {"type": "string", "format": "uri"},
        "source_version": {"type": "string", "minLength": 1},
        "retrieved_at": {"type": "string", "format": "date-time"},
        "processing_level": {"enum": ["measurement", "interpolated_measurement", "satellite", "reanalysis", "model", "derived"]},
        "quality_flag": {"enum": ["valid", "provisional", "suspect", "missing", "imputed"]},
        "license_or_terms": {"type": "string", "minLength": 1},
        "is_synthetic": {"type": "boolean"},
        "notes": {"type": "string"}
      }
    },
    "score": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "score_record_id",
        "spatial_id",
        "time_start",
        "time_end",
        "index_version",
        "config_sha256",
        "weight_coverage",
        "quality_score",
        "publication_status",
        "monte_carlo_runs",
        "generated_at",
        "is_synthetic"
      ],
      "properties": {
        "score_record_id": {"type": "string", "minLength": 1},
        "spatial_id": {"type": "string", "minLength": 1},
        "time_start": {"type": "string", "format": "date-time"},
        "time_end": {"type": "string", "format": "date-time"},
        "index_version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
        "config_sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
        "meteo_score": {"$ref": "#/$defs/nullable_score"},
        "hydrology_score": {"$ref": "#/$defs/nullable_score"},
        "soil_score": {"$ref": "#/$defs/nullable_score"},
        "vegetation_score": {"$ref": "#/$defs/nullable_score"},
        "landuse_score": {"$ref": "#/$defs/nullable_score"},
        "state_score": {"$ref": "#/$defs/nullable_score"},
        "capacity_score": {"$ref": "#/$defs/nullable_score"},
        "phri_p05": {"$ref": "#/$defs/nullable_score"},
        "phri_p50": {"$ref": "#/$defs/nullable_score"},
        "phri_p95": {"$ref": "#/$defs/nullable_score"},
        "bottleneck_score": {"$ref": "#/$defs/nullable_score"},
        "weight_coverage": {"type": "number", "minimum": 0, "maximum": 1},
        "quality_score": {"type": "number", "minimum": 0, "maximum": 100},
        "publication_status": {"enum": ["publishable", "provisional", "withheld"]},
        "monte_carlo_runs": {"type": "integer", "minimum": 0},
        "generated_at": {"type": "string", "format": "date-time"},
        "is_synthetic": {"type": "boolean"},
        "notes": {"type": "string"}
      }
    },
    "nullable_score": {
      "type": ["number", "null"],
      "minimum": 0,
      "maximum": 100
    }
  }
}
