{
    "x-license": {
        "id": "Apache-2.0",
        "notice": "Copyright 2025-2026 Dorsal Hub LTD",
        "url": "https://github.com/dorsalhub/open-validation-schemas/blob/main/LICENSE"
    },
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://dorsalhub.com/schemas/open/geolocation",
    "title": "Geolocation",
    "version": "0.6.0",
    "description": "Represent a geographic feature. Defines a subset of GeoJSON (RFC 7946) optimized for predictable parsing and indexing. It restricts the root to a single 'Feature', supports all fixed-depth geometries (Point, Polygon, Multi-types), and enforces flat properties to prevent recursion and nesting attacks.",
    "type": "object",
    "properties": {
        "type": {
            "description": "The GeoJSON object type.",
            "const": "Feature"
        },
        "id": {
            "description": "A unique identifier for the feature.",
            "anyOf": [
                {
                    "type": "string",
                    "maxLength": 128
                },
                {
                    "type": "number"
                }
            ]
        },
        "producer": {
            "type": "string",
            "description": "The creator (model, tool or author) of this record.",
            "maxLength": 1024
        },
        "bbox": {
            "$ref": "#/$defs/bbox"
        },
        "geometry": {
            "description": "The geometry of the feature. Uses the WGS 84 coordinate reference system.",
            "anyOf": [
                {
                    "type": "null"
                },
                {
                    "title": "Point",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "Point"
                        },
                        "coordinates": {
                            "$ref": "#/$defs/position"
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                },
                {
                    "title": "LineString",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "LineString"
                        },
                        "coordinates": {
                            "$ref": "#/$defs/line-string-coords"
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                },
                {
                    "title": "Polygon",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "Polygon"
                        },
                        "coordinates": {
                            "$ref": "#/$defs/polygon-coords"
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                },
                {
                    "title": "MultiPoint",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "MultiPoint"
                        },
                        "coordinates": {
                            "type": "array",
                            "description": "A list of positions.",
                            "items": {
                                "$ref": "#/$defs/position"
                            },
                            "maxItems": 10000
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                },
                {
                    "title": "MultiLineString",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "MultiLineString"
                        },
                        "coordinates": {
                            "type": "array",
                            "description": "A list of line strings.",
                            "items": {
                                "$ref": "#/$defs/line-string-coords"
                            },
                            "maxItems": 1000
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                },
                {
                    "title": "MultiPolygon",
                    "type": "object",
                    "properties": {
                        "type": {
                            "const": "MultiPolygon"
                        },
                        "coordinates": {
                            "type": "array",
                            "description": "A list of polygons.",
                            "items": {
                                "$ref": "#/$defs/polygon-coords"
                            },
                            "maxItems": 1000
                        },
                        "bbox": {
                            "$ref": "#/$defs/bbox"
                        }
                    },
                    "required": [
                        "type",
                        "coordinates"
                    ],
                    "maxProperties": 16,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                }
            ]
        },
        "properties": {
            "description": "An object containing additional properties of the feature. Can be null.",
            "anyOf": [
                {
                    "type": "null"
                },
                {
                    "type": "object",
                    "properties": {
                        "timestamp": {
                            "type": "string",
                            "description": "The time the feature was observed.",
                            "format": "date-time",
                            "maxLength": 128
                        },
                        "camera_make": {
                            "type": "string",
                            "description": "The make of the camera that captured the source media.",
                            "maxLength": 128
                        },
                        "camera_model": {
                            "type": "string",
                            "description": "The model of the camera that captured the source media.",
                            "maxLength": 128
                        }
                    },
                    "maxProperties": 100,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "$ref": "#/$defs/foreign-member"
                    }
                }
            ]
        }
    },
    "required": [
        "type",
        "geometry",
        "properties"
    ],
    "maxProperties": 32,
    "propertyNames": {
        "maxLength": 128
    },
    "$defs": {
        "position": {
            "type": "array",
            "description": "A single position: [longitude, latitude] or [longitude, latitude, altitude].",
            "prefixItems": [
                {
                    "type": "number",
                    "description": "Longitude in decimal degrees.",
                    "minimum": -180,
                    "maximum": 180
                },
                {
                    "type": "number",
                    "description": "Latitude in decimal degrees.",
                    "minimum": -90,
                    "maximum": 90
                },
                {
                    "type": "number",
                    "description": "Altitude in meters above the WGS 84 ellipsoid."
                }
            ],
            "items": false,
            "minItems": 2,
            "maxItems": 3
        },
        "line-string-coords": {
            "type": "array",
            "description": "An ordered list of two or more positions.",
            "items": {
                "$ref": "#/$defs/position"
            },
            "minItems": 2,
            "maxItems": 10000
        },
        "linear-ring": {
            "type": "array",
            "description": "A closed ring of four or more positions. The first and last positions must be identical.",
            "items": {
                "$ref": "#/$defs/position"
            },
            "minItems": 4,
            "maxItems": 10000
        },
        "polygon-coords": {
            "type": "array",
            "description": "A list of linear rings. The first is the exterior ring; any others are holes.",
            "items": {
                "$ref": "#/$defs/linear-ring"
            },
            "minItems": 1,
            "maxItems": 100
        },
        "bbox": {
            "type": "array",
            "description": "A bounding box (RFC 7946, Section 5): 4 values for 2D or 6 values for 3D.",
            "items": {
                "type": "number"
            },
            "anyOf": [
                {
                    "minItems": 4,
                    "maxItems": 4
                },
                {
                    "minItems": 6,
                    "maxItems": 6
                }
            ],
            "minItems": 4,
            "maxItems": 6
        },
        "foreign-member": {
            "description": "Constrained definition of RFC 7946 Foreign Members.",
            "anyOf": [
                {
                    "type": "string",
                    "maxLength": 2048
                },
                {
                    "type": "number"
                },
                {
                    "type": "boolean"
                },
                {
                    "type": "null"
                },
                {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                        "anyOf": [
                            {
                                "type": "string",
                                "maxLength": 1024
                            },
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            }
                        ]
                    }
                },
                {
                    "type": "object",
                    "maxProperties": 20,
                    "propertyNames": {
                        "maxLength": 128
                    },
                    "additionalProperties": {
                        "anyOf": [
                            {
                                "type": "string",
                                "maxLength": 2048
                            },
                            {
                                "type": "number"
                            },
                            {
                                "type": "boolean"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    }
                }
            ]
        }
    },
    "additionalProperties": {
        "$ref": "#/$defs/foreign-member"
    }
}