{
  "openapi": "3.0.3",
  "info": {
    "title": "astrea-sda-api",
    "description": "A high-performance Rust API for Space Domain Awareness (SDA), satellite tracking, SGP4 propagation, and visibility prediction",
    "contact": {
      "name": "Michael Wedd"
    },
    "license": {
      "name": "MIT OR Apache-2.0"
    },
    "version": "0.1.0"
  },
  "paths": {
    "/v1/auth/login": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Developer Account Login & JWT Token Generation",
        "description": "Authenticates developer account credentials and returns an RS256/Supabase JWT Bearer token for API access and Swagger UI authorization.",
        "operationId": "loginHandler",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Authenticated successfully and JWT token issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid email or password",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/me": {
      "get": {
        "tags": [
          "Authentication"
        ],
        "summary": "Get Current Authenticated Developer Profile",
        "description": "Returns decoded JWT claims and profile info for the authenticated caller.",
        "operationId": "getCurrentUser",
        "responses": {
          "200": {
            "description": "Decoded caller JWT claims",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Claims"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/auth/signup": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Developer Account Registration",
        "description": "Registers a new developer account and issues an authenticated RS256/Supabase JWT Bearer token.",
        "operationId": "signupHandler",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Developer account registered and JWT token issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid registration request or email already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/auth/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "RFC 7523 Private Key JWT Client Assertion M2M Token Exchange",
        "description": "Authenticates machine-to-machine service accounts via signed RSA Private Key assertions (`client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer`) and returns a scoped RS256 JWT Bearer token.",
        "operationId": "tokenExchangeHandler",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientAssertionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "M2M Client assertion verified and JWT Bearer token issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid client assertion format or unsupported grant type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid assertion signature or expired timestamp",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/conjunctions/collision-probability": {
      "post": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Calculate Conjunction Collision Probability (Pc)",
        "description": "Computes 2D encounter-plane collision probability (Pc) using Foster's algorithm given miss distance, relative velocity, hard-body radius, and combined position covariance uncertainty. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "calculateCollisionProbability",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollisionProbabilityRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Collision probability computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollisionProbabilityResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/conjunctions/search": {
      "get": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Search Conjunctions & Satellite Collision Radar",
        "description": "Evaluates close-approach orbital conjunctions across all active satellites using Rayon parallel execution. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "searchConjunctions",
        "parameters": [
          {
            "name": "max_distance_km",
            "in": "query",
            "description": "Maximum threshold distance in km between satellites to trigger a conjunction match (default: 10.0 km)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "duration_hours",
            "in": "query",
            "description": "Forecast window forward in hours (default: 24 hrs, max: 72)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conjunction radar search completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConjunctionSearchResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/pipelines/sync": {
      "post": {
        "tags": [
          "Pipelines"
        ],
        "summary": "Trigger CelesTrak Pipeline Sync",
        "description": "Triggers automated CelesTrak discovery pipeline synchronization for a specific satellite group. Protected by JWT auth (requires 'admin' role).",
        "operationId": "triggerPipelineSync",
        "parameters": [
          {
            "name": "group",
            "in": "query",
            "description": "CelesTrak satellite group name to synchronize. Options: 'curated' (default: stations, visual, last-30-days), 'all', 'stations', 'visual', 'starlink', 'weather', 'last-30-days', 'active', or a comma-separated list (e.g. 'stations,visual').",
            "required": false,
            "schema": {
              "type": "string",
              "nullable": true
            }
          },
          {
            "name": "max_age_hours",
            "in": "query",
            "description": "Maximum allowed data age in hours before triggering a CelesTrak query (default: 12.0 hours). If existing data was synced within this period, CelesTrak requests are skipped to prevent spamming.",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "force",
            "in": "query",
            "description": "Force an immediate fetch from CelesTrak, bypassing freshness checks.",
            "required": false,
            "schema": {
              "type": "boolean",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Pipeline sync completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PipelineSyncResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid or unknown satellite group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Insufficient role permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Pipeline sync execution failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "List Satellites",
        "description": "Retrieves a paginated list of satellites using base64 checkpoint cursors. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "listSatellites",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of satellites",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponseSatellite"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "post": {
        "tags": [
          "Satellites"
        ],
        "summary": "Create Satellite",
        "description": "Creates a new satellite record from Two-Line Element (TLE) set data. Protected by JWT auth (requires 'editor' or 'admin' role).",
        "operationId": "createSatellite",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSatelliteDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Satellite created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Satellite"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Insufficient role permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/decay-watch": {
      "get": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Atmospheric Drag & Orbital Decay Re-Entry Watch",
        "description": "Scans the satellite catalog for debris and satellites experiencing severe atmospheric drag or nearing uncontrolled atmospheric re-entry. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getDecayWatch",
        "parameters": [
          {
            "name": "max_perigee_km",
            "in": "query",
            "description": "Maximum perigee altitude threshold in km to flag re-entry hazard (default: 300.0 km)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of decaying objects to return (default: 50, max: 500)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decay watch scan completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecayWatchResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/overhead": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Overhead Satellite",
        "description": "Computes the satellite closest to overhead (highest elevation) across all tracked satellites using parallel Rayon propagation. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getOverheadSatellite",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "time",
            "in": "query",
            "description": "UTC timestamp for calculation epoch (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Overhead satellite computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OverheadResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No satellite overhead found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/transforms/elements": {
      "post": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Transform Orbital Elements (Cartesian, Keplerian, Modified Equinoctial)",
        "description": "Converts between Cartesian state vectors, Classical Keplerian elements, and singularity-free Modified Equinoctial elements (p, f, g, h, k, L). Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "transformOrbitalElements",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ElementTransformRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Orbital elements transformed successfully across all representations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ElementTransformResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload or singular/hyperbolic orbit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/transforms/frames": {
      "post": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Transform Coordinate Frames (ECI, ECEF, Topocentric SEZ / NED)",
        "description": "Converts position and velocity state vectors across ECI (TEME), ECEF (WGS-84), and Topocentric Horizon frames (SEZ, NED) with Greenwich Mean Sidereal Time rotation, kinematic velocity transport, Bowring geodetics, and look angle slant range/range rates. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "transformCoordinateFrames",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FrameTransformRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "State vectors transformed successfully across coordinate frames",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameTransformResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload or missing topocentric observer coordinates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Satellite by ID",
        "description": "Retrieves details for a specific satellite by its unique UUID. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatellite",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Satellite found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Satellite"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Satellites"
        ],
        "summary": "Delete Satellite",
        "description": "Deletes a satellite record by its unique UUID. Protected by JWT auth (requires 'admin' role).",
        "operationId": "deleteSatellite",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Satellite deleted successfully"
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Admin role required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Satellites"
        ],
        "summary": "Update Satellite",
        "description": "Updates a satellite's name or TLE orbital parameters. Protected by JWT auth (requires 'editor' or 'admin' role).",
        "operationId": "updateSatellite",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSatelliteDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Satellite updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Satellite"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Insufficient role permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/decay-risk": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Satellite Atmospheric Drag & Decay Risk",
        "description": "Evaluates perigee/apogee altitude above the WGS-84 ellipsoid, the re-entry regime and a risk score from perigee altitude alone. No lifetime is estimated because a TLE carries no ballistic coefficient. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatelliteDecayRisk",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Satellite orbital decay risk assessed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SatelliteDecayRiskResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/detect-anomalies": {
      "post": {
        "tags": [
          "Satellites"
        ],
        "summary": "Detect Satellite Trajectory Anomalies",
        "description": "Performs statistical residual analysis across TLE epoch parameters to identify non-natural trajectory anomalies. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "detectSatelliteAnomalies",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/AnomalyDetectionRequest"
                  }
                ],
                "nullable": true
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "description": "Anomaly detection report generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnomalyDetectionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/doppler": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Satellite RF Doppler Shift",
        "description": "Computes range rate (km/s), Doppler frequency shift (Hz), and corrected transmitter frequency for ground station tracking. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatelliteDoppler",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "center_freq_hz",
            "in": "query",
            "description": "Nominal satellite transmitter frequency in Hertz (e.g. 437500000 for 437.5 MHz UHF)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt_km",
            "in": "query",
            "description": "Observer altitude above sea level in km (default: 0.0)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "time",
            "in": "query",
            "description": "UTC timestamp for calculation epoch (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          },
          {
            "name": "relativistic",
            "in": "query",
            "description": "Use the relativistic Doppler equation with gravitational shift (default: false, classical first-order)",
            "required": false,
            "schema": {
              "type": "boolean",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Doppler shift computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DopplerResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/groundtrack": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Satellite 3D Ground Track & Trajectory",
        "description": "Computes 3D ECF coordinates, geodetic position, orbital period, footprint radius, and GeoJSON ground track line. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getGroundTrack",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite UUID",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "duration_minutes",
            "in": "query",
            "description": "Trajectory projection duration in minutes (default: 90 mins, max: 1440)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "step_seconds",
            "in": "query",
            "description": "Step sampling interval in seconds (default: 30 secs, max: 300)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Output format: 'geojson' (default), 'json', 'czml' or 'all' (geojson + czml)",
            "required": false,
            "schema": {
              "type": "string",
              "nullable": true
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "description": "UTC timestamp to start projection from (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "3D Ground Track and GeoJSON trajectory",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroundTrackResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Per-user concurrent compute quota exceeded (COMPUTE_JOB_QUOTA_BY_ROLE, default 5; admin 50); retry when a job finishes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "No compute slot freed within the queue wait; retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Computation exceeded the 30 s limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/illumination": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Satellite Illumination & Visual Magnitude",
        "description": "Computes solar shadow geometry (FullSunlight, Penumbra, Umbra), observer twilight state, observable status, and visual magnitude. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatelliteIllumination",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters (default: 0.0 m)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "time",
            "in": "query",
            "description": "UTC timestamp for calculation epoch (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Satellite illumination status computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IlluminationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/maneuvers": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Reconstruct Satellite Orbital Maneuvers",
        "description": "Detects trajectory step discontinuities and calculates delta-V vector components, fuel consumption, and maneuver classification. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatelliteManeuvers",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "startTime",
            "in": "query",
            "description": "Only report windows ending at or after this time",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          },
          {
            "name": "endTime",
            "in": "query",
            "description": "Only report windows ending at or before this time",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          },
          {
            "name": "minSmaChangeKm",
            "in": "query",
            "description": "Minimum |semi-major axis residual| in km (default 0.1)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "minInclinationChangeDeg",
            "in": "query",
            "description": "Minimum |inclination change| in degrees (default 0.005)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Orbital maneuvers reconstructed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManeuversResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/next-visible": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Next Visible Pass",
        "description": "Calculates the next visible pass for a specific satellite above elevation threshold. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getNextVisiblePass",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "threshold_deg",
            "in": "query",
            "description": "Minimum elevation angle threshold in degrees (default: 5.0 deg)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Next visible pass calculated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NextVisiblePassResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/passes": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Schedule Ground Station Satellite Passes",
        "description": "Computes multi-day pass prediction schedule (AOS, TCA, LOS, elevation, azimuth, duration, optical visibility, visual magnitude). Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatellitePasses",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters (default: 0.0 m)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "threshold_deg",
            "in": "query",
            "description": "Minimum elevation angle threshold in degrees (default: 5.0 deg)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "duration_days",
            "in": "query",
            "description": "Forecast schedule window in days (default: 3 days, max: 14)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "visible_only",
            "in": "query",
            "description": "Filter for only visually observable passes in twilight/darkness (default: false)",
            "required": false,
            "schema": {
              "type": "boolean",
              "nullable": true
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "description": "UTC timestamp to start pass schedule forecast from (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Output format: 'json' (default) or 'czml' (adds a `czml` document with one entity per pass)",
            "required": false,
            "schema": {
              "type": "string",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Satellite pass schedule computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PassScheduleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Per-user concurrent compute quota exceeded (COMPUTE_JOB_QUOTA_BY_ROLE, default 5; admin 50); retry when a job finishes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "No compute slot freed within the queue wait; retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Computation exceeded the 30 s limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/relative-motion": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Compute Satellite Relative Motion & RPO",
        "description": "Computes relative position, velocity vectors, range rate, and RPO regime in the Local-Vertical Local-Horizontal (LVLH / Hill's) frame between two satellites. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getRelativeMotion",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Primary satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "target_id",
            "in": "query",
            "description": "Target / secondary satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "time",
            "in": "query",
            "description": "UTC timestamp for calculation epoch (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          },
          {
            "name": "duration_minutes",
            "in": "query",
            "description": "Relative motion trajectory duration in minutes (default: 0, max: 1440)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "step_seconds",
            "in": "query",
            "description": "Step sampling interval in seconds (default: 60 secs, min: 5, max: 300)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Relative motion and RPO computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RelativeMotionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/satellites/{id}/state": {
      "get": {
        "tags": [
          "Satellites"
        ],
        "summary": "Get Instantaneous State Vector & Keplerian Elements",
        "description": "Computes ECI (TEME), ECEF, Geodetic state vectors and osculating Keplerian orbital elements at an exact epoch. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSatelliteState",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Satellite unique UUID identifier",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "epoch",
            "in": "query",
            "description": "UTC timestamp for calculation epoch (defaults to current time if omitted)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Satellite state vector computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SatelliteStateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Satellite not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/scenes": {
      "post": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Create Composed 3D/4D Scene",
        "description": "Composes multiple scene layers (ground tracks, passes) into a single cohesive CZML document with a shared document clock and timeline.",
        "operationId": "createScene",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "description": "Format of the response: `json` (default, returns `SceneResponse`) or `czml` (returns raw CZML array).",
            "required": false,
            "schema": {
              "type": "string",
              "nullable": true
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SceneRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Composed 3D/4D CZML scene generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SceneResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload or scene caps exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "One or more satellites in the scene layers not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Per-user concurrent compute quota exceeded (COMPUTE_JOB_QUOTA_BY_ROLE, default 5; admin 50); retry when a job finishes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "No compute slot freed within the queue wait; retry shortly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "504": {
            "description": "Computation exceeded the 30 s limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/sensors/passes": {
      "post": {
        "tags": [
          "Sensors"
        ],
        "operationId": "evaluateSensorPasses",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SingleSensorPassesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Satellite tracking passes over the sensor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SensorScheduleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid sensor or satellite parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Insufficient permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/sensors/schedule": {
      "post": {
        "tags": [
          "Sensors"
        ],
        "operationId": "scheduleSensorNetwork",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SensorScheduleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Sensor network tracking pass schedule and handovers",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SensorScheduleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid sensor parameters or limits exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Insufficient permissions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/transits/lunar": {
      "get": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Predict Lunar Satellite Transits",
        "description": "Predicts satellite silhouettes crossing in front of the Lunar disk for a ground station observer. Uses a low-accuracy lunar series (position error up to ~2 degrees), so results are screening-level. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getLunarTransits",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters (default: 0.0)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "durationDays",
            "in": "query",
            "description": "Forecast window in days (default: 7 days, max: 30)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "maxAngularSeparationDeg",
            "in": "query",
            "description": "Maximum angular separation from Sun/Moon center in degrees (default: 0.5 degrees)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lunar transit predictions generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransitPredictionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    },
    "/v1/transits/solar": {
      "get": {
        "tags": [
          "Astrodynamics"
        ],
        "summary": "Predict Solar Satellite Transits",
        "description": "Predicts satellite silhouettes crossing in front of the Solar disk for a ground station observer. Protected by JWT auth (requires 'viewer', 'editor', or 'admin' role).",
        "operationId": "getSolarTransits",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)",
            "required": true,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "alt",
            "in": "query",
            "description": "Observer altitude above sea level in meters (default: 0.0)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          },
          {
            "name": "durationDays",
            "in": "query",
            "description": "Forecast window in days (default: 7 days, max: 30)",
            "required": false,
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0
            }
          },
          {
            "name": "maxAngularSeparationDeg",
            "in": "query",
            "description": "Maximum angular separation from Sun/Moon center in degrees (default: 0.5 degrees)",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double",
              "nullable": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Solar transit predictions generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransitPredictionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Missing or invalid JWT token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal calculation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearer_auth": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AnomalyDetectionRequest": {
        "type": "object",
        "properties": {
          "minInclinationChangeDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "minSmaChangeKm": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "thresholdSigma": {
            "type": "number",
            "format": "double",
            "description": "Robust z-score (median/MAD) threshold (default 3.0)",
            "nullable": true
          }
        }
      },
      "AnomalyDetectionResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "status",
          "anomaliesDetected",
          "residualHistory"
        ],
        "properties": {
          "anomaliesDetected": {
            "type": "integer",
            "minimum": 0
          },
          "residualHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrbitalParameterResidual"
            }
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/AnomalyStatus"
          }
        }
      },
      "AnomalyStatus": {
        "type": "string",
        "enum": [
          "Nominal",
          "AnomalyDetected",
          "InsufficientData"
        ]
      },
      "AuthResponse": {
        "type": "object",
        "description": "Response returned upon successful RS256 JWT token generation.",
        "required": [
          "token",
          "tokenType",
          "expiresIn",
          "claims"
        ],
        "properties": {
          "claims": {
            "$ref": "#/components/schemas/Claims"
          },
          "expiresIn": {
            "type": "integer",
            "description": "Token lifetime in seconds (e.g. 86400)",
            "minimum": 0
          },
          "token": {
            "type": "string",
            "description": "Encoded RS256 JWT Bearer token"
          },
          "tokenType": {
            "type": "string",
            "description": "Token type (always \"Bearer\")"
          }
        }
      },
      "CartesianState": {
        "type": "object",
        "required": [
          "positionKm",
          "velocityKms"
        ],
        "properties": {
          "positionKm": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "velocityKms": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          }
        }
      },
      "Claims": {
        "type": "object",
        "description": "JWT Claims payload structure containing standard OIDC and OAuth 2.0 claim fields.",
        "required": [
          "sub",
          "exp",
          "iat"
        ],
        "properties": {
          "aud": {
            "type": "string",
            "description": "Token audience (target API audience)",
            "nullable": true
          },
          "cnf": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CnfClaim"
              }
            ],
            "nullable": true
          },
          "exp": {
            "type": "integer",
            "description": "Expiration timestamp in seconds since Unix epoch",
            "minimum": 0
          },
          "iat": {
            "type": "integer",
            "description": "Issued-at timestamp in seconds since Unix epoch",
            "minimum": 0
          },
          "iss": {
            "type": "string",
            "description": "Token issuer (OIDC issuer URI or auth server ID)",
            "nullable": true
          },
          "role": {
            "type": "string",
            "description": "User role (\"viewer\", \"editor\", or \"admin\")"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional list of secondary roles",
            "nullable": true
          },
          "scope": {
            "type": "string",
            "description": "Space-separated OAuth 2.0 scopes string (e.g. \"read:satellites write:satellites admin:satellites\")",
            "nullable": true
          },
          "sub": {
            "type": "string",
            "description": "Subject (User ID, username, or client service ID)"
          }
        }
      },
      "ClassicalKeplerianElements": {
        "type": "object",
        "required": [
          "semiMajorAxisKm",
          "eccentricity",
          "inclinationDeg",
          "raanDeg",
          "argOfPerigeeDeg",
          "trueAnomalyDeg",
          "meanAnomalyDeg",
          "orbitalPeriodMinutes",
          "perigeeAltitudeKm",
          "apogeeAltitudeKm"
        ],
        "properties": {
          "apogeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "argOfPerigeeDeg": {
            "type": "number",
            "format": "double"
          },
          "eccentricity": {
            "type": "number",
            "format": "double"
          },
          "inclinationDeg": {
            "type": "number",
            "format": "double"
          },
          "meanAnomalyDeg": {
            "type": "number",
            "format": "double"
          },
          "orbitalPeriodMinutes": {
            "type": "number",
            "format": "double"
          },
          "perigeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "raanDeg": {
            "type": "number",
            "format": "double"
          },
          "semiMajorAxisKm": {
            "type": "number",
            "format": "double"
          },
          "trueAnomalyDeg": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "ClientAssertionRequest": {
        "type": "object",
        "description": "Request body for RFC 7523 Private Key JWT Client Assertion token exchange (M2M authentication).",
        "required": [
          "grantType",
          "clientAssertionType",
          "clientAssertion"
        ],
        "properties": {
          "clientAssertion": {
            "type": "string",
            "description": "RS256-signed JWT assertion token generated using client's RSA private key"
          },
          "clientAssertionType": {
            "type": "string",
            "description": "Client assertion type (must be \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\")"
          },
          "grantType": {
            "type": "string",
            "description": "OAuth 2.0 grant type (must be \"client_credentials\" or \"urn:ietf:params:oauth:grant-type:jwt-bearer\")"
          },
          "scope": {
            "type": "string",
            "description": "Optional requested OAuth 2.0 scope",
            "nullable": true
          }
        }
      },
      "CnfClaim": {
        "type": "object",
        "description": "RFC 8705 OIDC Confirmation Claim (`cnf`) containing SHA-256 certificate thumbprint (`x5t#S256`).",
        "required": [
          "x5t#S256"
        ],
        "properties": {
          "x5t#S256": {
            "type": "string",
            "description": "SHA-256 base64url-encoded client certificate thumbprint"
          }
        }
      },
      "CollisionProbabilityRequest": {
        "type": "object",
        "required": [
          "missDistanceKm",
          "relativeVelocityKms",
          "sigma1M",
          "sigma2M"
        ],
        "properties": {
          "hardBodyRadiusM": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "missAngleDeg": {
            "type": "number",
            "format": "double",
            "description": "Angle of the miss vector from the sigma_1 axis in degrees (default 0)",
            "nullable": true
          },
          "missDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "relativeVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "sigma1M": {
            "type": "number",
            "format": "double",
            "description": "Principal-axis 1-sigma position uncertainty in the encounter plane (metres), major axis"
          },
          "sigma2M": {
            "type": "number",
            "format": "double",
            "description": "Principal-axis 1-sigma position uncertainty in the encounter plane (metres), minor axis"
          }
        }
      },
      "CollisionProbabilityResponse": {
        "type": "object",
        "required": [
          "missDistanceKm",
          "relativeVelocityKms",
          "hardBodyRadiusM",
          "sigma1M",
          "sigma2M",
          "missAngleDeg",
          "collisionProbability",
          "riskCategory",
          "recommendation"
        ],
        "properties": {
          "collisionProbability": {
            "type": "number",
            "format": "double"
          },
          "hardBodyRadiusM": {
            "type": "number",
            "format": "double"
          },
          "missAngleDeg": {
            "type": "number",
            "format": "double"
          },
          "missDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "recommendation": {
            "type": "string"
          },
          "relativeVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "riskCategory": {
            "type": "string"
          },
          "sigma1M": {
            "type": "number",
            "format": "double"
          },
          "sigma2M": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "ConjunctionMatch": {
        "type": "object",
        "required": [
          "satelliteA",
          "satelliteB",
          "closestApproachTime",
          "minDistanceKm",
          "relativeVelocityKms"
        ],
        "properties": {
          "closestApproachTime": {
            "type": "string",
            "format": "date-time"
          },
          "collisionProbability": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "minDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "relativeVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "riskCategory": {
            "type": "string",
            "nullable": true
          },
          "satelliteA": {
            "$ref": "#/components/schemas/SatelliteSummary"
          },
          "satelliteB": {
            "$ref": "#/components/schemas/SatelliteSummary"
          }
        }
      },
      "ConjunctionSearchResponse": {
        "type": "object",
        "required": [
          "searchDurationHours",
          "maxDistanceKm",
          "conjunctionsFound",
          "results"
        ],
        "properties": {
          "conjunctionsFound": {
            "type": "integer",
            "minimum": 0
          },
          "maxDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConjunctionMatch"
            }
          },
          "searchDurationHours": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "CoordinateFrame": {
        "type": "string",
        "enum": [
          "ECI_TEME",
          "ECEF_WGS84",
          "TOPOCENTRIC_SEZ",
          "TOPOCENTRIC_NED"
        ]
      },
      "CreateSatelliteDto": {
        "type": "object",
        "required": [
          "name",
          "lineOne",
          "lineTwo"
        ],
        "properties": {
          "lineOne": {
            "type": "string"
          },
          "lineTwo": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "DecayWatchResponse": {
        "type": "object",
        "required": [
          "scannedSatellitesCount",
          "decayingSatellitesFound",
          "thresholdPerigeeKm",
          "objects"
        ],
        "properties": {
          "decayingSatellitesFound": {
            "type": "integer",
            "minimum": 0
          },
          "objects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SatelliteDecayRiskResponse"
            }
          },
          "scannedSatellitesCount": {
            "type": "integer",
            "minimum": 0
          },
          "thresholdPerigeeKm": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "DetectedManeuver": {
        "type": "object",
        "description": "A candidate maneuver: an element discontinuity between two consecutive TLEs that\nexceeds the requested thresholds. It happened somewhere inside the window; TLEs\ncannot localise it further. Unmodelled drag or TLE fit errors can also cause one.",
        "required": [
          "windowStart",
          "windowEnd",
          "semiMajorAxisResidualKm",
          "inclinationChangeDeg",
          "maneuverType"
        ],
        "properties": {
          "inclinationChangeDeg": {
            "type": "number",
            "format": "double",
            "description": "Observed mean inclination change, in degrees"
          },
          "maneuverType": {
            "$ref": "#/components/schemas/ManeuverType"
          },
          "semiMajorAxisResidualKm": {
            "type": "number",
            "format": "double",
            "description": "Observed mean semi-major axis minus the value predicted by the earlier TLE's\nmean-motion derivatives, in km"
          },
          "windowEnd": {
            "type": "string",
            "format": "date-time"
          },
          "windowStart": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DopplerResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "centerFreqHz",
          "rangeRateKms",
          "dopplerShiftHz",
          "correctedFreqHz",
          "signalDirection"
        ],
        "properties": {
          "centerFreqHz": {
            "type": "number",
            "format": "double"
          },
          "correctedFreqHz": {
            "type": "number",
            "format": "double"
          },
          "dopplerShiftHz": {
            "type": "number",
            "format": "double"
          },
          "rangeRateKms": {
            "type": "number",
            "format": "double"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "signalDirection": {
            "type": "string"
          }
        }
      },
      "ElementTransformRequest": {
        "type": "object",
        "properties": {
          "cartesian": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CartesianState"
              }
            ],
            "nullable": true
          },
          "equinoctial": {
            "allOf": [
              {
                "$ref": "#/components/schemas/EquinoctialInput"
              }
            ],
            "nullable": true
          },
          "keplerian": {
            "allOf": [
              {
                "$ref": "#/components/schemas/KeplerianInput"
              }
            ],
            "nullable": true
          }
        }
      },
      "ElementTransformResponse": {
        "type": "object",
        "required": [
          "cartesian",
          "keplerian",
          "equinoctial"
        ],
        "properties": {
          "cartesian": {
            "$ref": "#/components/schemas/CartesianState"
          },
          "equinoctial": {
            "$ref": "#/components/schemas/ModifiedEquinoctialElements"
          },
          "keplerian": {
            "$ref": "#/components/schemas/ClassicalKeplerianElements"
          }
        }
      },
      "EquinoctialInput": {
        "type": "object",
        "required": [
          "pKm",
          "f",
          "g",
          "h",
          "k"
        ],
        "properties": {
          "f": {
            "type": "number",
            "format": "double"
          },
          "g": {
            "type": "number",
            "format": "double"
          },
          "h": {
            "type": "number",
            "format": "double"
          },
          "k": {
            "type": "number",
            "format": "double"
          },
          "meanLongitudeDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "pKm": {
            "type": "number",
            "format": "double"
          },
          "retrogradeFactor": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "trueLongitudeDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error",
          "status"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "FrameTransformRequest": {
        "type": "object",
        "required": [
          "sourceFrame",
          "targetFrame",
          "epoch",
          "position"
        ],
        "properties": {
          "epoch": {
            "type": "string",
            "format": "date-time"
          },
          "observerAltM": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "observerLatDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "observerLonDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "position": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "sourceFrame": {
            "$ref": "#/components/schemas/CoordinateFrame"
          },
          "targetFrame": {
            "$ref": "#/components/schemas/CoordinateFrame"
          },
          "velocity": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            },
            "nullable": true
          }
        }
      },
      "FrameTransformResponse": {
        "type": "object",
        "required": [
          "sourceFrame",
          "targetFrame",
          "epoch",
          "position"
        ],
        "properties": {
          "epoch": {
            "type": "string",
            "format": "date-time"
          },
          "geodetic": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GeodeticCoordinates"
              }
            ],
            "nullable": true
          },
          "lookAngles": {
            "allOf": [
              {
                "$ref": "#/components/schemas/LookAnglesDetail"
              }
            ],
            "nullable": true
          },
          "position": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "sourceFrame": {
            "$ref": "#/components/schemas/CoordinateFrame"
          },
          "targetFrame": {
            "$ref": "#/components/schemas/CoordinateFrame"
          },
          "velocity": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            },
            "nullable": true
          }
        }
      },
      "GeoJsonFeature": {
        "type": "object",
        "required": [
          "type",
          "geometry",
          "properties"
        ],
        "properties": {
          "geometry": {
            "$ref": "#/components/schemas/GeoJsonGeometry"
          },
          "properties": {},
          "type": {
            "type": "string"
          }
        }
      },
      "GeoJsonGeometry": {
        "type": "object",
        "required": [
          "type",
          "coordinates"
        ],
        "properties": {
          "coordinates": {},
          "type": {
            "type": "string"
          }
        }
      },
      "GeodeticCoordinates": {
        "type": "object",
        "required": [
          "latitudeDeg",
          "longitudeDeg",
          "altitudeKm"
        ],
        "properties": {
          "altitudeKm": {
            "type": "number",
            "format": "double"
          },
          "latitudeDeg": {
            "type": "number",
            "format": "double"
          },
          "longitudeDeg": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "GroundTrackPoint": {
        "type": "object",
        "required": [
          "timestamp",
          "lat",
          "lon",
          "altKm",
          "positionEcfKm",
          "velocityEcfKms"
        ],
        "properties": {
          "altKm": {
            "type": "number",
            "format": "double"
          },
          "lat": {
            "type": "number",
            "format": "double"
          },
          "lon": {
            "type": "number",
            "format": "double"
          },
          "positionEcfKm": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "velocityEcfKms": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          }
        }
      },
      "GroundTrackResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "orbitalPeriodMinutes",
          "footprintRadiusKm",
          "durationMinutes",
          "stepSeconds",
          "trajectory",
          "droppedSamples"
        ],
        "properties": {
          "czml": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "nullable": true
          },
          "droppedSamples": {
            "type": "integer",
            "description": "Requested sample instants SGP4 could not produce (omitted from `trajectory`)",
            "minimum": 0
          },
          "durationMinutes": {
            "type": "integer",
            "minimum": 0
          },
          "footprintPolygon": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GeoJsonFeature"
              }
            ],
            "nullable": true
          },
          "footprintRadiusKm": {
            "type": "number",
            "format": "double"
          },
          "geojson": {
            "allOf": [
              {
                "$ref": "#/components/schemas/GeoJsonFeature"
              }
            ],
            "nullable": true
          },
          "orbitalPeriodMinutes": {
            "type": "number",
            "format": "double"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "stepSeconds": {
            "type": "integer",
            "minimum": 0
          },
          "trajectory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroundTrackPoint"
            }
          }
        }
      },
      "HorizonMaskPoint": {
        "type": "object",
        "description": "2D azimuth-elevation coordinate defining a point on a terrain horizon profile.",
        "required": [
          "azimuthDeg",
          "elevationDeg"
        ],
        "properties": {
          "azimuthDeg": {
            "type": "number",
            "format": "double",
            "description": "True North-referenced azimuth in degrees [0.0, 360.0)"
          },
          "elevationDeg": {
            "type": "number",
            "format": "double",
            "description": "Minimum local horizon elevation angle in degrees [-10.0, 90.0]"
          }
        }
      },
      "IlluminationResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "lightingState",
          "observerTwilightState",
          "observerSunElevationDeg",
          "isVisiblyObservable"
        ],
        "properties": {
          "isVisiblyObservable": {
            "type": "boolean"
          },
          "lightingState": {
            "$ref": "#/components/schemas/LightingState"
          },
          "observerSunElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "observerTwilightState": {
            "$ref": "#/components/schemas/ObserverTwilightState"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          }
        }
      },
      "KeplerianElements": {
        "type": "object",
        "required": [
          "semiMajorAxisKm",
          "eccentricity",
          "inclinationDeg",
          "raanDeg",
          "argOfPerigeeDeg",
          "trueAnomalyDeg",
          "meanAnomalyDeg",
          "orbitalPeriodMinutes",
          "perigeeAltitudeKm",
          "apogeeAltitudeKm"
        ],
        "properties": {
          "apogeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "argOfPerigeeDeg": {
            "type": "number",
            "format": "double"
          },
          "eccentricity": {
            "type": "number",
            "format": "double"
          },
          "inclinationDeg": {
            "type": "number",
            "format": "double"
          },
          "meanAnomalyDeg": {
            "type": "number",
            "format": "double"
          },
          "orbitalPeriodMinutes": {
            "type": "number",
            "format": "double"
          },
          "perigeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "raanDeg": {
            "type": "number",
            "format": "double"
          },
          "semiMajorAxisKm": {
            "type": "number",
            "format": "double"
          },
          "trueAnomalyDeg": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "KeplerianInput": {
        "type": "object",
        "required": [
          "semiMajorAxisKm",
          "eccentricity",
          "inclinationDeg",
          "raanDeg",
          "argOfPerigeeDeg"
        ],
        "properties": {
          "argOfPerigeeDeg": {
            "type": "number",
            "format": "double"
          },
          "eccentricity": {
            "type": "number",
            "format": "double"
          },
          "inclinationDeg": {
            "type": "number",
            "format": "double"
          },
          "meanAnomalyDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "raanDeg": {
            "type": "number",
            "format": "double"
          },
          "semiMajorAxisKm": {
            "type": "number",
            "format": "double"
          },
          "trueAnomalyDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "LightingState": {
        "type": "string",
        "enum": [
          "FullSunlight",
          "Penumbra",
          "Umbra"
        ]
      },
      "LoginRequest": {
        "type": "object",
        "description": "Request body for developer account login.",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "description": "Developer email address or username"
          },
          "password": {
            "type": "string",
            "description": "Account password"
          }
        }
      },
      "LookAnglesDetail": {
        "type": "object",
        "required": [
          "azimuthDeg",
          "elevationDeg",
          "slantRangeKm"
        ],
        "properties": {
          "azimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "elevationDeg": {
            "type": "number",
            "format": "double"
          },
          "rangeRateKms": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "slantRangeKm": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "ManeuverType": {
        "type": "string",
        "description": "Observed element change between two consecutive TLEs. Describes what changed, not why:\nburn intent (stationkeeping, collision avoidance, ...) is not observable from TLEs.",
        "enum": [
          "SemiMajorAxisIncrease",
          "SemiMajorAxisDecrease",
          "InclinationChange",
          "Combined"
        ]
      },
      "ManeuversResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "tleEpochsAnalyzed",
          "totalManeuversDetected",
          "maneuvers"
        ],
        "properties": {
          "maneuvers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DetectedManeuver"
            }
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "tleEpochsAnalyzed": {
            "type": "integer",
            "minimum": 0
          },
          "totalManeuversDetected": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ModifiedEquinoctialElements": {
        "type": "object",
        "required": [
          "pKm",
          "f",
          "g",
          "h",
          "k",
          "trueLongitudeDeg",
          "meanLongitudeDeg",
          "retrogradeFactor"
        ],
        "properties": {
          "f": {
            "type": "number",
            "format": "double"
          },
          "g": {
            "type": "number",
            "format": "double"
          },
          "h": {
            "type": "number",
            "format": "double"
          },
          "k": {
            "type": "number",
            "format": "double"
          },
          "meanLongitudeDeg": {
            "type": "number",
            "format": "double"
          },
          "pKm": {
            "type": "number",
            "format": "double"
          },
          "retrogradeFactor": {
            "type": "integer",
            "format": "int32"
          },
          "trueLongitudeDeg": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "NextVisiblePassResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "passTime",
          "elevationDeg",
          "azimuthDeg",
          "rangeKm"
        ],
        "properties": {
          "azimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "elevationDeg": {
            "type": "number",
            "format": "double"
          },
          "passTime": {
            "type": "string",
            "format": "date-time"
          },
          "rangeKm": {
            "type": "number",
            "format": "double"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          }
        }
      },
      "ObserverTwilightState": {
        "type": "string",
        "enum": [
          "Daylight",
          "CivilTwilight",
          "NauticalTwilight",
          "AstronomicalTwilight",
          "Night"
        ]
      },
      "OrbitalParameterResidual": {
        "type": "object",
        "description": "Mean elements of one TLE and, for every TLE after the first, its change from the previous.",
        "required": [
          "epoch",
          "meanSemiMajorAxisKm",
          "inclinationDeg",
          "meanMotionRevday",
          "eccentricity",
          "bstarDrag",
          "isAnomaly"
        ],
        "properties": {
          "bstarDrag": {
            "type": "number",
            "format": "double"
          },
          "eccentricity": {
            "type": "number",
            "format": "double"
          },
          "epoch": {
            "type": "string",
            "format": "date-time"
          },
          "inclinationChangeDeg": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "inclinationDeg": {
            "type": "number",
            "format": "double"
          },
          "isAnomaly": {
            "type": "boolean"
          },
          "meanMotionRevday": {
            "type": "number",
            "format": "double"
          },
          "meanSemiMajorAxisKm": {
            "type": "number",
            "format": "double"
          },
          "semiMajorAxisResidualKm": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "OverheadResponse": {
        "type": "object",
        "required": [
          "satellite",
          "elevation"
        ],
        "properties": {
          "elevation": {
            "type": "number",
            "format": "double"
          },
          "satellite": {
            "$ref": "#/components/schemas/Satellite"
          }
        }
      },
      "PaginatedResponseSatellite": {
        "type": "object",
        "description": "Generic Paginated Response envelope",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Satellite"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationMeta"
          }
        }
      },
      "PaginationMeta": {
        "type": "object",
        "description": "Metadata envelope for paginated responses",
        "required": [
          "hasMore",
          "limit",
          "totalCount"
        ],
        "properties": {
          "hasMore": {
            "type": "boolean"
          },
          "limit": {
            "type": "integer",
            "minimum": 0
          },
          "nextCursor": {
            "type": "string",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "PassScheduleResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "observerLat",
          "observerLon",
          "observerAltM",
          "elevationThresholdDeg",
          "forecastDays",
          "passesFound",
          "passes"
        ],
        "properties": {
          "czml": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "CZML document with one entity per pass (only when `format=czml`)",
            "nullable": true
          },
          "czmlDroppedSamples": {
            "type": "integer",
            "description": "Sample instants SGP4 could not produce for the CZML tracks (only when `format=czml`)",
            "nullable": true,
            "minimum": 0
          },
          "elevationThresholdDeg": {
            "type": "number",
            "format": "double"
          },
          "forecastDays": {
            "type": "integer",
            "minimum": 0
          },
          "observerAltM": {
            "type": "number",
            "format": "double"
          },
          "observerLat": {
            "type": "number",
            "format": "double"
          },
          "observerLon": {
            "type": "number",
            "format": "double"
          },
          "passes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SatellitePass"
            }
          },
          "passesFound": {
            "type": "integer",
            "minimum": 0
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          }
        }
      },
      "PipelineGroupSyncDetail": {
        "type": "object",
        "required": [
          "group",
          "syncedCount",
          "status"
        ],
        "properties": {
          "ageHours": {
            "type": "number",
            "format": "double",
            "description": "Current age of the data in hours at query time",
            "nullable": true
          },
          "group": {
            "type": "string",
            "description": "Group identifier that was synchronized"
          },
          "lastSyncedAt": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp when this group was last synchronized from CelesTrak",
            "nullable": true
          },
          "status": {
            "type": "string",
            "description": "Freshness status: 'synced' (fetched from CelesTrak) or 'fresh' (skipped because records are within maxAgeHours)"
          },
          "syncedCount": {
            "type": "integer",
            "description": "Number of satellites upserted for this specific group (0 if skipped because data was already fresh)",
            "minimum": 0
          }
        }
      },
      "PipelineSyncResponse": {
        "type": "object",
        "required": [
          "group",
          "syncedCount",
          "message"
        ],
        "properties": {
          "availableGroups": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Available CelesTrak groups supported by the API",
            "nullable": true
          },
          "force": {
            "type": "boolean",
            "description": "Whether force mode was enabled to bypass freshness checks",
            "nullable": true
          },
          "group": {
            "type": "string",
            "description": "Requested group name or descriptive summary"
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PipelineGroupSyncDetail"
            },
            "description": "Detailed per-group synchronization counts and freshness status",
            "nullable": true
          },
          "maxAgeHours": {
            "type": "number",
            "format": "double",
            "description": "Maximum age limit applied in hours",
            "nullable": true
          },
          "message": {
            "type": "string",
            "description": "Informative status summary message"
          },
          "syncedCount": {
            "type": "integer",
            "description": "Total number of satellites newly updated across all groups",
            "minimum": 0
          }
        }
      },
      "RelativeMotionPoint": {
        "type": "object",
        "required": [
          "timestamp",
          "radialKm",
          "inTrackKm",
          "crossTrackKm",
          "rangeKm",
          "rangeRateKms"
        ],
        "properties": {
          "crossTrackKm": {
            "type": "number",
            "format": "double"
          },
          "inTrackKm": {
            "type": "number",
            "format": "double"
          },
          "radialKm": {
            "type": "number",
            "format": "double"
          },
          "rangeKm": {
            "type": "number",
            "format": "double"
          },
          "rangeRateKms": {
            "type": "number",
            "format": "double"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RelativeMotionResponse": {
        "type": "object",
        "required": [
          "primarySatellite",
          "targetSatellite",
          "epoch",
          "relativeDistanceKm",
          "rangeRateKms",
          "radialDistanceKm",
          "inTrackDistanceKm",
          "crossTrackDistanceKm",
          "radialVelocityKms",
          "inTrackVelocityKms",
          "crossTrackVelocityKms",
          "rpoRegime"
        ],
        "properties": {
          "crossTrackDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "crossTrackVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "epoch": {
            "type": "string",
            "format": "date-time"
          },
          "inTrackDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "inTrackVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "primarySatellite": {
            "$ref": "#/components/schemas/SatelliteSummary"
          },
          "radialDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "radialVelocityKms": {
            "type": "number",
            "format": "double"
          },
          "rangeRateKms": {
            "type": "number",
            "format": "double"
          },
          "relativeDistanceKm": {
            "type": "number",
            "format": "double"
          },
          "rpoRegime": {
            "type": "string"
          },
          "targetSatellite": {
            "$ref": "#/components/schemas/SatelliteSummary"
          },
          "trajectory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RelativeMotionPoint"
            },
            "nullable": true
          }
        }
      },
      "Satellite": {
        "type": "object",
        "required": [
          "id",
          "name",
          "tle",
          "createdDate",
          "lastModifiedDate"
        ],
        "properties": {
          "createdDate": {
            "type": "string",
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "lastModifiedDate": {
            "type": "string",
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "tle": {
            "$ref": "#/components/schemas/Tle"
          }
        }
      },
      "SatelliteDecayRiskResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "perigeeAltitudeKm",
          "apogeeAltitudeKm",
          "bstarDrag",
          "meanMotionDerivativeRevDay2",
          "decayStatus",
          "reentryRiskScore"
        ],
        "properties": {
          "apogeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "bstarDrag": {
            "type": "number",
            "format": "double"
          },
          "decayStatus": {
            "type": "string"
          },
          "meanMotionDerivativeRevDay2": {
            "type": "number",
            "format": "double"
          },
          "orbitalLifetimeDaysEstimate": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "perigeeAltitudeKm": {
            "type": "number",
            "format": "double"
          },
          "reentryRiskScore": {
            "type": "number",
            "format": "double"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          }
        }
      },
      "SatellitePass": {
        "type": "object",
        "required": [
          "passId",
          "aosTime",
          "aosAzimuthDeg",
          "aosElevationDeg",
          "tcaTime",
          "tcaAzimuthDeg",
          "maxElevationDeg",
          "tcaRangeKm",
          "losTime",
          "losAzimuthDeg",
          "losElevationDeg",
          "durationSeconds",
          "isVisible"
        ],
        "properties": {
          "aosAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "aosElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "aosTime": {
            "type": "string",
            "format": "date-time"
          },
          "durationSeconds": {
            "type": "number",
            "format": "double"
          },
          "isVisible": {
            "type": "boolean"
          },
          "losAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "losElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "losTime": {
            "type": "string",
            "format": "date-time"
          },
          "maxElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "passId": {
            "type": "integer",
            "minimum": 0
          },
          "tcaAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "tcaRangeKm": {
            "type": "number",
            "format": "double"
          },
          "tcaTime": {
            "type": "string",
            "format": "date-time"
          },
          "visualMagnitude": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "SatelliteStateResponse": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "epoch",
          "positionEciKm",
          "velocityEciKms",
          "positionEcefKm",
          "velocityEcefKms",
          "latitudeDeg",
          "longitudeDeg",
          "altitudeKm",
          "keplerianElements"
        ],
        "properties": {
          "altitudeKm": {
            "type": "number",
            "format": "double"
          },
          "epoch": {
            "type": "string",
            "format": "date-time"
          },
          "keplerianElements": {
            "$ref": "#/components/schemas/KeplerianElements"
          },
          "latitudeDeg": {
            "type": "number",
            "format": "double"
          },
          "longitudeDeg": {
            "type": "number",
            "format": "double"
          },
          "positionEcefKm": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "positionEciKm": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "velocityEcefKms": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "velocityEciKms": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          }
        }
      },
      "SatelliteSummary": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "SceneLayer": {
        "oneOf": [
          {
            "type": "object",
            "description": "3D orbital trajectory / ground track for a satellite",
            "required": [
              "satellite_id",
              "type"
            ],
            "properties": {
              "label": {
                "type": "string",
                "description": "Optional human-readable display label",
                "nullable": true
              },
              "rgba": {
                "type": "string",
                "format": "binary",
                "description": "Optional RGBA color override [r, g, b, a] with values 0-255",
                "nullable": true
              },
              "satellite_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique satellite identifier"
              },
              "type": {
                "type": "string",
                "enum": [
                  "groundtrack"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "Ground station pass visibility intervals and topocentric tracks",
            "required": [
              "satellite_id",
              "observer",
              "type"
            ],
            "properties": {
              "label": {
                "type": "string",
                "description": "Optional human-readable display label",
                "nullable": true
              },
              "min_elevation": {
                "type": "number",
                "format": "double",
                "description": "Minimum elevation angle threshold in degrees (defaults to 10.0)",
                "nullable": true
              },
              "observer": {
                "$ref": "#/components/schemas/SceneObserverLocation"
              },
              "satellite_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique satellite identifier"
              },
              "type": {
                "type": "string",
                "enum": [
                  "passes"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "Orbital conjunction close-approach geometry between two satellites",
            "required": [
              "primary_id",
              "secondary_id",
              "type"
            ],
            "properties": {
              "label": {
                "type": "string",
                "description": "Optional human-readable display label",
                "nullable": true
              },
              "max_distance_km": {
                "type": "number",
                "format": "double",
                "description": "Maximum miss distance threshold in km (defaults to 10.0)",
                "nullable": true
              },
              "primary_id": {
                "type": "string",
                "format": "uuid",
                "description": "Primary satellite identifier"
              },
              "secondary_id": {
                "type": "string",
                "format": "uuid",
                "description": "Secondary satellite identifier"
              },
              "type": {
                "type": "string",
                "enum": [
                  "conjunction"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "Orbital trajectory color-coded by solar illumination state (sunlit / penumbra / umbra)",
            "required": [
              "satellite_id",
              "type"
            ],
            "properties": {
              "label": {
                "type": "string",
                "description": "Optional human-readable display label",
                "nullable": true
              },
              "satellite_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique satellite identifier"
              },
              "type": {
                "type": "string",
                "enum": [
                  "illumination"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "Hill/LVLH (RTN) relative motion trajectory of target satellite relative to primary",
            "required": [
              "primary_id",
              "target_id",
              "type"
            ],
            "properties": {
              "label": {
                "type": "string",
                "description": "Optional human-readable display label",
                "nullable": true
              },
              "primary_id": {
                "type": "string",
                "format": "uuid",
                "description": "Primary satellite identifier (reference frame origin)"
              },
              "target_id": {
                "type": "string",
                "format": "uuid",
                "description": "Target satellite identifier"
              },
              "type": {
                "type": "string",
                "enum": [
                  "relativeMotion"
                ]
              }
            }
          }
        ],
        "description": "Discriminated union of scene layer specifications.",
        "discriminator": {
          "propertyName": "type"
        }
      },
      "SceneObserverLocation": {
        "type": "object",
        "description": "Observer geodetic location for ground station pass layers.",
        "required": [
          "lat",
          "lon"
        ],
        "properties": {
          "altM": {
            "type": "number",
            "format": "double",
            "description": "Observer altitude above sea level in meters (defaults to 0.0)",
            "nullable": true
          },
          "lat": {
            "type": "number",
            "format": "double",
            "description": "Observer latitude in decimal degrees (-90.0 to 90.0)"
          },
          "lon": {
            "type": "number",
            "format": "double",
            "description": "Observer longitude in decimal degrees (-180.0 to 180.0)"
          }
        }
      },
      "SceneRequest": {
        "type": "object",
        "description": "Top-level request payload for composing a 3D/4D CZML scene.",
        "required": [
          "layers"
        ],
        "properties": {
          "durationHours": {
            "type": "number",
            "format": "double",
            "description": "Scene duration in hours (0.1 to 24.0, defaults to 6.0)",
            "nullable": true
          },
          "layers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SceneLayer"
            },
            "description": "List of renderable layers in the scene (1 to 20 layers)"
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Calculation start epoch in UTC (defaults to current time if omitted)",
            "nullable": true
          },
          "stepSeconds": {
            "type": "integer",
            "description": "Ephemeris trajectory sample spacing in seconds (1 to 120, defaults to 30)",
            "nullable": true,
            "minimum": 0
          }
        }
      },
      "SceneResponse": {
        "type": "object",
        "description": "Structured response for a composed scene.",
        "required": [
          "czml",
          "droppedSamples",
          "layerCount",
          "start",
          "end"
        ],
        "properties": {
          "czml": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Composed CZML document containing the document packet followed by layer entity packets"
          },
          "droppedSamples": {
            "type": "integer",
            "description": "Total count of sample instants SGP4 could not produce across all layers",
            "minimum": 0
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "description": "Scene calculation time window end in UTC"
          },
          "layerCount": {
            "type": "integer",
            "description": "Total count of successfully composed layers in the scene",
            "minimum": 0
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Scene calculation time window start in UTC"
          }
        }
      },
      "ScheduledSensorPass": {
        "type": "object",
        "description": "Scheduled satellite tracking pass over a specific ground sensor.",
        "required": [
          "passId",
          "sensorId",
          "sensorName",
          "satelliteId",
          "satelliteName",
          "aosTime",
          "aosAzimuthDeg",
          "aosElevationDeg",
          "tcaTime",
          "tcaAzimuthDeg",
          "maxElevationDeg",
          "tcaRangeKm",
          "tcaRangeRateKms",
          "tcaAzimuthRateDegS",
          "tcaElevationRateDegS",
          "peakAzimuthRateDegS",
          "peakElevationRateDegS",
          "isMountFeasible",
          "isOpticalVisible",
          "losTime",
          "losAzimuthDeg",
          "losElevationDeg",
          "durationSeconds"
        ],
        "properties": {
          "aosAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "aosElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "aosTime": {
            "type": "string",
            "format": "date-time"
          },
          "durationSeconds": {
            "type": "number",
            "format": "double"
          },
          "isMountFeasible": {
            "type": "boolean",
            "description": "True if pass rates and elevations stay within sensor mount mechanical limits"
          },
          "isOpticalVisible": {
            "type": "boolean",
            "description": "True if satellite is illuminated and observer is in twilight/darkness"
          },
          "losAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "losElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "losTime": {
            "type": "string",
            "format": "date-time"
          },
          "maxElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "passId": {
            "type": "integer",
            "minimum": 0
          },
          "peakAzimuthRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Peak azimuth rate experienced during the pass in deg/s"
          },
          "peakElevationRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Peak elevation rate experienced during the pass in deg/s"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "sensorId": {
            "type": "string",
            "format": "uuid"
          },
          "sensorName": {
            "type": "string"
          },
          "tcaAzimuthDeg": {
            "type": "number",
            "format": "double"
          },
          "tcaAzimuthRateDegS": {
            "type": "number",
            "format": "double"
          },
          "tcaElevationRateDegS": {
            "type": "number",
            "format": "double"
          },
          "tcaRangeKm": {
            "type": "number",
            "format": "double"
          },
          "tcaRangeRateKms": {
            "type": "number",
            "format": "double"
          },
          "tcaTime": {
            "type": "string",
            "format": "date-time"
          },
          "visualMagnitude": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "SensorDefinition": {
        "type": "object",
        "description": "Definition of a ground sensor (optical telescope, radar, or tracking station).",
        "required": [
          "name",
          "lat",
          "lon",
          "altM"
        ],
        "properties": {
          "altM": {
            "type": "number",
            "format": "double",
            "description": "Altitude above WGS-84 reference ellipsoid in metres"
          },
          "horizonMask": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HorizonMaskPoint"
            },
            "description": "Custom 360° terrain horizon elevation profile",
            "nullable": true
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional sensor unique identifier (generated if omitted)",
            "nullable": true
          },
          "lat": {
            "type": "number",
            "format": "double",
            "description": "Geodetic latitude in degrees [-90.0, 90.0]"
          },
          "lon": {
            "type": "number",
            "format": "double",
            "description": "Geodetic longitude in degrees [-180.0, 180.0]"
          },
          "maxAzimuthRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Maximum mount azimuth slew rate in deg/s (e.g. 15.0 deg/s)",
            "nullable": true
          },
          "maxElevationDeg": {
            "type": "number",
            "format": "double",
            "description": "Maximum mount elevation angle in degrees (e.g. 85.0 to model zenith keyhole / dome limits)",
            "nullable": true
          },
          "maxElevationRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Maximum mount elevation slew rate in deg/s (e.g. 5.0 deg/s)",
            "nullable": true
          },
          "minElevationDeg": {
            "type": "number",
            "format": "double",
            "description": "Default minimum elevation cutoff in degrees (defaults to 10.0)",
            "nullable": true
          },
          "name": {
            "type": "string",
            "description": "Human-readable sensor name"
          },
          "opticalOnly": {
            "type": "boolean",
            "description": "Whether only sunlit passes during local darkness are tracked",
            "nullable": true
          }
        }
      },
      "SensorHandover": {
        "type": "object",
        "description": "Transition or overlap event between two sensors tracking the same satellite.",
        "required": [
          "satelliteId",
          "satelliteName",
          "fromSensorId",
          "fromSensorName",
          "toSensorId",
          "toSensorName",
          "handoverTime",
          "overlapSeconds"
        ],
        "properties": {
          "fromSensorId": {
            "type": "string",
            "format": "uuid"
          },
          "fromSensorName": {
            "type": "string"
          },
          "handoverTime": {
            "type": "string",
            "format": "date-time"
          },
          "overlapSeconds": {
            "type": "number",
            "format": "double",
            "description": "Overlap duration in seconds (positive = simultaneous dual-station coverage, negative = gap)"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "toSensorId": {
            "type": "string",
            "format": "uuid"
          },
          "toSensorName": {
            "type": "string"
          }
        }
      },
      "SensorScheduleRequest": {
        "type": "object",
        "description": "Request payload for multi-station sensor network tracking schedule generation.",
        "required": [
          "sensors",
          "satelliteIds"
        ],
        "properties": {
          "durationDays": {
            "type": "number",
            "format": "double",
            "description": "Forecast window duration in days [0.1, 14.0] (defaults to 3.0)",
            "nullable": true
          },
          "satelliteIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "List of satellite IDs to schedule (max 20)"
          },
          "sensors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SensorDefinition"
            },
            "description": "List of ground stations / optical sensors in the network (max 10)"
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "Start epoch for schedule (defaults to current time if omitted)",
            "nullable": true
          }
        }
      },
      "SensorScheduleResponse": {
        "type": "object",
        "description": "Response payload containing network schedule and handover events.",
        "required": [
          "start",
          "end",
          "totalPasses",
          "passes",
          "handovers"
        ],
        "properties": {
          "end": {
            "type": "string",
            "format": "date-time"
          },
          "handovers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SensorHandover"
            }
          },
          "passes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduledSensorPass"
            }
          },
          "start": {
            "type": "string",
            "format": "date-time"
          },
          "totalPasses": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "SignupRequest": {
        "type": "object",
        "description": "Request body for developer account registration.",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "description": "Developer email address"
          },
          "password": {
            "type": "string",
            "description": "Account password"
          },
          "role": {
            "type": "string",
            "description": "Requested role (\"viewer\", \"editor\", or \"admin\", defaults to \"viewer\")",
            "nullable": true
          }
        }
      },
      "SingleSensorPassesRequest": {
        "type": "object",
        "description": "Request payload for single-sensor pass evaluation with custom horizon and mount limits.",
        "required": [
          "sensor",
          "satelliteId"
        ],
        "properties": {
          "durationDays": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "sensor": {
            "$ref": "#/components/schemas/SensorDefinition"
          },
          "start": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Tle": {
        "type": "object",
        "required": [
          "lineOne",
          "lineTwo"
        ],
        "properties": {
          "lineOne": {
            "type": "string"
          },
          "lineTwo": {
            "type": "string"
          }
        }
      },
      "TrackingRates": {
        "type": "object",
        "description": "Angular tracking rates and radial Doppler velocity at an instant.",
        "required": [
          "rangeRateKms",
          "azimuthRateDegS",
          "elevationRateDegS"
        ],
        "properties": {
          "azimuthRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Azimuth angular tracking rate in deg/s"
          },
          "elevationRateDegS": {
            "type": "number",
            "format": "double",
            "description": "Elevation angular tracking rate in deg/s"
          },
          "rangeRateKms": {
            "type": "number",
            "format": "double",
            "description": "Slant range rate in km/s (negative = approaching, positive = receding)"
          }
        }
      },
      "TransitMatch": {
        "type": "object",
        "required": [
          "satelliteId",
          "satelliteName",
          "transitStartUtc",
          "transitCenterUtc",
          "transitEndUtc",
          "transitDurationSeconds",
          "minAngularSeparationDeg",
          "targetElevationDeg"
        ],
        "properties": {
          "minAngularSeparationDeg": {
            "type": "number",
            "format": "double"
          },
          "satelliteId": {
            "type": "string",
            "format": "uuid"
          },
          "satelliteName": {
            "type": "string"
          },
          "targetElevationDeg": {
            "type": "number",
            "format": "double"
          },
          "transitCenterUtc": {
            "type": "string",
            "format": "date-time"
          },
          "transitDurationSeconds": {
            "type": "number",
            "format": "double"
          },
          "transitEndUtc": {
            "type": "string",
            "format": "date-time"
          },
          "transitStartUtc": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TransitPredictionResponse": {
        "type": "object",
        "required": [
          "target",
          "observerLat",
          "observerLon",
          "forecastDays",
          "transitsFound",
          "results"
        ],
        "properties": {
          "forecastDays": {
            "type": "integer",
            "minimum": 0
          },
          "observerLat": {
            "type": "number",
            "format": "double"
          },
          "observerLon": {
            "type": "number",
            "format": "double"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransitMatch"
            }
          },
          "target": {
            "$ref": "#/components/schemas/TransitTarget"
          },
          "transitsFound": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "TransitTarget": {
        "type": "string",
        "enum": [
          "Sun",
          "Moon"
        ]
      },
      "UpdateSatelliteDto": {
        "type": "object",
        "properties": {
          "lineOne": {
            "type": "string",
            "nullable": true
          },
          "lineTwo": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "UserRole": {
        "type": "string",
        "description": "Modern OAuth 2.0 / OIDC Role Hierarchy for Satellite API RBAC.",
        "enum": [
          "viewer",
          "editor",
          "admin"
        ]
      }
    },
    "securitySchemes": {
      "bearer_auth": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  },
  "tags": [
    {
      "name": "Authentication",
      "description": "JWT Token issuance endpoints"
    },
    {
      "name": "Satellites",
      "description": "Satellite catalog, telemetry, and individual satellite astrodynamics"
    },
    {
      "name": "Astrodynamics",
      "description": "Multi-satellite and celestial space domain awareness (SDA) calculations"
    },
    {
      "name": "Sensors",
      "description": "Ground station, optical telescope, and radar sensor network tracking schedules"
    },
    {
      "name": "Pipelines",
      "description": "CelesTrak automated discovery pipelines"
    }
  ]
}