{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://andresgmg.github.io/World-GeoJSON/schemas/manifest.schema.json",
  "title": "World GeoJSON country manifest",
  "description": "data/{body}/{ISO3}/manifest.json — identity, provenance and one entry per published administrative level. See docs/reference/manifest.md.",
  "type": "object",
  "required": ["schema_version", "body", "iso_a3", "name", "crs", "status", "source", "datasets"],
  "additionalProperties": false,
  "properties": {
    "schema_version": { "const": 1 },
    "body": { "enum": ["earth", "moon", "mars"] },
    "iso_a3": { "$ref": "#/$defs/iso3" },
    "iso_a2": { "type": "string", "pattern": "^[A-Z]{2}$" },
    "m49_region": { "type": "string", "minLength": 1 },
    "name": { "$ref": "#/$defs/localised" },
    "crs": {
      "type": "object",
      "required": ["authority", "code", "epsg"],
      "additionalProperties": false,
      "properties": {
        "authority": { "type": "string" },
        "code": { "type": "string" },
        "epsg": { "type": "integer" }
      }
    },
    "status": { "enum": ["ok", "review", "deprecated"] },
    "source": {
      "type": "object",
      "required": ["name", "url", "license", "retrieved"],
      "additionalProperties": false,
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "url": { "type": "string", "format": "uri" },
        "license": {
          "description": "The single licence covering every dataset, or \"mixed\" (then `licenses` lists them).",
          "anyOf": [{ "$ref": "#/$defs/license" }, { "const": "mixed" }]
        },
        "licenses": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": { "$ref": "#/$defs/license" }
        },
        "retrieved": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }
      },
      "if": { "properties": { "license": { "const": "mixed" } } },
      "then": { "required": ["licenses"] }
    },
    "notes": { "$ref": "#/$defs/singleLine" },
    "datasets": {
      "type": "array",
      "items": { "$ref": "#/$defs/dataset" }
    }
  },
  "$defs": {
    "iso3": { "type": "string", "pattern": "^[A-Z]{3}$" },
    "level": { "type": "string", "pattern": "^(ADM[0-5]|QUAD)$" },
    "singleLine": { "type": "string", "pattern": "^[^\\n]*$" },
    "localised": {
      "type": "object",
      "required": ["en"],
      "additionalProperties": false,
      "properties": {
        "en": { "type": "string", "minLength": 1 },
        "es": { "type": "string", "minLength": 1 }
      }
    },
    "license": {
      "description": "SPDX identifiers on the permissive allow-list (docs/contributing/sources.md).",
      "enum": [
        "CC0-1.0",
        "CC-BY-2.5",
        "CC-BY-3.0",
        "CC-BY-3.0-IGO",
        "CC-BY-4.0",
        "DL-DE-BY-2.0",
        "Etalab-2.0",
        "ODC-By-1.0",
        "OGL-Canada-2.0",
        "OGL-UK-3.0",
        "public-domain"
      ]
    },
    "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "bbox": {
      "description": "[west, south, east, north] in degrees; naive min/max, so a dataset crossing the antimeridian reads west > east only in the file's own bbox, not here.",
      "type": "array",
      "minItems": 4,
      "maxItems": 4,
      "items": { "type": "number" }
    },
    "geometryTypes": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "Polygon": { "type": "integer", "minimum": 0 },
        "MultiPolygon": { "type": "integer", "minimum": 0 }
      }
    },
    "propertyNames": {
      "type": "array",
      "items": { "type": "string" },
      "uniqueItems": true
    },
    "fileStats": {
      "type": "object",
      "properties": {
        "path": { "type": "string", "pattern": "^data/[a-z]+/[A-Z]{3}/.+\\.geojson$" },
        "bytes": { "type": "integer", "minimum": 1 },
        "sha256": { "$ref": "#/$defs/sha256" },
        "features": { "type": "integer", "minimum": 1 },
        "bbox": { "$ref": "#/$defs/bbox" },
        "geometry_types": { "$ref": "#/$defs/geometryTypes" },
        "properties": { "$ref": "#/$defs/propertyNames" }
      }
    },
    "part": {
      "description": "One file of a split level: data/{body}/{ISO3}/{LEVEL}/{code}.geojson.",
      "allOf": [{ "$ref": "#/$defs/fileStats" }],
      "type": "object",
      "required": ["code", "path", "bytes", "sha256", "features", "bbox", "geometry_types", "properties"],
      "additionalProperties": false,
      "properties": {
        "code": { "type": "string", "minLength": 1 },
        "path": true, "bytes": true, "sha256": true, "features": true,
        "bbox": true, "geometry_types": true, "properties": true
      }
    },
    "dataset": {
      "allOf": [{ "$ref": "#/$defs/fileStats" }],
      "type": "object",
      "required": ["level", "features", "bbox", "geometry_types", "properties", "license"],
      "additionalProperties": false,
      "properties": {
        "level": { "$ref": "#/$defs/level" },
        "path": { "description": "Absent when the level is published as parts only (Brazil ADM2)." },
        "bytes": true, "sha256": true, "features": true, "bbox": true,
        "geometry_types": true, "properties": true,
        "preview": { "type": "string", "pattern": "^data/[a-z]+/[A-Z]{3}/preview/[A-Z]{3}_(ADM[0-5]|QUAD)\\.preview\\.geojson$" },
        "preview_bytes": { "type": "integer", "minimum": 1, "maximum": 2097152 },
        "simplification": {
          "type": "object",
          "required": ["method", "tolerance_m"],
          "additionalProperties": false,
          "properties": {
            "method": { "enum": ["visvalingam", "douglas-peucker", "none"] },
            "tolerance_m": { "type": "integer", "minimum": 0 }
          }
        },
        "license": { "$ref": "#/$defs/license" },
        "src_provider": { "type": "string", "minLength": 1 },
        "src_year": { "type": ["string", "integer"] },
        "unassigned": {
          "description": "Features whose ADM1 parent could not be determined; they live in {LEVEL}/unassigned.geojson.",
          "type": "integer",
          "minimum": 1
        },
        "split_by": { "const": "ADM1" },
        "parts": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/part" }
        }
      },
      "dependentRequired": { "parts": ["split_by"], "split_by": ["parts"] }
    }
  }
}
