{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.null-echo.com/schema/observation-session.schema.json",
  "title": "Kolasky Observation Session",
  "description": "Portable structure for a provenance-aware Kolasky field observation.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schemaVersion", "id", "state", "observedAt", "createdAt", "updatedAt", "privacy", "evidence", "directionTracks"],
  "properties": {
    "schemaVersion": { "const": "1.0.0" },
    "id": { "type": "string", "format": "uuid" },
    "state": { "enum": ["draft", "active", "completed"] },
    "title": { "type": "string", "maxLength": 200 },
    "observedAt": { "$ref": "#/$defs/observedAt" },
    "createdAt": { "type": "string", "format": "date-time" },
    "updatedAt": { "type": "string", "format": "date-time" },
    "privacy": { "$ref": "#/$defs/privacy" },
    "evidence": { "$ref": "#/$defs/evidence" },
    "directionTracks": {
      "type": "array",
      "items": { "$ref": "#/$defs/directionTrack" }
    },
    "publication": { "$ref": "#/$defs/publication" },
    "extensions": { "type": "object" }
  },
  "$defs": {
    "observedAt": {
      "type": "object",
      "additionalProperties": false,
      "required": ["start"],
      "properties": {
        "start": { "type": "string", "format": "date-time" },
        "end": { "type": "string", "format": "date-time" },
        "timeZoneOffset": { "type": "string", "pattern": "^[+-](0[0-9]|1[0-4]):[0-5][0-9]$" }
      }
    },
    "privacy": {
      "type": "object",
      "additionalProperties": false,
      "required": ["locationMode"],
      "properties": {
        "locationMode": { "enum": ["hidden", "approximate", "precise"] },
        "coordinates": { "$ref": "#/$defs/coordinates" },
        "precisionMeters": { "type": "number", "minimum": 0 },
        "originalMediaLocalOnly": { "type": "boolean", "default": true }
      },
      "allOf": [
        {
          "if": { "properties": { "locationMode": { "const": "hidden" } }, "required": ["locationMode"] },
          "then": { "not": { "required": ["coordinates"] } }
        },
        {
          "if": { "properties": { "locationMode": { "const": "approximate" } }, "required": ["locationMode"] },
          "then": { "required": ["precisionMeters"] }
        },
        {
          "if": { "properties": { "locationMode": { "const": "precise" } }, "required": ["locationMode"] },
          "then": { "required": ["coordinates"] }
        }
      ]
    },
    "coordinates": {
      "type": "object",
      "additionalProperties": false,
      "required": ["latitude", "longitude"],
      "properties": {
        "latitude": { "type": "number", "minimum": -90, "maximum": 90 },
        "longitude": { "type": "number", "minimum": -180, "maximum": 180 },
        "altitudeMeters": { "type": "number" }
      }
    },
    "evidence": {
      "type": "object",
      "additionalProperties": false,
      "required": ["raw", "statements", "measurements", "machineNotes"],
      "properties": {
        "raw": { "type": "array", "items": { "$ref": "#/$defs/rawEvidence" } },
        "statements": { "type": "array", "items": { "$ref": "#/$defs/statement" } },
        "measurements": { "type": "array", "items": { "$ref": "#/$defs/measurement" } },
        "machineNotes": { "type": "array", "items": { "$ref": "#/$defs/machineNote" } }
      }
    },
    "rawEvidence": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "kind", "capturedAt", "mediaType", "byteSize", "hash", "isOriginal"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "kind": { "enum": ["photo", "video", "audio"] },
        "capturedAt": { "type": "string", "format": "date-time" },
        "mediaType": { "type": "string", "pattern": "^[a-z0-9.+-]+/[a-z0-9.+-]+$" },
        "byteSize": { "type": "integer", "minimum": 0 },
        "durationSeconds": { "type": "number", "minimum": 0 },
        "hash": { "$ref": "#/$defs/hash" },
        "isOriginal": { "type": "boolean" },
        "derivedFrom": { "type": "string", "format": "uuid" },
        "redactions": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
        "extensions": { "type": "object" }
      }
    },
    "hash": {
      "type": "object",
      "additionalProperties": false,
      "required": ["algorithm", "value"],
      "properties": {
        "algorithm": { "const": "sha-256" },
        "value": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
      }
    },
    "statement": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "recordedAt", "text"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "recordedAt": { "type": "string", "format": "date-time" },
        "language": { "type": "string" },
        "text": { "type": "string", "minLength": 1, "maxLength": 10000 },
        "extensions": { "type": "object" }
      }
    },
    "measurement": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "recordedAt", "kind", "value", "unit", "source"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "recordedAt": { "type": "string", "format": "date-time" },
        "kind": { "type": "string", "minLength": 1, "maxLength": 80 },
        "value": { "type": "number" },
        "unit": { "type": "string", "minLength": 1, "maxLength": 40 },
        "uncertainty": { "type": "number", "minimum": 0 },
        "source": { "type": "string", "minLength": 1, "maxLength": 120 },
        "extensions": { "type": "object" }
      }
    },
    "machineNote": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "createdAt", "analyzer", "version", "text"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "createdAt": { "type": "string", "format": "date-time" },
        "analyzer": { "type": "string", "minLength": 1, "maxLength": 120 },
        "version": { "type": "string", "minLength": 1, "maxLength": 80 },
        "text": { "type": "string", "minLength": 1, "maxLength": 4000 },
        "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
        "limitations": { "type": "array", "items": { "type": "string" } },
        "extensions": { "type": "object" }
      }
    },
    "directionTrack": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "northReference", "samples"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "northReference": { "enum": ["true", "magnetic"] },
        "samples": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/directionSample" } },
        "extensions": { "type": "object" }
      }
    },
    "directionSample": {
      "type": "object",
      "additionalProperties": false,
      "required": ["recordedAt", "azimuthDegrees", "elevationDegrees"],
      "properties": {
        "recordedAt": { "type": "string", "format": "date-time" },
        "azimuthDegrees": { "type": "number", "minimum": 0, "exclusiveMaximum": 360 },
        "elevationDegrees": { "type": "number", "minimum": -90, "maximum": 90 },
        "azimuthUncertaintyDegrees": { "type": "number", "minimum": 0, "maximum": 180 },
        "elevationUncertaintyDegrees": { "type": "number", "minimum": 0, "maximum": 180 }
      }
    },
    "publication": {
      "type": "object",
      "additionalProperties": false,
      "required": ["publishedAt", "publicId", "includedFields"],
      "properties": {
        "publishedAt": { "type": "string", "format": "date-time" },
        "publicId": { "type": "string", "minLength": 1, "maxLength": 120 },
        "includedFields": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
        "locationPrecisionMeters": { "type": "number", "minimum": 0 }
      }
    }
  }
}
