{
  "openapi": "3.1.0",
  "info": {
    "title": "GeoScan Core API",
    "version": "1.3.0",
    "description": "Live single-server local API. JSON uploads <=16 MiB. Anonymous cookie sessions: GET /api/v1/session first, retain the HttpOnly __Host-geoscan_session cookie (geoscan_session for local HTTP) for jobs, cancellation, reports and exports. Secure deployments accept only the prefixed cookie. Cookie lasts 90 days, refreshed when fewer than 30 remain at session bootstrap. Deleting it or using another browser loses access. Local drafts are separate. Legacy jobs require explicit operator migration. Missing/expired credentials return 401; foreign job IDs return 404. Unsafe cross-origin requests are rejected unless the origin is explicitly allowed, including the public site origin behind Next proxy. Start with /api/v1/examples. NO_SOLUTION means the heuristic found no verified plan; it does not prove infeasibility. Calculation timeout <=1800 s; a previously verified candidate is preserved at timeout. Queue is durable and has one owner per directory.",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Same-origin Next proxy or direct API"
    }
  ],
  "tags": [
    {
      "name": "Planning",
      "description": "Mission validation, queue, results and history."
    },
    {
      "name": "Exports",
      "description": "Verified flight assignments and full reports."
    },
    {
      "name": "System",
      "description": "Fixtures and readiness."
    },
    {
      "name": "Terrain",
      "description": "Bounded terrain preparation (120 s, two concurrent requests), snapshots and source provenance."
    }
  ],
  "paths": {
    "/api/v1/session": {
      "get": {
        "tags": [
          "System"
        ],
        "operationId": "startAnonymousSession",
        "summary": "Create or resume this browser's anonymous session",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "anonymous": {
                      "type": "boolean",
                      "const": true
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "id",
                    "anonymous",
                    "expiresAt"
                  ]
                }
              }
            },
            "headers": {
              "Set-Cookie": {
                "description": "New or renewed session; HttpOnly, SameSite=Lax, Path=/, Max-Age=7776000; Secure in HTTPS deployments.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/missions/validate": {
      "post": {
        "tags": [
          "Planning"
        ],
        "operationId": "validateMission",
        "summary": "Validate geometry, terrain, aircraft and sensor profile",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Validation"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Field validation errors",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Validation"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Mission"
              }
            }
          }
        }
      }
    },
    "/api/v1/planning-jobs": {
      "post": {
        "tags": [
          "Planning"
        ],
        "operationId": "createPlanningJob",
        "summary": "Submit immutable mission for calculation",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "SESSION_QUEUE_FULL (4 active jobs for this browser), QUEUE_FULL (20 globally), or VALIDATOR_BUSY; wait or cancel an active job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "200": {
            "description": "Existing idempotent job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "422": {
            "description": "Field validation errors",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Validation"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Mission"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Within this anonymous session: same key and normalized input return existing job (200); different input returns 409. At most 4 active jobs per session, 20 globally (429); idempotent retries do not consume a slot."
          }
        ]
      },
      "get": {
        "tags": [
          "Planning"
        ],
        "operationId": "listPlanningJobs",
        "summary": "Newest 200 jobs belonging to this anonymous session",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jobs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HistoryItem"
                      },
                      "minItems": 0,
                      "maxItems": 200
                    }
                  },
                  "required": []
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/planning-jobs/{jobId}": {
      "get": {
        "tags": [
          "Planning"
        ],
        "operationId": "getPlanningJob",
        "summary": "State, immutable input and complete result",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/planning-jobs/{jobId}/cancel": {
      "post": {
        "tags": [
          "Planning"
        ],
        "operationId": "cancelPlanningJob",
        "summary": "Cancel queued/running calculation, terminating its process group",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/planning-jobs/{jobId}/result": {
      "get": {
        "tags": [
          "Planning"
        ],
        "operationId": "getPlanningResult",
        "summary": "Result or 409 if not available",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Result"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/planning-jobs/{jobId}/report": {
      "get": {
        "tags": [
          "Exports"
        ],
        "operationId": "downloadPlanningReport",
        "summary": "Download input and full report",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/planning-jobs/{jobId}/exports/{uavId}/{format}": {
      "get": {
        "tags": [
          "Exports"
        ],
        "operationId": "exportUavMission",
        "summary": "Download all verified sorties for one physical UAV",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/geo+json": {
                "schema": {
                  "type": "object",
                  "description": "RFC7946 FeatureCollection, 2D lon/lat geometry. MSL and AGL heights, relative/mission timing and incoming-segment actions in properties."
                }
              },
              "application/vnd.google-earth.kml+xml": {
                "schema": {
                  "type": "string",
                  "description": "KML relativeToGround AGL. Waypoint ExtendedData: MSL height, speed, mission time, action. Viewer terrain may differ; not an autopilot protocol."
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "uavId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "geojson",
                "kml"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/mission-plans/{jobId}/uavs/{uavId}/exports/{format}": {
      "get": {
        "tags": [
          "Exports"
        ],
        "operationId": "exportUavMissionAlias",
        "summary": "Compatibility alias: download this session's verified UAV sorties",
        "security": [
          {
            "AnonymousCookie": []
          },
          {
            "LocalAnonymousCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/geo+json": {
                "schema": {
                  "type": "object",
                  "description": "RFC7946 FeatureCollection, 2D lon/lat geometry. MSL and AGL heights, relative/mission timing and incoming-segment actions in properties."
                }
              },
              "application/vnd.google-earth.kml+xml": {
                "schema": {
                  "type": "string",
                  "description": "KML relativeToGround AGL. Waypoint ExtendedData: MSL height, speed, mission time, action. Viewer terrain may differ; not an autopilot protocol."
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid or expired session cookie; bootstrap /api/v1/session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Job not found in this session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "uavId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "geojson",
                "kml"
              ]
            }
          }
        ]
      }
    },
    "/api/v1/examples": {
      "get": {
        "tags": [
          "System"
        ],
        "operationId": "listExamples",
        "summary": "Available downloadable mission examples",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "url": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      },
                      "group": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "starter": {
                        "type": "string"
                      },
                      "summary": {
                        "type": "string"
                      }
                    },
                    "required": []
                  },
                  "minItems": 0,
                  "maxItems": 1000
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/examples/{name}": {
      "get": {
        "tags": [
          "System"
        ],
        "operationId": "getExample",
        "summary": "Download a mission fixture (including intentional invalid cases)",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mission"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/readiness": {
      "get": {
        "tags": [
          "System"
        ],
        "operationId": "checkEngine",
        "summary": "Check Python executable and native binary presence",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    }
                  },
                  "required": []
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/survey-profiles": {
      "get": {
        "tags": [
          "System"
        ],
        "operationId": "getSurveyProfiles",
        "summary": "Pinned defaults and mandatory minima per survey type",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/terrain/fetch": {
      "post": {
        "tags": [
          "Terrain"
        ],
        "operationId": "fetchTerrain",
        "summary": "Fetch public terrain tiles and return a frozen 20–30 m UTM grid",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid geometry, unavailable terrain or unsupported DEM",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mission": {
                    "type": "object",
                    "properties": {
                      "area": {
                        "$ref": "#/components/schemas/Geometry"
                      },
                      "allowedAirspace": {
                        "$ref": "#/components/schemas/Geometry"
                      }
                    },
                    "required": [
                      "area",
                      "allowedAirspace"
                    ]
                  },
                  "spacingM": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 30,
                    "default": 25
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "AWS_TERRAIN_TILES",
                      "DEMO_SYNTHETIC"
                    ],
                    "default": "AWS_TERRAIN_TILES",
                    "description": "AWS fetches public terrain data. DEMO_SYNTHETIC creates artificial terrain solely for demonstrations; source.provider and source.demoOnly retain that provenance. Grid spacing is not source accuracy."
                  }
                },
                "required": [
                  "mission"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/terrain/import": {
      "post": {
        "tags": [
          "Terrain"
        ],
        "operationId": "importTerrain",
        "summary": "Import single-band DEM GeoTIFF with CRS and MSL metres",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid geometry, unavailable terrain or unsupported DEM",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "mission": {
                    "type": "string",
                    "description": "JSON mission; area and allowedAirspace required"
                  },
                  "dem": {
                    "type": "string",
                    "format": "binary",
                    "description": "Local GeoTIFF <=64 MiB; no VRT or remote references"
                  },
                  "spacingM": {
                    "type": "number",
                    "minimum": 20,
                    "maximum": 30,
                    "default": 25
                  },
                  "verticalDatum": {
                    "const": "MSL"
                  }
                },
                "required": [
                  "mission",
                  "dem",
                  "verticalDatum"
                ]
              }
            }
          }
        }
      }
    },
    "/api/v1/missions/recommend-sites": {
      "post": {
        "tags": [
          "Planning"
        ],
        "operationId": "recommendSites",
        "summary": "Pareto suggestions inside explicit siteSelectionAreas; no automatic runway selection",
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          },
          "default": {
            "description": "Request or service error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid geometry, unavailable terrain or unsupported DEM",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preparation"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "schemaVersion": {
                    "const": "1.0"
                  },
                  "missionId": {
                    "type": "string",
                    "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$"
                  },
                  "missionName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "objective": {
                    "type": "string",
                    "enum": [
                      "MIN_MAKESPAN",
                      "MIN_TOTAL_FLIGHT_TIME"
                    ],
                    "default": "MIN_TOTAL_FLIGHT_TIME"
                  },
                  "surveyType": {
                    "type": "string",
                    "enum": [
                      "VISIBLE_PHOTO",
                      "MULTISPECTRAL",
                      "THERMAL_IR",
                      "LIDAR",
                      "GEOPHYSICAL"
                    ]
                  },
                  "area": {
                    "$ref": "#/components/schemas/Geometry"
                  },
                  "allowedAirspace": {
                    "$ref": "#/components/schemas/Geometry"
                  },
                  "noFlyZones": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "area": {
                          "$ref": "#/components/schemas/Geometry"
                        },
                        "safetyBufferM": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 1000
                        }
                      },
                      "required": [
                        "area",
                        "safetyBufferM"
                      ]
                    },
                    "minItems": 0,
                    "maxItems": 20
                  },
                  "obstacles": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "area": {
                          "$ref": "#/components/schemas/Geometry"
                        },
                        "heightM": {
                          "oneOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1000
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "clearanceM": {
                          "type": "number",
                          "minimum": 1,
                          "maximum": 1000
                        }
                      },
                      "required": [
                        "area",
                        "clearanceM"
                      ],
                      "description": "heightM is above the HIGHEST ground under the ENTIRE physical footprint, including parts outside allowedAirspace. One constant MSL roof. Known heights <=150 m remain in the survey area: fly above the roof at parameters.altitudeM, or clearanceM if larger. Heights >150 m, missing height or terrain under part of the footprint require a lateral detour and exclude the buffered footprint from survey coverage, regardless of nominal flight altitude. clearanceM expands the footprint horizontally and requires vertical clearance. The 150 m threshold classifies obstacles; UAV AGL/MSL ceilings still apply to the raised route. Output altitudeAglM remains relative to terrain, not the roof."
                    },
                    "minItems": 0,
                    "maxItems": 100
                  },
                  "uavs": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Uav"
                    },
                    "minItems": 1,
                    "maxItems": 10
                  },
                  "parameters": {
                    "$ref": "#/components/schemas/Parameters"
                  },
                  "constraints": {
                    "$ref": "#/components/schemas/Constraints"
                  },
                  "terrain": {
                    "$ref": "#/components/schemas/Terrain"
                  },
                  "wind": {
                    "type": "object",
                    "properties": {
                      "speedMps": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 60
                      },
                      "gustMps": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 60
                      },
                      "directionDeg": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 360
                      }
                    },
                    "required": [],
                    "additionalProperties": false,
                    "description": "Accepted and preserved, but calculation explicitly ignores wind. Nonzero values generate WIND_IGNORED in validation and result; UI displays a warning."
                  },
                  "rechargePolicy": {
                    "type": "object",
                    "properties": {
                      "maxSortiesPerUav": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 20
                      },
                      "durationS": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 86400
                      }
                    },
                    "required": [],
                    "additionalProperties": false,
                    "description": "Optional repeated sorties: full recharge from landing state to 100% takes durationS at a charger-equipped launch/landing site."
                  },
                  "optimization": {
                    "type": "object",
                    "properties": {
                      "timeLimitMs": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 1800000,
                        "default": 180000
                      },
                      "maxIterations": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 50,
                        "default": 50
                      },
                      "maxCandidateEvaluations": {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 100000,
                        "default": 100000
                      },
                      "fixedWingOrderCandidates": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 5,
                        "default": 5,
                        "description": "Maximum fixed-wing swath visiting orders compared using fully verified flight and reserve costs. 1 keeps the native order."
                      }
                    },
                    "required": [],
                    "additionalProperties": false,
                    "description": "API, CLI and parameter lab use one default, sortie-graph-v3 (deployment-wide override PLANNER_STRATEGY). timeLimitMs and maxCandidateEvaluations bound search. In sortie-graph-v3 maxIterations bounds spatial orders (0 disables this strategy). restrictedMasterOptimal certifies only the generated candidate set, not the continuous mission."
                  },
                  "launchSites": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Site"
                    },
                    "minItems": 0,
                    "maxItems": 20
                  },
                  "primaryLandingSites": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Site"
                    },
                    "minItems": 0,
                    "maxItems": 20
                  },
                  "reserveLandingSites": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Site"
                    },
                    "minItems": 0,
                    "maxItems": 20
                  },
                  "surveyProfileVersion": {
                    "type": "string",
                    "enum": [
                      "survey-v1"
                    ],
                    "default": "survey-v1"
                  },
                  "siteSelectionAreas": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "area": {
                          "$ref": "#/components/schemas/Geometry"
                        },
                        "clearanceRadiusM": {
                          "type": "number",
                          "minimum": 1,
                          "maximum": 200,
                          "default": 15
                        },
                        "maxSlopeDeg": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 20,
                          "default": 5
                        }
                      },
                      "required": [
                        "area"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 20
                  }
                },
                "required": [
                  "schemaVersion",
                  "missionName",
                  "surveyType",
                  "area",
                  "allowedAirspace",
                  "uavs",
                  "parameters",
                  "terrain",
                  "siteSelectionAreas"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Position": {
        "type": "array",
        "prefixItems": [
          {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          {
            "type": "number",
            "minimum": -80,
            "maximum": 84
          }
        ],
        "minItems": 2,
        "maxItems": 2
      },
      "Geometry": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "Polygon"
              },
              "coordinates": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Position"
                  },
                  "minItems": 4,
                  "maxItems": 2000
                },
                "minItems": 1,
                "maxItems": 100
              }
            },
            "required": [
              "type",
              "coordinates"
            ]
          },
          {
            "type": "object",
            "properties": {
              "type": {
                "const": "MultiPolygon"
              },
              "coordinates": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Position"
                    },
                    "minItems": 4,
                    "maxItems": 2000
                  },
                  "minItems": 1,
                  "maxItems": 100
                },
                "minItems": 1,
                "maxItems": 100
              }
            },
            "required": [
              "type",
              "coordinates"
            ]
          }
        ],
        "description": "WGS84 [longitude, latitude], closed non-self-intersecting rings. At most 2000 vertices per geometry; mission <=150 km² and airspace span <=100 km. Geometric predicates are additionally validated by the server."
      },
      "Terrain": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "const": "flat"
              },
              "verticalDatum": {
                "const": "MSL"
              },
              "elevationM": {
                "type": "number",
                "minimum": -500,
                "maximum": 9000
              },
              "source": {
                "type": "object",
                "description": "Immutable provenance and snapshot hash; grid spacing is not source accuracy."
              },
              "verticalUncertaintyM": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "default": 0
              }
            },
            "required": [
              "kind",
              "verticalDatum",
              "elevationM"
            ]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "const": "grid"
              },
              "verticalDatum": {
                "const": "MSL"
              },
              "origin": {
                "$ref": "#/components/schemas/Position"
              },
              "stepM": {
                "type": "array",
                "items": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 1000
                },
                "minItems": 2,
                "maxItems": 2
              },
              "elevationsM": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number",
                    "minimum": -500,
                    "maximum": 9000
                  },
                  "minItems": 2,
                  "maxItems": 1000
                },
                "minItems": 2,
                "maxItems": 1000
              },
              "source": {
                "type": "object",
                "description": "Immutable provenance and snapshot hash; grid spacing is not source accuracy."
              },
              "verticalUncertaintyM": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "default": 0
              },
              "referenceElevationsM": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {
                    "type": "number",
                    "minimum": -500,
                    "maximum": 9000
                  },
                  "minItems": 2,
                  "maxItems": 1000
                },
                "minItems": 2,
                "maxItems": 1000
              }
            },
            "required": [
              "kind",
              "verticalDatum",
              "origin",
              "stepM",
              "elevationsM"
            ]
          }
        ],
        "description": "Grid origin is WGS84; columns go east and rows north in the mission UTM CRS. Positive metre spacing; equal row lengths; <=500000 samples; grid must cover allowedAirspace. Linear triangular interpolation. No ellipsoidal/geoid conversion. Prepared DEMs use a continuous upper envelope of source-cell maxima; referenceElevationsM keeps the sampled surface for worst-case GSD and density. verticalUncertaintyM is an explicit assumed margin (5 m for prepared snapshots, editable; not provider-certified accuracy). Ground operations use the DEM surface; operating pads require field verification."
      },
      "Constraints": {
        "type": "object",
        "properties": {
          "missionDeadlineS": {
            "type": "number",
            "minimum": 1,
            "maximum": 86400,
            "default": 86400
          },
          "calculationTimeoutS": {
            "type": "number",
            "minimum": 1,
            "maximum": 1800,
            "default": 600
          },
          "horizontalSeparationM": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "default": 20
          },
          "verticalSeparationM": {
            "type": "number",
            "minimum": 1,
            "maximum": 500,
            "default": 10
          },
          "safetyReserveRatio": {
            "type": "number",
            "minimum": 0.2,
            "maximum": 0.5,
            "default": 0.2,
            "description": "Untouchable fraction of FULL battery capacity. Usable energy = capacity * max(0, availableChargeRatio - safetyReserveRatio); the same fraction bounds time and distance."
          },
          "minimumCoverageRatio": {
            "type": "number",
            "minimum": 0.9,
            "maximum": 1,
            "default": 0.98,
            "description": "Mandatory area fraction meeting coverage AND configured side overlap. Boundary strips have the documented outer-pass exception; below-threshold plans are rejected."
          }
        },
        "required": [],
        "additionalProperties": false
      },
      "Parameters": {
        "type": "object",
        "properties": {
          "altitudeM": {
            "type": "number",
            "minimum": 5,
            "maximum": 1000
          },
          "altitudeReference": {
            "const": "AGL"
          },
          "sideOverlapRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 0.95
          },
          "forwardOverlapRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 0.95
          },
          "preferredBearingDeg": {
            "type": "number",
            "minimum": 0,
            "maximum": 360
          }
        },
        "required": [
          "altitudeM",
          "altitudeReference"
        ],
        "additionalProperties": false,
        "description": "Missing overlaps use the pinned survey profile defaults. Configured mandatory minima cannot be reduced by the mission. altitudeM is the survey height over terrain and over eligible obstacle roofs; actual terrain-relative AGL rises over a roof."
      },
      "Site": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$"
          },
          "position": {
            "$ref": "#/components/schemas/Position"
          },
          "elevationAmslM": {
            "type": "number",
            "minimum": -500,
            "maximum": 9000
          },
          "supportedTakeoffTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "VERTICAL",
                "RUNWAY",
                "CATAPULT"
              ]
            },
            "minItems": 1,
            "maxItems": 5
          },
          "supportedLandingTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "VERTICAL",
                "RUNWAY",
                "PARACHUTE"
              ]
            },
            "minItems": 1,
            "maxItems": 5
          },
          "headingDeg": {
            "type": "number",
            "minimum": 0,
            "maximum": 360
          },
          "approachLengthM": {
            "type": "number",
            "minimum": 1,
            "maximum": 10000
          },
          "capacity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 1
          },
          "clearanceTimeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 3600,
            "default": 30
          },
          "runwayLengthM": {
            "type": "number",
            "minimum": 1,
            "maximum": 10000
          },
          "chargerCount": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10,
            "default": 0
          }
        },
        "required": [
          "id",
          "position"
        ],
        "description": "One physical pad shares capacity and clearanceTimeS across roles and aliases. Aircraft are staged off-pad before takeoff; after landing a slot stays occupied for clearanceTimeS. RUNWAY requires headingDeg and a sufficient runwayLengthM. approachLengthM is airborne approach/departure length, not runway length. Heights come from the planning DEM. Reserve must be physically distinct from primary landing."
      },
      "EnergyProfile": {
        "type": "object",
        "properties": {
          "takeoffPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "climbPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "cruisePowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "surveyPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "turnPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "descentPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "landingPowerW": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "takeoffDurationS": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "landingDurationS": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "climbRateMps": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          },
          "descentRateMps": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 1000000.0
          }
        },
        "required": [
          "takeoffPowerW",
          "climbPowerW",
          "cruisePowerW",
          "surveyPowerW",
          "turnPowerW",
          "descentPowerW",
          "landingPowerW",
          "takeoffDurationS",
          "landingDurationS",
          "climbRateMps",
          "descentRateMps"
        ],
        "description": "Explicit calibrated phase powers in W, durations in s, vertical rates in m/s. Examples use synthetic parameters."
      },
      "UavCapabilities": {
        "type": "object",
        "properties": {
          "airframeType": {
            "type": "string",
            "enum": [
              "MULTIROTOR",
              "FIXED_WING",
              "VTOL"
            ]
          },
          "takeoffType": {
            "type": "string",
            "enum": [
              "VERTICAL",
              "RUNWAY",
              "CATAPULT"
            ]
          },
          "landingType": {
            "type": "string",
            "enum": [
              "VERTICAL",
              "RUNWAY",
              "PARACHUTE"
            ]
          },
          "energyProfile": {
            "$ref": "#/components/schemas/EnergyProfile"
          },
          "minSpeedMps": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "cruiseSpeedMps": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 100
          },
          "maxSpeedMps": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 100
          },
          "maxWindSpeedMps": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "maxFlightTimeS": {
            "type": "number",
            "minimum": 1,
            "maximum": 86400
          },
          "maxRouteDistanceM": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000000.0
          },
          "maxPayloadKg": {
            "type": "number",
            "minimum": 0.001,
            "maximum": 1000
          },
          "minSafeAltitudeAglM": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000
          },
          "maxAltitudeAglM": {
            "type": "number",
            "minimum": 1,
            "maximum": 10000
          },
          "maxAltitudeAmslM": {
            "type": "number",
            "minimum": 1,
            "maximum": 15000
          },
          "minTurnRadiusM": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000
          },
          "batteryCapacityWh": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000000.0
          },
          "takeoffRunM": {
            "type": "number",
            "minimum": 1,
            "maximum": 10000
          },
          "landingRunM": {
            "type": "number",
            "minimum": 1,
            "maximum": 10000
          }
        },
        "required": [
          "airframeType",
          "takeoffType",
          "landingType",
          "energyProfile",
          "minSpeedMps",
          "cruiseSpeedMps",
          "maxSpeedMps",
          "maxWindSpeedMps",
          "maxFlightTimeS",
          "maxRouteDistanceM",
          "maxPayloadKg",
          "minSafeAltitudeAglM",
          "maxAltitudeAglM",
          "maxAltitudeAmslM",
          "minTurnRadiusM",
          "batteryCapacityWh"
        ],
        "allOf": [
          {
            "if": {
              "properties": {
                "takeoffType": {
                  "const": "RUNWAY"
                }
              },
              "required": [
                "takeoffType"
              ]
            },
            "then": {
              "properties": {
                "takeoffRunM": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 10000
                }
              },
              "required": [
                "takeoffRunM"
              ]
            }
          },
          {
            "if": {
              "properties": {
                "landingType": {
                  "const": "RUNWAY"
                }
              },
              "required": [
                "landingType"
              ]
            },
            "then": {
              "properties": {
                "landingRunM": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 10000
                }
              },
              "required": [
                "landingRunM"
              ]
            }
          }
        ],
        "description": "Fixed wings: CATAPULT/RUNWAY takeoff, PARACHUTE/RUNWAY landing, positive minSpeedMps and minTurnRadiusM >=1. VTOL: vertical operations and fixed-wing cruise. Explicit synthetic or calibrated phase powers are required."
      },
      "Sensor": {
        "type": "object",
        "properties": {
          "surveyType": {
            "type": "string",
            "enum": [
              "VISIBLE_PHOTO",
              "MULTISPECTRAL",
              "THERMAL_IR",
              "LIDAR",
              "GEOPHYSICAL"
            ]
          },
          "weightKg": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000
          },
          "horizontalFieldOfViewDeg": {
            "type": "number",
            "minimum": 1,
            "maximum": 150
          },
          "verticalFieldOfViewDeg": {
            "type": "number",
            "minimum": 1,
            "maximum": 150
          },
          "minTriggerIntervalS": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 100
          },
          "properties": {
            "type": "object",
            "properties": {
              "imageWidthPx": {
                "type": "number",
                "minimum": 32,
                "maximum": 100000
              },
              "maxGsdCm": {
                "type": "number",
                "minimum": 0.01,
                "maximum": 1000
              },
              "scanAngleDeg": {
                "type": "number",
                "minimum": 1,
                "maximum": 120
              },
              "effectivePointsPerSecond": {
                "type": "number",
                "minimum": 1,
                "maximum": 2000000.0
              },
              "targetDensityPerM2": {
                "type": "number",
                "minimum": 0.1,
                "maximum": 10000
              },
              "lineSpacingM": {
                "type": "number",
                "minimum": 1,
                "maximum": 1000
              },
              "sampleSpacingM": {
                "type": "number",
                "minimum": 0.01,
                "maximum": 100
              },
              "samplingHz": {
                "type": "number",
                "minimum": 0.01,
                "maximum": 10000
              }
            },
            "required": []
          }
        },
        "required": [
          "surveyType",
          "weightKg",
          "properties"
        ],
        "description": "RGB/multispectral/thermal require both FOVs, minTriggerIntervalS and imageWidthPx. LiDAR requires scanAngleDeg, effectivePointsPerSecond and targetDensityPerM2. Geophysics requires lineSpacingM, sampleSpacingM and samplingHz. Server checks required fields for selected type and payload compatibility."
      },
      "Uav": {
        "type": "object",
        "properties": {
          "uavId": {
            "type": "string",
            "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$"
          },
          "sensorId": {
            "type": "string",
            "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$"
          },
          "modelId": {
            "type": "string",
            "enum": [
              "GEOSCAN_201",
              "GEOSCAN_GEMINI",
              "GEOSCAN_801"
            ],
            "description": "Optional documented airframe profile selected by the operator. Numeric capabilities may be overridden; modelId must match airframeType. The UI installs a compatible default sensor when this model changes, and the operator may replace or edit it."
          },
          "availableChargeRatio": {
            "type": "number",
            "minimum": 0.001,
            "maximum": 1
          },
          "uav": {
            "$ref": "#/components/schemas/UavCapabilities"
          },
          "sensor": {
            "$ref": "#/components/schemas/Sensor"
          },
          "sensorModelId": {
            "type": "string",
            "enum": [
              "RIEBO_R4",
              "RIEBO_R6",
              "POLLUX_201",
              "GEMINI_PF1B",
              "POLLUX_GEMINI",
              "GS801_RGB_WIDE",
              "GS801_RGB_TELE",
              "GS801_THERMAL"
            ],
            "description": "Optional installed-camera preset. Its numeric sensor fields remain editable; values absent from the supplied brochures are provisional and must be verified for real missions."
          },
          "initialSiteId": {
            "type": "string",
            "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$",
            "description": "Optional launch-site binding for this physical aircraft. Repeated sorties return to a compatible charger-equipped base."
          }
        },
        "required": [
          "uavId",
          "sensorId",
          "availableChargeRatio",
          "uav",
          "sensor"
        ]
      },
      "Mission": {
        "type": "object",
        "properties": {
          "schemaVersion": {
            "const": "1.0"
          },
          "missionId": {
            "type": "string",
            "pattern": "^(?!\\.{1,2}$)[A-Za-z0-9_.-]{1,100}$"
          },
          "missionName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "objective": {
            "type": "string",
            "enum": [
              "MIN_MAKESPAN",
              "MIN_TOTAL_FLIGHT_TIME"
            ],
            "default": "MIN_TOTAL_FLIGHT_TIME"
          },
          "surveyType": {
            "type": "string",
            "enum": [
              "VISIBLE_PHOTO",
              "MULTISPECTRAL",
              "THERMAL_IR",
              "LIDAR",
              "GEOPHYSICAL"
            ]
          },
          "area": {
            "$ref": "#/components/schemas/Geometry"
          },
          "allowedAirspace": {
            "$ref": "#/components/schemas/Geometry"
          },
          "noFlyZones": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "area": {
                  "$ref": "#/components/schemas/Geometry"
                },
                "safetyBufferM": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000
                }
              },
              "required": [
                "area",
                "safetyBufferM"
              ]
            },
            "minItems": 0,
            "maxItems": 20
          },
          "obstacles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "area": {
                  "$ref": "#/components/schemas/Geometry"
                },
                "heightM": {
                  "oneOf": [
                    {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1000
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "clearanceM": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 1000
                }
              },
              "required": [
                "area",
                "clearanceM"
              ],
              "description": "heightM is above the HIGHEST ground under the ENTIRE physical footprint, including parts outside allowedAirspace. One constant MSL roof. Known heights <=150 m remain in the survey area: fly above the roof at parameters.altitudeM, or clearanceM if larger. Heights >150 m, missing height or terrain under part of the footprint require a lateral detour and exclude the buffered footprint from survey coverage, regardless of nominal flight altitude. clearanceM expands the footprint horizontally and requires vertical clearance. The 150 m threshold classifies obstacles; UAV AGL/MSL ceilings still apply to the raised route. Output altitudeAglM remains relative to terrain, not the roof."
            },
            "minItems": 0,
            "maxItems": 100
          },
          "uavs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Uav"
            },
            "minItems": 1,
            "maxItems": 10
          },
          "parameters": {
            "$ref": "#/components/schemas/Parameters"
          },
          "constraints": {
            "$ref": "#/components/schemas/Constraints"
          },
          "terrain": {
            "$ref": "#/components/schemas/Terrain"
          },
          "wind": {
            "type": "object",
            "properties": {
              "speedMps": {
                "type": "number",
                "minimum": 0,
                "maximum": 60
              },
              "gustMps": {
                "type": "number",
                "minimum": 0,
                "maximum": 60
              },
              "directionDeg": {
                "type": "number",
                "minimum": 0,
                "maximum": 360
              }
            },
            "required": [],
            "additionalProperties": false,
            "description": "Accepted and preserved, but calculation explicitly ignores wind. Nonzero values generate WIND_IGNORED in validation and result; UI displays a warning."
          },
          "rechargePolicy": {
            "type": "object",
            "properties": {
              "maxSortiesPerUav": {
                "type": "integer",
                "minimum": 1,
                "maximum": 20
              },
              "durationS": {
                "type": "number",
                "minimum": 0,
                "maximum": 86400
              }
            },
            "required": [],
            "additionalProperties": false,
            "description": "Optional repeated sorties: full recharge from landing state to 100% takes durationS at a charger-equipped launch/landing site."
          },
          "optimization": {
            "type": "object",
            "properties": {
              "timeLimitMs": {
                "type": "number",
                "minimum": 0,
                "maximum": 1800000,
                "default": 180000
              },
              "maxIterations": {
                "type": "number",
                "minimum": 0,
                "maximum": 50,
                "default": 50
              },
              "maxCandidateEvaluations": {
                "type": "number",
                "minimum": 0,
                "maximum": 100000,
                "default": 100000
              },
              "fixedWingOrderCandidates": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5,
                "default": 5,
                "description": "Maximum fixed-wing swath visiting orders compared using fully verified flight and reserve costs. 1 keeps the native order."
              }
            },
            "required": [],
            "additionalProperties": false,
            "description": "API, CLI and parameter lab use one default, sortie-graph-v3 (deployment-wide override PLANNER_STRATEGY). timeLimitMs and maxCandidateEvaluations bound search. In sortie-graph-v3 maxIterations bounds spatial orders (0 disables this strategy). restrictedMasterOptimal certifies only the generated candidate set, not the continuous mission."
          },
          "launchSites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Site"
            },
            "minItems": 1,
            "maxItems": 20
          },
          "primaryLandingSites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Site"
            },
            "minItems": 1,
            "maxItems": 20
          },
          "reserveLandingSites": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Site"
            },
            "minItems": 1,
            "maxItems": 20
          },
          "surveyProfileVersion": {
            "type": "string",
            "enum": [
              "survey-v1"
            ],
            "default": "survey-v1"
          },
          "siteSelectionAreas": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "area": {
                  "$ref": "#/components/schemas/Geometry"
                },
                "clearanceRadiusM": {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 200,
                  "default": 15
                },
                "maxSlopeDeg": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 20,
                  "default": 5
                }
              },
              "required": [
                "area"
              ]
            },
            "minItems": 1,
            "maxItems": 20
          }
        },
        "required": [
          "schemaVersion",
          "missionName",
          "surveyType",
          "area",
          "allowedAirspace",
          "launchSites",
          "primaryLandingSites",
          "reserveLandingSites",
          "uavs",
          "parameters",
          "terrain"
        ],
        "additionalProperties": false
      },
      "Issue": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "field": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "Validation": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "input": {
            "$ref": "#/components/schemas/Mission"
          },
          "summary": {
            "type": "object"
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            },
            "minItems": 0,
            "maxItems": 1000
          }
        },
        "required": [
          "valid"
        ]
      },
      "Metrics": {
        "type": "object",
        "properties": {
          "makespanS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "totalFlightTimeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "totalDistanceM": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "totalEnergyWh": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "usedUavCount": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "coverageRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "coveredAreaM2": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "surveyableAreaM2": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "excludedAreaM2": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "objectiveValueS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "totalRechargeTimeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0,
            "description": "Sum of charging durations over all aircraft. Not flight time; parallel charging means this is not a separate additive term in mission makespan."
          },
          "sideOverlapCoverageRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": []
      },
      "Waypoint": {
        "type": "object",
        "properties": {
          "sequenceNumber": {
            "type": "integer",
            "minimum": 1
          },
          "position": {
            "type": "array",
            "items": {
              "type": "number",
              "minimum": -10000000.0,
              "maximum": 10000000.0
            },
            "minItems": 3,
            "maxItems": 3
          },
          "altitudeAglM": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "stage": {
            "type": "string"
          },
          "segmentStage": {
            "type": "string"
          },
          "speedMps": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "timeFromStartS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "energyUsedWh": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "action": {
            "type": "object"
          }
        },
        "required": [
          "sequenceNumber",
          "position",
          "stage",
          "timeFromStartS"
        ],
        "description": "Position [lon,lat,MSL metres] is an internal tuple, not RFC7946 geometry. stage and action describe the incoming segment. Trigger distance is continuous within surveySegment across terrain vertices; endpoint acquisitions only when flagged."
      },
      "Sortie": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "uavId": {
            "type": "string"
          },
          "takeoffSiteId": {
            "type": "string"
          },
          "landingSiteId": {
            "type": "string"
          },
          "reserveLandingSiteId": {
            "type": "string"
          },
          "scheduledStartS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "scheduledEndS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "flightTimeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "distanceM": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "waypoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Waypoint"
            },
            "minItems": 2,
            "maxItems": 1000000
          },
          "sensorProfile": {
            "type": "object"
          },
          "energyEstimate": {
            "type": "object"
          },
          "airframeType": {
            "type": "string",
            "enum": [
              "MULTIROTOR",
              "FIXED_WING",
              "VTOL"
            ]
          },
          "phaseMetrics": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phase": {
                  "type": "string"
                },
                "durationS": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000.0
                },
                "distanceM": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000.0
                },
                "energyWh": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000.0
                }
              },
              "required": []
            },
            "minItems": 0,
            "maxItems": 1000
          },
          "trajectoryModel": {
            "type": "object"
          },
          "reserveRoute": {
            "type": "object"
          },
          "sequenceNumber": {
            "type": "integer",
            "minimum": 1,
            "description": "One-based sortie number for this physical uavId; uavId can repeat across sorties."
          },
          "rechargeBeforeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0,
            "description": "Charging duration before this sortie, excluding queueing and other ground waits. Zero for the first sortie."
          },
          "rechargeStartS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "rechargeEndS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "chargeBeforeRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "chargeAfterRatio": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "groundOperations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "siteId": {
                  "type": "string"
                },
                "physicalSiteId": {
                  "type": "string"
                },
                "resourceId": {
                  "type": "string"
                },
                "operation": {
                  "type": "string",
                  "enum": [
                    "TAKEOFF",
                    "LANDING",
                    "RECHARGE"
                  ]
                },
                "startS": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000.0
                },
                "endS": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000.0
                },
                "capacity": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 10
                },
                "chargeFromRatio": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                },
                "chargeToRatio": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                }
              },
              "required": []
            },
            "minItems": 0,
            "maxItems": 1000
          }
        },
        "required": [
          "id",
          "uavId",
          "waypoints",
          "scheduledStartS",
          "scheduledEndS"
        ],
        "description": "Fixed-wing reserve follows the verified route to the pre-landing gate, then a verified Dubins diversion. Landing after that gate is committed; no immediate turn-back or arbitrary emergency landing is claimed."
      },
      "Result": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "feasible": {
            "type": "boolean"
          },
          "plan": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "properties": {
                  "objective": {
                    "type": "string",
                    "enum": [
                      "MIN_MAKESPAN",
                      "MIN_TOTAL_FLIGHT_TIME"
                    ],
                    "default": "MIN_TOTAL_FLIGHT_TIME"
                  },
                  "metrics": {
                    "$ref": "#/components/schemas/Metrics"
                  },
                  "sorties": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Sortie"
                    },
                    "minItems": 1,
                    "maxItems": 200
                  },
                  "verification": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "passed": {
                          "type": "boolean"
                        }
                      },
                      "required": []
                    },
                    "minItems": 0,
                    "maxItems": 1000
                  },
                  "assumptions": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 0,
                    "maxItems": 1000
                  },
                  "search": {
                    "type": "object"
                  },
                  "nativeOptimization": {
                    "type": "object"
                  },
                  "qualityModel": {
                    "type": "string"
                  }
                },
                "required": [
                  "metrics",
                  "sorties"
                ]
              }
            ]
          },
          "violations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            },
            "minItems": 0,
            "maxItems": 1000
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            },
            "minItems": 0,
            "maxItems": 1000
          },
          "calculationTimeS": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "inputSummary": {
            "type": "object"
          }
        },
        "required": [
          "status",
          "feasible",
          "plan"
        ]
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "QUEUED",
              "RUNNING",
              "SUCCEEDED",
              "NO_SOLUTION",
              "INVALID_INPUT",
              "FAILED",
              "TIMED_OUT",
              "CANCELLED"
            ]
          },
          "missionName": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "input": {
            "$ref": "#/components/schemas/Mission"
          },
          "inputDigest": {
            "type": "string"
          },
          "inputSummary": {
            "type": "object"
          },
          "result": {
            "$ref": "#/components/schemas/Result"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "missionName",
          "createdAt"
        ]
      },
      "Problem": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "HistoryItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "QUEUED",
              "RUNNING",
              "SUCCEEDED",
              "NO_SOLUTION",
              "INVALID_INPUT",
              "FAILED",
              "TIMED_OUT",
              "CANCELLED"
            ]
          },
          "missionName": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "input": {
            "$ref": "#/components/schemas/Mission"
          },
          "inputDigest": {
            "type": "string"
          },
          "inputSummary": {
            "type": "object"
          },
          "result": {
            "type": "object",
            "properties": {
              "metrics": {
                "$ref": "#/components/schemas/Metrics"
              },
              "calculationTimeS": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000000000000.0
              }
            },
            "required": []
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "missionName",
          "createdAt"
        ],
        "description": "Compact list item; input and detailed result are omitted. Fetch job detail for its immutable input and full result."
      },
      "Preparation": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "terrain": {
            "$ref": "#/components/schemas/Terrain"
          },
          "suggestions": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "minItems": 0,
            "maxItems": 6
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            },
            "minItems": 0,
            "maxItems": 1000
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 0,
            "maxItems": 1000
          },
          "evaluatedPoints": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "feasiblePoints": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "paretoCount": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          }
        },
        "required": [
          "valid"
        ]
      }
    },
    "securitySchemes": {
      "AnonymousCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Host-geoscan_session",
        "description": "Signed HttpOnly cookie from GET /api/v1/session on HTTPS or GEOSCAN_COOKIE_SECURE. SameSite=Lax, Secure, Path=/, no Domain. The public session id is not a credential."
      },
      "LocalAnonymousCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "geoscan_session",
        "description": "Local HTTP development only. Not accepted in secure deployments. Use the cookie jar returned by GET /api/v1/session."
      }
    }
  }
}
