{
  "components": {
    "schemas": {
      "AirfoilBreakpoint": {
        "additionalProperties": false,
        "description": "One per-station airfoil assignment in an ``airfoil_layout``.\n\n``r_over_R`` is the normalized radial station the breakpoint applies at;\n``airfoil_ref`` is either an aerosandbox library name (e.g. ``\"clarky\"``) or\nan ``afl_<ksuid>`` reference to the caller's custom airfoil. Custom refs are\nresolved caller-scoped at the route and the resolved Kulfan\nweights are passed inline to the stateless service.",
        "properties": {
          "airfoil_ref": {
            "maxLength": 128,
            "minLength": 1,
            "title": "Airfoil Ref",
            "type": "string"
          },
          "r_over_R": {
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "R Over R",
            "type": "number"
          }
        },
        "required": [
          "r_over_R",
          "airfoil_ref"
        ],
        "title": "AirfoilBreakpoint",
        "type": "object"
      },
      "AirfoilListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AirfoilResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "AirfoilListResponse",
        "type": "object"
      },
      "AirfoilResource": {
        "properties": {
          "camber": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Camber"
          },
          "family": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Family"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "max_thickness": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Thickness"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "object": {
            "default": "airfoil",
            "title": "Object",
            "type": "string"
          },
          "source": {
            "title": "Source",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "source"
        ],
        "title": "AirfoilResource",
        "type": "object"
      },
      "AnalyzeGeometryRequest": {
        "additionalProperties": false,
        "description": "Aero-only operating-point analysis request (point / sweep / solve-to-target).\n\nMirrors ``CalibrateRequest``'s geometry block + ``extra=\"forbid\"`` so an\nunknown field (e.g. a stray ``motor_id``) is rejected at the boundary \u2014 the\nschema itself is the aero-only guard. Every scalar carries numeric\nbounds and the sweep ``j_steps`` is capped at 200.",
        "properties": {
          "air_density": {
            "default": 1.225,
            "description": "Air density kg/m^3",
            "exclusiveMinimum": 0.0,
            "maximum": 5.0,
            "title": "Air Density",
            "type": "number"
          },
          "airfoil": {
            "default": "naca4412",
            "maxLength": 64,
            "title": "Airfoil",
            "type": "string"
          },
          "airspeed": {
            "default": 0.0,
            "description": "Freestream m/s",
            "maximum": 343.0,
            "minimum": 0.0,
            "title": "Airspeed",
            "type": "number"
          },
          "chord": {
            "items": {
              "type": "number"
            },
            "maxItems": 50,
            "minItems": 2,
            "title": "Chord",
            "type": "array"
          },
          "diameter": {
            "description": "Diameter in inches",
            "exclusiveMinimum": 0.0,
            "maximum": 120.0,
            "title": "Diameter",
            "type": "number"
          },
          "hub_radius": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Hub Radius"
          },
          "j_from": {
            "anyOf": [
              {
                "maximum": 10.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "J From"
          },
          "j_steps": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 2.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Sweep point count (DoS bound \u2014 each step is a full solve)",
            "title": "J Steps"
          },
          "j_to": {
            "anyOf": [
              {
                "maximum": 10.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "J To"
          },
          "mode": {
            "default": "point",
            "enum": [
              "point",
              "sweep",
              "solve_to_target"
            ],
            "title": "Mode",
            "type": "string"
          },
          "num_blades": {
            "default": 2,
            "maximum": 16.0,
            "minimum": 1.0,
            "title": "Num Blades",
            "type": "integer"
          },
          "radius": {
            "items": {
              "type": "number"
            },
            "maxItems": 50,
            "minItems": 2,
            "title": "Radius",
            "type": "array"
          },
          "rpm": {
            "default": 5000.0,
            "exclusiveMinimum": 0.0,
            "maximum": 200000.0,
            "title": "Rpm",
            "type": "number"
          },
          "section_airfoils": {
            "description": "Per-station Kulfan CST sections: {lower_weights, upper_weights, leading_edge_weight, TE_thickness} per station. The legacy [lower_w, upper_w] pair form is still accepted on read.",
            "items": {},
            "title": "Section Airfoils",
            "type": "array"
          },
          "sweep": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sweep"
          },
          "target_type": {
            "anyOf": [
              {
                "enum": [
                  "thrust",
                  "power"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Target Type"
          },
          "target_value": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Target Value"
          },
          "thickness": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thickness"
          },
          "twist": {
            "description": "Twist in degrees",
            "items": {
              "type": "number"
            },
            "maxItems": 50,
            "minItems": 2,
            "title": "Twist",
            "type": "array"
          }
        },
        "required": [
          "diameter",
          "radius",
          "chord",
          "twist"
        ],
        "title": "AnalyzeGeometryRequest",
        "type": "object"
      },
      "AnalyzeGeometryResponse": {
        "description": "Bounded aero-only union response for all three modes.\n\nEvery field is optional so a single shape carries a point, a sweep, OR a\nnon-converged solve (``converged: false`` + ``reason``). NO motor/battery\nfield anywhere.",
        "properties": {
          "Cp": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cp"
          },
          "Cp_raw": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Power coefficient from the raw blade-element solve, before the empirical correction.",
            "title": "Cp Raw"
          },
          "Ct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ct"
          },
          "Ct_raw": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Thrust coefficient from the raw blade-element solve, before the empirical correction. The `stations` table integrates to this.",
            "title": "Ct Raw"
          },
          "J": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "J"
          },
          "converged": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Converged"
          },
          "efficiency": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Efficiency"
          },
          "envelope_limiting_factor": {
            "anyOf": [
              {
                "enum": [
                  "advance_ratio",
                  "tip_mach",
                  "pitch_diameter",
                  "thrust_coefficient",
                  "diameter",
                  "blade_count"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Which dimension takes this solve outside the validation envelope. Absent when `envelope_status` is `validated` or absent.",
            "title": "Envelope Limiting Factor"
          },
          "envelope_status": {
            "anyOf": [
              {
                "enum": [
                  "validated",
                  "partial",
                  "outside"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where this solve sits relative to the published validation envelope (17 two-bladed APC Thin-Electric propellers, in diameter, advance ratio J <= 0.95, tip Mach <= 0.43). `validated` = operating point and propeller both inside it. `partial` = outside in one dimension but still carrying most of the validated model \u2014 the common case, and not an error. `outside` = far enough out that the answer is the underlying physics model's own prediction. Absent when the envelope could not be established for this solve.",
            "title": "Envelope Status"
          },
          "mode": {
            "title": "Mode",
            "type": "string"
          },
          "object": {
            "default": "geometry_analysis",
            "title": "Object",
            "type": "string"
          },
          "power": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Power"
          },
          "power_raw": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Shaft power in W from the raw blade-element solve.",
            "title": "Power Raw"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "rpm": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rpm"
          },
          "stations": {
            "items": {
              "$ref": "#/components/schemas/AnalyzeStationRow"
            },
            "title": "Stations",
            "type": "array"
          },
          "sweep_Cp": {
            "items": {
              "type": "number"
            },
            "title": "Sweep Cp",
            "type": "array"
          },
          "sweep_Ct": {
            "items": {
              "type": "number"
            },
            "title": "Sweep Ct",
            "type": "array"
          },
          "sweep_J": {
            "items": {
              "type": "number"
            },
            "title": "Sweep J",
            "type": "array"
          },
          "sweep_eta": {
            "items": {
              "anyOf": [
                {
                  "type": "number"
                },
                {
                  "type": "null"
                }
              ]
            },
            "title": "Sweep Eta",
            "type": "array"
          },
          "thrust": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thrust"
          },
          "thrust_raw": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Thrust in N from the raw blade-element solve. sum(dT_dr * dr) over `stations` equals THIS, not `thrust`.",
            "title": "Thrust Raw"
          },
          "torque_raw": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Torque in N\u00b7m from the raw blade-element solve. sum(dQ_dr * dr) over `stations` equals THIS.",
            "title": "Torque Raw"
          }
        },
        "required": [
          "mode"
        ],
        "title": "AnalyzeGeometryResponse",
        "type": "object"
      },
      "AnalyzeStationRow": {
        "description": "One radial-station row of the per-station table. Aero quantities only.",
        "properties": {
          "Cd": {
            "title": "Cd",
            "type": "number"
          },
          "Cl": {
            "title": "Cl",
            "type": "number"
          },
          "Mach": {
            "title": "Mach",
            "type": "number"
          },
          "Re": {
            "title": "Re",
            "type": "number"
          },
          "beta_deg": {
            "title": "Beta Deg",
            "type": "number"
          },
          "chord": {
            "title": "Chord",
            "type": "number"
          },
          "dQ_dr": {
            "title": "Dq Dr",
            "type": "number"
          },
          "dT_dr": {
            "title": "Dt Dr",
            "type": "number"
          },
          "eta_local": {
            "title": "Eta Local",
            "type": "number"
          },
          "r_over_R": {
            "title": "R Over R",
            "type": "number"
          },
          "va": {
            "title": "Va",
            "type": "number"
          },
          "vt": {
            "title": "Vt",
            "type": "number"
          }
        },
        "required": [
          "r_over_R",
          "chord",
          "beta_deg",
          "Cl",
          "Cd",
          "Re",
          "Mach",
          "dT_dr",
          "dQ_dr",
          "va",
          "vt",
          "eta_local"
        ],
        "title": "AnalyzeStationRow",
        "type": "object"
      },
      "Body_import_airfoil_v1_airfoils_import_post": {
        "properties": {
          "file": {
            "format": "binary",
            "title": "File",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "file",
          "name"
        ],
        "title": "Body_import_airfoil_v1_airfoils_import_post",
        "type": "object"
      },
      "CalibrateAcceptedResponse": {
        "description": "202 body \u2014 the calibration job was queued.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "calibration_job",
            "title": "Object",
            "type": "string"
          },
          "status": {
            "default": "queued",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "CalibrateAcceptedResponse",
        "type": "object"
      },
      "CancelBatchResult": {
        "description": "``canceled``: terminal now \u2014 queued rows, and dynamic rows, whose status\nflips at request time. ``requested``: running sweeps; the worker honours\nthe request at its next point and the row turns canceled then.\n``skipped``: rows the batch left alone, with the reason.",
        "properties": {
          "canceled": {
            "items": {
              "type": "string"
            },
            "title": "Canceled",
            "type": "array"
          },
          "requested": {
            "items": {
              "type": "string"
            },
            "title": "Requested",
            "type": "array"
          },
          "skipped": {
            "items": {
              "$ref": "#/components/schemas/CancelSkipped"
            },
            "title": "Skipped",
            "type": "array"
          }
        },
        "required": [
          "canceled",
          "requested",
          "skipped"
        ],
        "title": "CancelBatchResult",
        "type": "object"
      },
      "CancelSelectedBody": {
        "additionalProperties": false,
        "properties": {
          "run_ids": {
            "description": "Run ids of any kind: sim_, sweep_ or dyn_ prefixed.",
            "items": {
              "type": "string"
            },
            "maxItems": 1000,
            "minItems": 1,
            "title": "Run Ids",
            "type": "array"
          }
        },
        "required": [
          "run_ids"
        ],
        "title": "CancelSelectedBody",
        "type": "object"
      },
      "CancelSkipped": {
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "reason": {
            "enum": [
              "already_terminal",
              "draft",
              "running_single_point"
            ],
            "title": "Reason",
            "type": "string"
          }
        },
        "required": [
          "id",
          "reason"
        ],
        "title": "CancelSkipped",
        "type": "object"
      },
      "ComponentBrand": {
        "properties": {
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "object": {
            "default": "component_brand",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "name",
          "count"
        ],
        "title": "ComponentBrand",
        "type": "object"
      },
      "ComponentBrandsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ComponentBrand"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "ComponentBrandsResponse",
        "type": "object"
      },
      "ComponentCreateBody": {
        "properties": {
          "name": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "spec_json": {
            "additionalProperties": true,
            "title": "Spec Json",
            "type": "object"
          },
          "type": {
            "pattern": "^(motor|battery|propeller)$",
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "name",
          "spec_json"
        ],
        "title": "ComponentCreateBody",
        "type": "object"
      },
      "ComponentIdsResponse": {
        "description": "The Select-all id list.\n\nReturns EVERY component id matching the current search + filters in the\nrequested ``sort_by``/``sort_order`` (the SAME primary ordering the paginated\nlist uses), bounded by a documented hard cap. This sidesteps the cursor-keyset\nbug \u2014 the cursor keyset is ``(created_at, public_id)`` and so cannot honor a\nnon-default ``sort_by``; a single sorted ``.limit(cap)`` query can. ``total``\nis the count returned (== matches when not truncated); ``truncated`` is true\nwhen the matching set exceeded the cap (the first ``cap`` ids, in sort order,\nare returned).",
        "properties": {
          "data": {
            "items": {
              "type": "string"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          },
          "truncated": {
            "title": "Truncated",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "total",
          "truncated"
        ],
        "title": "ComponentIdsResponse",
        "type": "object"
      },
      "ComponentPatch": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "spec_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Spec Json"
          }
        },
        "title": "ComponentPatch",
        "type": "object"
      },
      "ComponentResource": {
        "properties": {
          "base_component_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Component Id"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "object": {
            "default": "component",
            "title": "Object",
            "type": "string"
          },
          "source": {
            "title": "Source",
            "type": "string"
          },
          "spec_json": {
            "additionalProperties": true,
            "title": "Spec Json",
            "type": "object"
          },
          "type": {
            "title": "Type",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "user_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "visibility": {
            "title": "Visibility",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "source",
          "visibility",
          "name",
          "spec_json",
          "user_id",
          "base_component_id",
          "created_at",
          "updated_at"
        ],
        "title": "ComponentResource",
        "type": "object"
      },
      "ComponentSpecsResponse": {
        "description": "The Turnstile-leased datasheet readout (spec gating, 2026-08-30).\n\n``spec_json`` is the DATASHEET projection (``_CATALOG_DATASHEET_KEYS``) for\na catalog motor/battery, the headline projection for other catalog types,\nand the raw spec for the caller's own custom row. Never carries a catalog\nrow's ``inertia`` / ``L`` / battery resistances \u2014 those are absent from\nevery allowlist this response can be built from.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "component_specs",
            "title": "Object",
            "type": "string"
          },
          "spec_json": {
            "additionalProperties": true,
            "title": "Spec Json",
            "type": "object"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "spec_json"
        ],
        "title": "ComponentSpecsResponse",
        "type": "object"
      },
      "ComponentSweepAxisIn": {
        "additionalProperties": false,
        "description": "A categorical component sweep axis on the\nwire. The caller supplies component IDs (raw UUID or comp_<ksuid>); the\nhandler resolves them ownership-scoped to the resolved spec_json + name and\nstores the resolved axis in config_json[\"sweep\"][\"component_axes\"].",
        "properties": {
          "axis": {
            "enum": [
              "motor",
              "propeller",
              "battery"
            ],
            "title": "Axis",
            "type": "string"
          },
          "component_ids": {
            "description": "Component IDs (raw UUID or comp_<ksuid>) to sweep over; >=2 (a 1-value axis is not a sweep)",
            "items": {
              "type": "string"
            },
            "minItems": 2,
            "title": "Component Ids",
            "type": "array"
          },
          "slot": {
            "default": 0,
            "description": "Rotor-group index this axis targets (ignored for battery). Back-compat single-slot; prefer `slots`.",
            "minimum": 0.0,
            "title": "Slot",
            "type": "integer"
          },
          "slots": {
            "anyOf": [
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Rotor-group indices this axis targets. >1 entry \u2192 SYNCED (one shared dimension). Omitted \u2192 [slot]. Battery must be a single slot.",
            "title": "Slots"
          }
        },
        "required": [
          "axis",
          "component_ids"
        ],
        "title": "ComponentSweepAxisIn",
        "type": "object"
      },
      "ComponentWriteResponse": {
        "description": "Create/patch response: the component resource plus optional warnings.\n\n``warnings`` is omitted (null) when every spec value looks plausible.",
        "properties": {
          "base_component_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Component Id"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "object": {
            "default": "component",
            "title": "Object",
            "type": "string"
          },
          "source": {
            "title": "Source",
            "type": "string"
          },
          "spec_json": {
            "additionalProperties": true,
            "title": "Spec Json",
            "type": "object"
          },
          "type": {
            "title": "Type",
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "user_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "visibility": {
            "title": "Visibility",
            "type": "string"
          },
          "warnings": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ComponentWriteWarning"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warnings"
          }
        },
        "required": [
          "id",
          "type",
          "source",
          "visibility",
          "name",
          "spec_json",
          "user_id",
          "base_component_id",
          "created_at",
          "updated_at"
        ],
        "title": "ComponentWriteResponse",
        "type": "object"
      },
      "ComponentWriteWarning": {
        "description": "Non-blocking plausibility warning attached to a create/patch response.\n\n2026-07-16 R audit Phase C: the write succeeded \u2014 a warning never blocks \u2014\nbut a spec value looks physically implausible (e.g. spec_json.R far outside\nthe R(kv, weight) band, the signature of a mOhm/Ohm slip or a per-phase\nvalue entered where phase-to-phase is expected).",
        "properties": {
          "code": {
            "title": "Code",
            "type": "string"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "object": {
            "default": "warning",
            "title": "Object",
            "type": "string"
          },
          "param": {
            "title": "Param",
            "type": "string"
          }
        },
        "required": [
          "code",
          "param",
          "message"
        ],
        "title": "ComponentWriteWarning",
        "type": "object"
      },
      "CreditBalanceResource": {
        "properties": {
          "as_of": {
            "title": "As Of",
            "type": "string"
          },
          "breakdown": {
            "items": {
              "$ref": "#/components/schemas/CreditBucketBreakdown"
            },
            "title": "Breakdown",
            "type": "array"
          },
          "currency": {
            "const": "credit",
            "default": "credit",
            "title": "Currency",
            "type": "string"
          },
          "low_balance_threshold": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Low Balance Threshold"
          },
          "object": {
            "const": "credit_balance",
            "default": "credit_balance",
            "title": "Object",
            "type": "string"
          },
          "total": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Remaining Free compute-unit allowance, or null when unlimited is true.",
            "title": "Total"
          },
          "unlimited": {
            "description": "True for usage-uncapped paid (Pro) accounts.",
            "title": "Unlimited",
            "type": "boolean"
          }
        },
        "required": [
          "total",
          "unlimited",
          "breakdown",
          "as_of"
        ],
        "title": "CreditBalanceResource",
        "type": "object"
      },
      "CreditBucketBreakdown": {
        "properties": {
          "balance": {
            "title": "Balance",
            "type": "integer"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "type": {
            "enum": [
              "free",
              "monthly"
            ],
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "type",
          "balance"
        ],
        "title": "CreditBucketBreakdown",
        "type": "object"
      },
      "CreditUsageEventResource": {
        "properties": {
          "amount": {
            "title": "Amount",
            "type": "integer"
          },
          "balance_after": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Remaining Free allowance after this event, or null for unlimited paid (Pro) accounts.",
            "title": "Balance After"
          },
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "const": "credit_usage_event",
            "default": "credit_usage_event",
            "title": "Object",
            "type": "string"
          },
          "resource": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CreditUsageRelatedResource"
              },
              {
                "type": "null"
              }
            ]
          },
          "type": {
            "enum": [
              "simulation_debit",
              "sweep_debit",
              "monthly_grant",
              "signup_grant",
              "bounty_grant",
              "refund",
              "adjustment",
              "debit",
              "topup"
            ],
            "title": "Type",
            "type": "string"
          },
          "unit_type": {
            "enum": [
              "free",
              "monthly"
            ],
            "title": "Unit Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "amount",
          "type",
          "unit_type",
          "balance_after",
          "created_at"
        ],
        "title": "CreditUsageEventResource",
        "type": "object"
      },
      "CreditUsageListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/CreditUsageEventResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more"
        ],
        "title": "CreditUsageListResponse",
        "type": "object"
      },
      "CreditUsageRelatedResource": {
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "enum": [
              "simulation",
              "component_submission"
            ],
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "object",
          "id"
        ],
        "title": "CreditUsageRelatedResource",
        "type": "object"
      },
      "CreditUsageSummaryResource": {
        "description": "The usage meter's single owner-scoped read.\n\n``used`` is in COMPUTE UNITS (per physical rotor) \u2014 inherited from\n``metering.used_in_window`` which SUMs ``abs(amount)`` (a 4-rotor static\ncounts 4). ``cap``/``remaining`` are None for Pro because paid\nusage is unlimited. ``resets_at`` is the ROLLING reporting window's next\nage-out instant (oldest in-window debit + window length), NEVER\n``since + window`` (which always equals ``now``).",
        "properties": {
          "cap": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cap"
          },
          "object": {
            "const": "credit_usage_summary",
            "default": "credit_usage_summary",
            "title": "Object",
            "type": "string"
          },
          "remaining": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Remaining"
          },
          "resets_at": {
            "title": "Resets At",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "used": {
            "title": "Used",
            "type": "integer"
          },
          "window": {
            "enum": [
              "day",
              "week"
            ],
            "title": "Window",
            "type": "string"
          }
        },
        "required": [
          "tier",
          "window",
          "used",
          "resets_at"
        ],
        "title": "CreditUsageSummaryResource",
        "type": "object"
      },
      "DesignRequest": {
        "additionalProperties": false,
        "description": "Generate an optimal MIL starting blade from design targets.\n\nStrict (``extra=\"forbid\"``) with numeric bounds on every field. The fields are the Generate-form inputs: blade count, diameter\n(-> tip radius), hub radius, design RPM (-> Omega), design airspeed (``0`` =\nstatic \u2014 the kernel is static-valid), a thrust *or* power target, and the\nper-station airfoil layout. The server computes the optimum design-Cl\ndistribution itself (the constant Cl that maximizes blade efficiency). There\nare NO polar coefficients (hard contract) \u2014 the geometry + Re/M\ndetermine the section physics via NeuralFoil.",
        "properties": {
          "air_density": {
            "default": 1.225,
            "description": "Air density kg/m^3",
            "exclusiveMinimum": 0.0,
            "maximum": 5.0,
            "title": "Air Density",
            "type": "number"
          },
          "airfoil": {
            "default": "naca4412",
            "maxLength": 64,
            "title": "Airfoil",
            "type": "string"
          },
          "airfoil_layout": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/AirfoilBreakpoint"
                },
                "maxItems": 64,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-station airfoil breakpoints. Only the rootmost entry is used \u2014 a MIL design flies one section for the whole blade.",
            "title": "Airfoil Layout"
          },
          "airspeed": {
            "default": 0.0,
            "description": "Design airspeed m/s; 0 = static",
            "maximum": 343.0,
            "minimum": 0.0,
            "title": "Airspeed",
            "type": "number"
          },
          "design_rpm": {
            "description": "Design RPM (-> Omega)",
            "exclusiveMinimum": 0.0,
            "maximum": 200000.0,
            "title": "Design Rpm",
            "type": "number"
          },
          "diameter": {
            "description": "Diameter in inches (-> tip radius R)",
            "exclusiveMinimum": 0.0,
            "maximum": 120.0,
            "title": "Diameter",
            "type": "number"
          },
          "hub_radius": {
            "description": "Hub radius as a fraction of the tip radius (0..1)",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Hub Radius",
            "type": "number"
          },
          "num_blades": {
            "default": 2,
            "description": "Blade count",
            "maximum": 16.0,
            "minimum": 1.0,
            "title": "Num Blades",
            "type": "integer"
          },
          "section_airfoils": {
            "description": "Optional per-station Kulfan CST weight pairs [[lower_w, upper_w], ...]. Prefer 'airfoil_layout' \u2014 that is what the picker emits.",
            "items": {
              "items": {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              "type": "array"
            },
            "title": "Section Airfoils",
            "type": "array"
          },
          "target_mode": {
            "description": "Drive to a thrust OR power target",
            "enum": [
              "thrust",
              "power"
            ],
            "title": "Target Mode",
            "type": "string"
          },
          "target_value": {
            "description": "Thrust (gf) or power (W) target \u2014 unit swaps with target_mode",
            "exclusiveMinimum": 0.0,
            "title": "Target Value",
            "type": "number"
          }
        },
        "required": [
          "diameter",
          "hub_radius",
          "design_rpm",
          "target_mode",
          "target_value"
        ],
        "title": "DesignRequest",
        "type": "object"
      },
      "DynamicCreateBody": {
        "additionalProperties": false,
        "description": "Create body for ``POST /v1/dynamic-simulations``.",
        "properties": {
          "ambient_temp_c": {
            "default": 25.0,
            "maximum": 85.0,
            "minimum": -60.0,
            "title": "Ambient Temp C",
            "type": "number"
          },
          "battery_charge_pct": {
            "default": 100.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "battery_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Component Id"
          },
          "battery_esc_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Battery Esc Wire Resistance Mohm",
            "type": "number"
          },
          "battery_initial_temp_c": {
            "anyOf": [
              {
                "maximum": 85.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Initial Temp C"
          },
          "battery_topology": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackTopologyIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "density_kg_m3": {
            "exclusiveMinimum": 0.0,
            "maximum": 2.0,
            "title": "Density Kg M3",
            "type": "number"
          },
          "motor_initial_temp_c": {
            "anyOf": [
              {
                "maximum": 85.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Initial Temp C"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "rotor_groups": {
            "items": {
              "$ref": "#/components/schemas/DynamicRotorGroupIn"
            },
            "maxItems": 10,
            "title": "Rotor Groups",
            "type": "array"
          },
          "rotors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/DynamicRotorIn"
                },
                "maxItems": 16,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "One entry per rotor. Preferred over rotor_groups, and required for coaxial stacks: set coax_stack_id to the same non-zero value on the rotors that share an axis, give each a distinct coax_position_m, and set opposite rotation_sense values for a contra-rotating stack. Supply either rotors or rotor_groups, not both.",
            "title": "Rotors"
          },
          "schedule": {
            "$ref": "#/components/schemas/ScheduleIn"
          },
          "termination": {
            "$ref": "#/components/schemas/TerminationIn"
          }
        },
        "required": [
          "project_id",
          "density_kg_m3",
          "schedule",
          "termination"
        ],
        "title": "DynamicCreateBody",
        "type": "object"
      },
      "DynamicEstimateBody": {
        "additionalProperties": false,
        "description": "Body for ``POST /v1/dynamic-simulations/estimate``.\n\nAccepts the full create body's fields (so the wizard can POST the same\npayload to /estimate as it would to create) \u2014 but the estimate path consumes\nONLY the battery + termination + schedule to compute the coulombic duration,\nnever the solver. ``extra=\"forbid\"`` keeps it a strict subset-compatible body.",
        "properties": {
          "ambient_temp_c": {
            "default": 25.0,
            "maximum": 85.0,
            "minimum": -60.0,
            "title": "Ambient Temp C",
            "type": "number"
          },
          "battery_charge_pct": {
            "default": 100.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "battery_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Component Id"
          },
          "battery_esc_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Battery Esc Wire Resistance Mohm",
            "type": "number"
          },
          "battery_initial_temp_c": {
            "anyOf": [
              {
                "maximum": 85.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Initial Temp C"
          },
          "battery_topology": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackTopologyIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "density_kg_m3": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "maximum": 2.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Density Kg M3"
          },
          "motor_initial_temp_c": {
            "anyOf": [
              {
                "maximum": 85.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Initial Temp C"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Project Id"
          },
          "rotor_groups": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/DynamicRotorGroupIn"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rotor Groups"
          },
          "rotors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/DynamicRotorIn"
                },
                "maxItems": 16,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "One entry per rotor. Preferred over rotor_groups, and required for coaxial stacks: set coax_stack_id to the same non-zero value on the rotors that share an axis, give each a distinct coax_position_m, and set opposite rotation_sense values for a contra-rotating stack. Supply either rotors or rotor_groups, not both.",
            "title": "Rotors"
          },
          "schedule": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ScheduleIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "termination": {
            "$ref": "#/components/schemas/TerminationIn"
          }
        },
        "required": [
          "termination"
        ],
        "title": "DynamicEstimateBody",
        "type": "object"
      },
      "DynamicEstimateResource": {
        "additionalProperties": false,
        "properties": {
          "estimated_credits": {
            "title": "Estimated Credits",
            "type": "integer"
          },
          "estimated_duration_s": {
            "title": "Estimated Duration S",
            "type": "number"
          },
          "object": {
            "const": "dynamic_estimate",
            "default": "dynamic_estimate",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "estimated_credits",
          "estimated_duration_s"
        ],
        "title": "DynamicEstimateResource",
        "type": "object"
      },
      "DynamicListResponse": {
        "additionalProperties": false,
        "description": "Cursor-paginated list of dynamic simulations (mirrors SweepListResponse) so\nthe project page + queue strip can surface dynamic runs like steady/sweep runs.",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/DynamicResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "DynamicListResponse",
        "type": "object"
      },
      "DynamicPatch": {
        "additionalProperties": false,
        "properties": {
          "is_starred": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Starred"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "DynamicPatch",
        "type": "object"
      },
      "DynamicResource": {
        "additionalProperties": false,
        "description": "The dynamic-simulation resource. ``result`` is populated only once the run\nis ``completed`` (the worker writes it); it stays ``None`` for\nqueued/running/failed/canceled (the SweepResource optional-result idiom).",
        "properties": {
          "battery_topology": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Topology"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "credits_cost": {
            "title": "Credits Cost",
            "type": "integer"
          },
          "dispatched_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dispatched At"
          },
          "display_labels": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Labels"
          },
          "error": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "input_snapshot": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Snapshot"
          },
          "is_starred": {
            "default": false,
            "title": "Is Starred",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "dynamic_simulation",
            "default": "dynamic_simulation",
            "title": "Object",
            "type": "string"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result"
          },
          "snapshot_version": {
            "default": 2,
            "title": "Snapshot Version",
            "type": "integer"
          },
          "solver_engine": {
            "default": "prom-rs/0.3.1",
            "title": "Solver Engine",
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "running",
              "completed",
              "failed",
              "canceled"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "project_id",
          "credits_cost"
        ],
        "title": "DynamicResource",
        "type": "object"
      },
      "DynamicRotorGroupIn": {
        "additionalProperties": false,
        "description": "A rotor group for a dynamic run. Takes exactly the shared\n``RotorGroupBase`` fields \u2014 label / count (bounded 1..16) / motor+propeller ids\n/ the per-group motor-cooling trio + cooling validator / the ESC block \u2014 and\nnothing more: the schedule supplies throttle over time, so there is no static\n``throttle_pct``, no pinned motor temperatures and no oblique\nflight-condition fields on the dynamic group.\n\nESC-8 (2026-08): the ESC block arrived here when it moved down into\n``RotorGroupBase``. Before that a dynamic group carried NO ESC fields, so a\ndynamic run had no escape hatch and the worker fabricated a 10 mOhm ESC with\nno commutation type. All six fields are defaulted, so every previously-valid\nbody stays valid \u2014 this is a pure widening.",
        "properties": {
          "count": {
            "default": 1,
            "maximum": 40.0,
            "minimum": 1.0,
            "title": "Count",
            "type": "integer"
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          }
        },
        "required": [
          "label",
          "propeller_component_id"
        ],
        "title": "DynamicRotorGroupIn",
        "type": "object"
      },
      "DynamicRotorIn": {
        "additionalProperties": false,
        "description": "ONE rotor for a dynamic run.\n\nMirrors ``DynamicRotorGroupIn``: no static throttle, no pinned motor\ntemperatures, no oblique flight-condition fields \u2014 the schedule supplies all\nof those over time. It DOES take the coaxial trio, because a stack's\ngeometry is a property of the machine, not of the operating point.",
        "properties": {
          "coax_position_m": {
            "default": 0.0,
            "description": "Position along the coaxial stack axis in metres, increasing downstream (in the direction the slipstream travels). The spacing between two rotors is the difference of their positions. Ignored when coax_stack_id is 0.",
            "maximum": 2.0,
            "minimum": -2.0,
            "title": "Coax Position M",
            "type": "number"
          },
          "coax_stack_id": {
            "default": 0,
            "description": "Coaxial stack this rotor belongs to. 0 (default) means the rotor is not stacked and is simulated in isolation. Rotors sharing a non-zero value form one contra-rotating or co-rotating stack.",
            "maximum": 16.0,
            "minimum": 0.0,
            "title": "Coax Stack Id",
            "type": "integer"
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "rotation_sense": {
            "default": 1,
            "description": "Direction of rotation about the downstream axis: 1 or -1. Opposite values in one stack give a contra-rotating pair, which recovers swirl energy and is the usual choice. Only read by coaxial pairing \u2014 a single rotor's value does not affect its own performance.",
            "enum": [
              1,
              -1
            ],
            "title": "Rotation Sense",
            "type": "integer"
          }
        },
        "required": [
          "label",
          "propeller_component_id"
        ],
        "title": "DynamicRotorIn",
        "type": "object"
      },
      "EntitlementsResource": {
        "description": "The tier -> capability bundle serialized onto /v1/users/me.\n\nSourced from ``entitlement_for(user.tier)`` (default-down), so the\nfrontend has ONE authoritative entitlement source and never re-hardcodes\ntier sets. A plain declared model (NOT a ``@computed_field``) so it appears\nin the OpenAPI schema that codegen consumes.",
        "properties": {
          "api_access": {
            "title": "Api Access",
            "type": "boolean"
          },
          "cad_export": {
            "title": "Cad Export",
            "type": "boolean"
          },
          "component_specs": {
            "default": false,
            "description": "Catalog motor/battery datasheet readout (spec gating 2026-08-30): paid tiers read specs through the leased endpoint; free tier receives identity-only catalog rows.",
            "title": "Component Specs",
            "type": "boolean"
          },
          "creator_edit": {
            "title": "Creator Edit",
            "type": "boolean"
          },
          "daily_cap": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Rolling daily usage cap, or null when no daily cap applies.",
            "title": "Daily Cap"
          },
          "db_access": {
            "title": "Db Access",
            "type": "string"
          },
          "fmi_export": {
            "title": "Fmi Export",
            "type": "boolean"
          },
          "max_concurrent_runs": {
            "description": "Account-wide simulations that may execute simultaneously across dashboard sessions and every API key. Additional work stays queued.",
            "title": "Max Concurrent Runs",
            "type": "integer"
          },
          "sim_types": {
            "items": {
              "type": "string"
            },
            "title": "Sim Types",
            "type": "array"
          },
          "weekly_cap": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Compatibility field for a rolling weekly usage cap; null for current tiers.",
            "title": "Weekly Cap"
          }
        },
        "required": [
          "sim_types",
          "db_access",
          "cad_export",
          "creator_edit",
          "api_access",
          "fmi_export",
          "max_concurrent_runs",
          "daily_cap",
          "weekly_cap"
        ],
        "title": "EntitlementsResource",
        "type": "object"
      },
      "ExportGeometryRequest": {
        "additionalProperties": false,
        "description": "Export the editor's working geometry (or a saved prop) to CAD bytes.\n\nExactly ONE of (``section_coords`` inline | ``component_id`` saved-prop) is\nrequired (mutually exclusive \u2014 the ``@model_validator``). The inline path is\nthe primary one: the editor always holds ``section_coords`` from\n``/v1/geometry/generate``, so the route skips the DB entirely. The\n``component_id`` path re-runs the deterministic geometry generator\nfrom the saved ``spec_json`` (caller-scoped, IDOR-safe at the route).\n\nStrictness (the geometry house style):\n\n* ``extra=\"forbid\"`` \u2014 a stray field (e.g. a motor_id) is rejected.\n* every numeric field carries a bound; the geometry arrays are capped at 200\n stations and ``num_blades`` at ``MAX_NUM_BLADES`` (16) \u2014 the DoS guard, enforced BEFORE any loft.\n* when ``section_coords`` is present, every station must share the same point\n count (a well-posed loft requires it) \u2014 the ``@model_validator``.",
        "properties": {
          "chord": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 200,
                "minItems": 2,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Chord"
          },
          "component_id": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Component Id"
          },
          "diameter": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "maximum": 120.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Diameter in inches",
            "title": "Diameter"
          },
          "format": {
            "default": "step",
            "enum": [
              "step",
              "iges",
              "stl"
            ],
            "title": "Format",
            "type": "string"
          },
          "hub_radius": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Hub Radius"
          },
          "include_hub": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "deprecated": true,
            "description": "Deprecated no-op: the hub and hub-to-root transition are always included in the exported body.",
            "title": "Include Hub"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 120,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "num_blades": {
            "default": 2,
            "maximum": 16.0,
            "minimum": 1.0,
            "title": "Num Blades",
            "type": "integer"
          },
          "radius": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 200,
                "minItems": 2,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Absolute radii in meters",
            "title": "Radius"
          },
          "rotation": {
            "anyOf": [
              {
                "enum": [
                  "cw",
                  "ccw"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rotation"
          },
          "section_coords": {
            "anyOf": [
              {
                "items": {},
                "maxItems": 200,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Section Coords"
          },
          "sweep": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 200,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sweep"
          },
          "twist": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 200,
                "minItems": 2,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Twist in degrees",
            "title": "Twist"
          }
        },
        "title": "ExportGeometryRequest",
        "type": "object"
      },
      "FmuExportAcceptedResponse": {
        "description": "202 body \u2014 the FMU export job was queued.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "fmu_export",
            "title": "Object",
            "type": "string"
          },
          "status": {
            "default": "queued",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "FmuExportAcceptedResponse",
        "type": "object"
      },
      "FmuExportJobError": {
        "properties": {
          "error_code": {
            "title": "Error Code",
            "type": "string"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "error_code",
          "message"
        ],
        "title": "FmuExportJobError",
        "type": "object"
      },
      "FmuExportStatusResponse": {
        "description": "The job resource: poll it, or stream ``.../stream`` for live progress.\n\nRead ``units_done``/``units_total`` for progress: they are weighted by\nexpected cost and rise monotonically across the whole job.\n``chunks_done``/``chunks_total`` are the CURRENT sampling phase's own\ncounters and restart when the job moves to the next phase.",
        "properties": {
          "artifact_available": {
            "default": false,
            "title": "Artifact Available",
            "type": "boolean"
          },
          "bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bytes"
          },
          "chunks_done": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Chunks Done"
          },
          "chunks_total": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Chunks Total"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FmuExportJobError"
              },
              {
                "type": "null"
              }
            ]
          },
          "eta_s": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Eta S"
          },
          "filename": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Filename"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "fmu_export",
            "title": "Object",
            "type": "string"
          },
          "phase": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phase"
          },
          "phase_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phase Count"
          },
          "phase_index": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phase Index"
          },
          "progress": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Progress"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "units_done": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Units Done"
          },
          "units_total": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Units Total"
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "title": "FmuExportStatusResponse",
        "type": "object"
      },
      "GenerateGeometryRequest": {
        "additionalProperties": false,
        "properties": {
          "airfoil": {
            "default": "naca4412",
            "title": "Airfoil",
            "type": "string"
          },
          "airfoil_layout": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/AirfoilBreakpoint"
                },
                "maxItems": 64,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Airfoil Layout"
          },
          "chord_spline": {
            "$ref": "#/components/schemas/SplineData"
          },
          "chord_stations": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Chord per station, normalized c/R.",
            "title": "Chord Stations"
          },
          "diameter": {
            "description": "Diameter in inches",
            "exclusiveMinimum": 0.0,
            "title": "Diameter",
            "type": "number"
          },
          "hub_r_over_R": {
            "anyOf": [
              {
                "exclusiveMaximum": 1.0,
                "exclusiveMinimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "The blade's own hub as a fraction of tip radius. Absent => the legacy APC diameter regression.",
            "title": "Hub R Over R"
          },
          "num_blades": {
            "default": 2,
            "maximum": 16.0,
            "minimum": 1.0,
            "title": "Num Blades",
            "type": "integer"
          },
          "pitch": {
            "description": "Pitch in inches",
            "exclusiveMinimum": 0.0,
            "title": "Pitch",
            "type": "number"
          },
          "station_r_over_R": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Station r/R column \u2014 strictly increasing within (0, 1]. Its presence switches chord/twist/thickness/sweep from spline evaluation to radius interpolation.",
            "title": "Station R Over R"
          },
          "sweep": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sweep"
          },
          "sweep_stations": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Swept c/4 leading-edge locus per station, x_le/R.",
            "title": "Sweep Stations"
          },
          "thickness_scale": {
            "default": 1.0,
            "maximum": 3.0,
            "minimum": 0.1,
            "title": "Thickness Scale",
            "type": "number"
          },
          "thickness_spline": {
            "$ref": "#/components/schemas/SplineData"
          },
          "thickness_stations": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Thickness per station, t/c.",
            "title": "Thickness Stations"
          },
          "twist_spline": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SplineData"
              },
              {
                "type": "null"
              }
            ]
          },
          "twist_stations": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Twist per station, degrees.",
            "title": "Twist Stations"
          }
        },
        "required": [
          "diameter",
          "pitch",
          "chord_spline",
          "thickness_spline"
        ],
        "title": "GenerateGeometryRequest",
        "type": "object"
      },
      "GeometryResponse": {
        "properties": {
          "chord": {
            "items": {
              "type": "number"
            },
            "title": "Chord",
            "type": "array"
          },
          "hub_radius": {
            "title": "Hub Radius",
            "type": "number"
          },
          "object": {
            "default": "geometry",
            "title": "Object",
            "type": "string"
          },
          "radius": {
            "items": {
              "type": "number"
            },
            "title": "Radius",
            "type": "array"
          },
          "section_airfoils": {
            "items": {},
            "title": "Section Airfoils",
            "type": "array"
          },
          "section_coords": {
            "anyOf": [
              {
                "items": {},
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Section Coords"
          },
          "thickness": {
            "items": {
              "type": "number"
            },
            "title": "Thickness",
            "type": "array"
          },
          "twist": {
            "items": {
              "type": "number"
            },
            "title": "Twist",
            "type": "array"
          },
          "x_le_over_R": {
            "anyOf": [
              {
                "items": {},
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "X Le Over R"
          }
        },
        "required": [
          "radius",
          "chord",
          "twist",
          "thickness",
          "hub_radius",
          "section_airfoils"
        ],
        "title": "GeometryResponse",
        "type": "object"
      },
      "GeometryStyleResource": {
        "description": "Identity/metadata-only view of a curated catalog geometry style.\n\nThe calibrated geometry arrays \u2014 ``thickness_spline``, ``thickness_scale``,\n``chord_spline_coefficients``, ``chord_spline_reference`` \u2014 are the curated\ntrade-secret geometry the anti-scrape moat protects, so they are NOT\nserialized here. The catalog stays browsable by IDENTITY (id/manufacturer/\nlabel/display_name/description/airfoil/source) so the editor can let a user\nPICK a style by name; the calibrated numbers are server-side only (read by\n``/v1/geometry/generate`` to produce the user's OWN-design geometry output,\nnever returned raw). ``from_attributes`` ignores the model's extra calibrated\ncolumns \u2014 they simply do not appear in the response.",
        "properties": {
          "airfoil": {
            "title": "Airfoil",
            "type": "string"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "display_name": {
            "title": "Display Name",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "manufacturer": {
            "title": "Manufacturer",
            "type": "string"
          },
          "object": {
            "default": "geometry_style",
            "title": "Object",
            "type": "string"
          },
          "source": {
            "title": "Source",
            "type": "string"
          }
        },
        "required": [
          "id",
          "manufacturer",
          "label",
          "display_name",
          "description",
          "airfoil",
          "source"
        ],
        "title": "GeometryStyleResource",
        "type": "object"
      },
      "GeometryStylesListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/GeometryStyleResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "GeometryStylesListResponse",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "PackLeafIn": {
        "additionalProperties": false,
        "properties": {
          "battery_component_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Battery Component Id",
            "type": "string"
          },
          "branch_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Branch Wire Resistance Mohm",
            "type": "number"
          },
          "id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Id",
            "type": "string"
          },
          "initial_soc_pct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Initial Soc Pct"
          },
          "kind": {
            "const": "leaf",
            "default": "leaf",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "id",
          "battery_component_id"
        ],
        "title": "PackLeafIn",
        "type": "object"
      },
      "PackParallelIn": {
        "additionalProperties": false,
        "properties": {
          "branches": {
            "items": {
              "discriminator": {
                "mapping": {
                  "leaf": "#/components/schemas/PackLeafIn",
                  "parallel": "#/components/schemas/PackParallelIn",
                  "series": "#/components/schemas/PackSeriesIn"
                },
                "propertyName": "kind"
              },
              "oneOf": [
                {
                  "$ref": "#/components/schemas/PackLeafIn"
                },
                {
                  "$ref": "#/components/schemas/PackSeriesIn"
                },
                {
                  "$ref": "#/components/schemas/PackParallelIn"
                }
              ]
            },
            "minItems": 2,
            "title": "Branches",
            "type": "array"
          },
          "kind": {
            "const": "parallel",
            "default": "parallel",
            "title": "Kind",
            "type": "string"
          },
          "voltage_match_tolerance_v": {
            "maximum": 20.0,
            "minimum": 0.0,
            "title": "Voltage Match Tolerance V",
            "type": "number"
          }
        },
        "required": [
          "branches",
          "voltage_match_tolerance_v"
        ],
        "title": "PackParallelIn",
        "type": "object"
      },
      "PackSeriesIn": {
        "additionalProperties": false,
        "properties": {
          "children": {
            "items": {
              "discriminator": {
                "mapping": {
                  "leaf": "#/components/schemas/PackLeafIn",
                  "parallel": "#/components/schemas/PackParallelIn",
                  "series": "#/components/schemas/PackSeriesIn"
                },
                "propertyName": "kind"
              },
              "oneOf": [
                {
                  "$ref": "#/components/schemas/PackLeafIn"
                },
                {
                  "$ref": "#/components/schemas/PackSeriesIn"
                },
                {
                  "$ref": "#/components/schemas/PackParallelIn"
                }
              ]
            },
            "minItems": 1,
            "title": "Children",
            "type": "array"
          },
          "kind": {
            "const": "series",
            "default": "series",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "children"
        ],
        "title": "PackSeriesIn",
        "type": "object"
      },
      "PackTopologyIn": {
        "additionalProperties": false,
        "properties": {
          "bus_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Bus Wire Resistance Mohm",
            "type": "number"
          },
          "cross_charge_warning_acknowledged": {
            "default": false,
            "title": "Cross Charge Warning Acknowledged",
            "type": "boolean"
          },
          "root": {
            "discriminator": {
              "mapping": {
                "leaf": "#/components/schemas/PackLeafIn",
                "parallel": "#/components/schemas/PackParallelIn",
                "series": "#/components/schemas/PackSeriesIn"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/components/schemas/PackLeafIn"
              },
              {
                "$ref": "#/components/schemas/PackSeriesIn"
              },
              {
                "$ref": "#/components/schemas/PackParallelIn"
              }
            ],
            "title": "Root"
          },
          "schema": {
            "const": 1,
            "default": 1,
            "title": "Schema",
            "type": "integer"
          }
        },
        "required": [
          "root"
        ],
        "title": "PackTopologyIn",
        "type": "object"
      },
      "ProjectCreateBody": {
        "properties": {
          "aircraft_type_tag": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Aircraft Type Tag"
          },
          "name": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          }
        },
        "required": [
          "name"
        ],
        "title": "ProjectCreateBody",
        "type": "object"
      },
      "ProjectPatch": {
        "properties": {
          "aircraft_type_tag": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Aircraft Type Tag"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          }
        },
        "title": "ProjectPatch",
        "type": "object"
      },
      "ProjectResource": {
        "properties": {
          "aircraft_type_tag": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Aircraft Type Tag"
          },
          "completed_count": {
            "default": 0,
            "title": "Completed Count",
            "type": "integer"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "failed_count": {
            "default": 0,
            "title": "Failed Count",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_activity_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Activity At"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "object": {
            "default": "project",
            "title": "Object",
            "type": "string"
          },
          "run_count": {
            "default": 0,
            "title": "Run Count",
            "type": "integer"
          },
          "running_count": {
            "default": 0,
            "title": "Running Count",
            "type": "integer"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "aircraft_type_tag",
          "notes",
          "created_at",
          "updated_at"
        ],
        "title": "ProjectResource",
        "type": "object"
      },
      "RotorGroupIn": {
        "additionalProperties": false,
        "description": "Single-point rotor GROUP \u2014 ``count`` identical rotors.\n\nInherits label / count (bounded 1..40) / motor+propeller ids / the\nmotor-cooling trio + cooling validator from ``RotorGroupBase``, and the\nper-rotor operating point (throttle, pinned motor temperatures, the oblique\nflight-condition fields, custom component overrides) from\n``RotorOperatingFields``.\n\nThe operating-point fields used to be declared HERE. They moved to\n``app/v1/_rotor_base.py`` so the flat ``RotorIn`` shape shares one\ndeclaration with this one \u2014 the same consolidation ESC-8 did for the ESC\nblock. Field definitions, bounds and descriptions are unchanged; only the\ndeclaration site moved.\n\nDEPRECATED in favour of ``rotors[]``. Still accepted and still behaves\nidentically, but cannot describe a coaxial stack \u2014 see ``_rotor_base``.",
        "properties": {
          "count": {
            "default": 1,
            "maximum": 40.0,
            "minimum": 1.0,
            "title": "Count",
            "type": "integer"
          },
          "custom_motor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_propeller": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "motor_t_mag": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed magnet temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T Mag"
          },
          "motor_t_w": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed winding temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T W"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "throttle_pct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Throttle Pct",
            "type": "number"
          },
          "tilt_deg": {
            "default": 0.0,
            "description": "Ground-mode rotor-axis tilt measured from the horizontal-forward (flight) direction (0\u00b0 = forward/cruise \u2014 the axis lies along the flight path and all airspeed becomes axial inflow; 90\u00b0 = lift/hover \u2014 the axis points up and forward airspeed becomes pure edgewise inflow). Decomposed host-side to V_axial = V_h\u00b7cos\u03b8 + V_v\u00b7sin\u03b8, V_edge = |V_v\u00b7cos\u03b8 \u2212 V_h\u00b7sin\u03b8|.",
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Tilt Deg",
            "type": "number"
          },
          "v_axial_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": -30.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode signed axial inflow (m/s); only with inflow_mode='components'.",
            "title": "V Axial M S"
          },
          "v_edge_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode edgewise inflow magnitude (m/s, \u22650); only with inflow_mode='components'.",
            "title": "V Edge M S"
          }
        },
        "required": [
          "throttle_pct",
          "label",
          "propeller_component_id"
        ],
        "title": "RotorGroupIn",
        "type": "object"
      },
      "RotorGroupResource": {
        "additionalProperties": false,
        "description": "Reused by SimulationResource and SweepResource.",
        "properties": {
          "coax_position_m": {
            "default": 0.0,
            "title": "Coax Position M",
            "type": "number"
          },
          "coax_stack_id": {
            "default": 0,
            "title": "Coax Stack Id",
            "type": "integer"
          },
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "esc_motor_wire_resistance_mohm": {
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "rotation_sense": {
            "default": 1,
            "title": "Rotation Sense",
            "type": "integer"
          },
          "throttle_pct": {
            "title": "Throttle Pct",
            "type": "number"
          }
        },
        "required": [
          "label",
          "count",
          "motor_component_id",
          "propeller_component_id",
          "throttle_pct",
          "esc_resistance_mohm",
          "esc_motor_wire_resistance_mohm",
          "esc_type"
        ],
        "title": "RotorGroupResource",
        "type": "object"
      },
      "RotorIn": {
        "additionalProperties": false,
        "description": "ONE rotor for a steady or sweep run.\n\nEverything a ``rotor_groups[]`` entry carries except ``count``, plus the\ncoaxial trio.",
        "properties": {
          "coax_position_m": {
            "default": 0.0,
            "description": "Position along the coaxial stack axis in metres, increasing downstream (in the direction the slipstream travels). The spacing between two rotors is the difference of their positions. Ignored when coax_stack_id is 0.",
            "maximum": 2.0,
            "minimum": -2.0,
            "title": "Coax Position M",
            "type": "number"
          },
          "coax_stack_id": {
            "default": 0,
            "description": "Coaxial stack this rotor belongs to. 0 (default) means the rotor is not stacked and is simulated in isolation. Rotors sharing a non-zero value form one contra-rotating or co-rotating stack.",
            "maximum": 16.0,
            "minimum": 0.0,
            "title": "Coax Stack Id",
            "type": "integer"
          },
          "custom_motor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_propeller": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "motor_t_mag": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed magnet temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T Mag"
          },
          "motor_t_w": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed winding temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T W"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "rotation_sense": {
            "default": 1,
            "description": "Direction of rotation about the downstream axis: 1 or -1. Opposite values in one stack give a contra-rotating pair, which recovers swirl energy and is the usual choice. Only read by coaxial pairing \u2014 a single rotor's value does not affect its own performance.",
            "enum": [
              1,
              -1
            ],
            "title": "Rotation Sense",
            "type": "integer"
          },
          "throttle_pct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Throttle Pct",
            "type": "number"
          },
          "tilt_deg": {
            "default": 0.0,
            "description": "Ground-mode rotor-axis tilt measured from the horizontal-forward (flight) direction (0\u00b0 = forward/cruise \u2014 the axis lies along the flight path and all airspeed becomes axial inflow; 90\u00b0 = lift/hover \u2014 the axis points up and forward airspeed becomes pure edgewise inflow). Decomposed host-side to V_axial = V_h\u00b7cos\u03b8 + V_v\u00b7sin\u03b8, V_edge = |V_v\u00b7cos\u03b8 \u2212 V_h\u00b7sin\u03b8|.",
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Tilt Deg",
            "type": "number"
          },
          "v_axial_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": -30.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode signed axial inflow (m/s); only with inflow_mode='components'.",
            "title": "V Axial M S"
          },
          "v_edge_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode edgewise inflow magnitude (m/s, \u22650); only with inflow_mode='components'.",
            "title": "V Edge M S"
          }
        },
        "required": [
          "throttle_pct",
          "label",
          "propeller_component_id"
        ],
        "title": "RotorIn",
        "type": "object"
      },
      "RunSelectedBody": {
        "additionalProperties": false,
        "properties": {
          "simulation_ids": {
            "items": {
              "type": "string"
            },
            "maxItems": 1000,
            "minItems": 1,
            "title": "Simulation Ids",
            "type": "array"
          }
        },
        "required": [
          "simulation_ids"
        ],
        "title": "RunSelectedBody",
        "type": "object"
      },
      "ScheduleIn": {
        "additionalProperties": false,
        "description": "The control schedule \u2014 a ``segments`` list OR a per-rotor ``csv_text``.\n\n``mode`` is the discriminator. ``segments`` is required for ``mode=segments``;\n``csv_text`` (+ optional ``interpolation``) for ``mode=csv``. The cross-field\nrequirement is enforced server-side by the schedule compiler (``validate_schedule``) so a malformed schedule 4xx's BEFORE any reservation.",
        "properties": {
          "csv_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Csv Text"
          },
          "interpolation": {
            "anyOf": [
              {
                "enum": [
                  "linear",
                  "hold"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Interpolation"
          },
          "mode": {
            "enum": [
              "segments",
              "csv"
            ],
            "title": "Mode",
            "type": "string"
          },
          "segments": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SegmentIn"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Segments"
          }
        },
        "required": [
          "mode"
        ],
        "title": "ScheduleIn",
        "type": "object"
      },
      "SegmentGroupCommandIn": {
        "additionalProperties": false,
        "description": "A single rotor-group's throttle (+ tilt) command inside a segment.",
        "properties": {
          "throttle_ramp": {
            "anyOf": [
              {
                "enum": [
                  "step",
                  "linear"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ramp shape for THIS group's throttle across the segment. Omit to inherit the segment-level `throttle_ramp` (itself defaulting to `step`). Each rotor group's ramp is honoured independently.",
            "title": "Throttle Ramp"
          },
          "throttle_target": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Throttle Target",
            "type": "number"
          },
          "tilt_ramp": {
            "anyOf": [
              {
                "enum": [
                  "step",
                  "linear"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ramp shape for THIS group's tilt. Omit for `step`.",
            "title": "Tilt Ramp"
          },
          "tilt_target": {
            "default": 0.0,
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Tilt Target",
            "type": "number"
          }
        },
        "required": [
          "throttle_target"
        ],
        "title": "SegmentGroupCommandIn",
        "type": "object"
      },
      "SegmentIn": {
        "additionalProperties": false,
        "description": "One schedule segment: a per-group throttle command + an airspeed target\n(+ vertical-speed target) held for ``duration_s`` (or until depletion\nwhen ``until_depleted``).",
        "properties": {
          "airspeed_ramp": {
            "default": "step",
            "enum": [
              "step",
              "linear"
            ],
            "title": "Airspeed Ramp",
            "type": "string"
          },
          "airspeed_target": {
            "default": 0.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Airspeed Target",
            "type": "number"
          },
          "duration_s": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration S"
          },
          "per_group": {
            "additionalProperties": {
              "$ref": "#/components/schemas/SegmentGroupCommandIn"
            },
            "title": "Per Group",
            "type": "object"
          },
          "throttle_ramp": {
            "default": "step",
            "enum": [
              "step",
              "linear"
            ],
            "title": "Throttle Ramp",
            "type": "string"
          },
          "until_depleted": {
            "default": false,
            "title": "Until Depleted",
            "type": "boolean"
          },
          "vertical_speed_ramp": {
            "default": "step",
            "enum": [
              "step",
              "linear"
            ],
            "title": "Vertical Speed Ramp",
            "type": "string"
          },
          "vertical_speed_target": {
            "default": 0.0,
            "maximum": 30.0,
            "minimum": -30.0,
            "title": "Vertical Speed Target",
            "type": "number"
          }
        },
        "required": [
          "per_group"
        ],
        "title": "SegmentIn",
        "type": "object"
      },
      "ShareResource": {
        "properties": {
          "object": {
            "default": "simulation_share",
            "title": "Object",
            "type": "string"
          },
          "share_token": {
            "title": "Share Token",
            "type": "string"
          },
          "share_url": {
            "title": "Share Url",
            "type": "string"
          }
        },
        "required": [
          "share_token",
          "share_url"
        ],
        "title": "ShareResource",
        "type": "object"
      },
      "SimulationCancelBody": {
        "additionalProperties": false,
        "properties": {},
        "title": "SimulationCancelBody",
        "type": "object"
      },
      "SimulationCreateBody": {
        "additionalProperties": false,
        "properties": {
          "airspeed_m_s": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Airspeed M S",
            "type": "number"
          },
          "ambient_temp_c": {
            "default": 25.0,
            "maximum": 85.0,
            "minimum": -60.0,
            "title": "Ambient Temp C",
            "type": "number"
          },
          "battery_charge_pct": {
            "default": 100.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "battery_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Component Id"
          },
          "battery_esc_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Battery Esc Wire Resistance Mohm",
            "type": "number"
          },
          "battery_topology": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackTopologyIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "cooling_source": {
            "anyOf": [
              {
                "enum": [
                  "static",
                  "airspeed",
                  "prop_slipstream",
                  "forced_air"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cooling Source"
          },
          "custom_battery": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "density_kg_m3": {
            "exclusiveMinimum": 0.0,
            "maximum": 2.0,
            "title": "Density Kg M3",
            "type": "number"
          },
          "flight_duration": {
            "anyOf": [
              {
                "maximum": 86400.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": 60.0,
            "description": "Flight time (seconds) for the time-bounded steady-state thermal solve. 0 \u2264 x \u2264 86400 (24 h). null disables time-bounding (infinite-hover baseline)..",
            "title": "Flight Duration"
          },
          "flight_regime": {
            "default": "static_bench",
            "deprecated": true,
            "description": "DEPRECATED \u2014 use cooling_source instead. Still accepted: when cooling_source is omitted, this value is mapped to the equivalent battery cooling source (prop_wash_mild and prop_wash_strong \u2192 prop_slipstream, forced_air \u2192 forced_air, static_bench \u2192 static). cooling_source wins whenever both are supplied.",
            "enum": [
              "static_bench",
              "prop_wash_mild",
              "prop_wash_strong",
              "forced_air"
            ],
            "title": "Flight Regime",
            "type": "string"
          },
          "forced_air_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Fixed cooling velocity (m/s) for cooling_source='forced_air' (fan/duct). Ignored for the other cooling sources; defaults to 10 m/s when omitted..",
            "title": "Forced Air Velocity M S"
          },
          "inflow_mode": {
            "default": "ground",
            "enum": [
              "ground",
              "components"
            ],
            "title": "Inflow Mode",
            "type": "string"
          },
          "launch_intent": {
            "default": "run",
            "description": "Launch intent. 'run' dispatches now; 'queue' reserves a credit slot but defers dispatch; 'draft' persists with no credit reservation and no dispatch..",
            "enum": [
              "run",
              "queue",
              "draft"
            ],
            "title": "Launch Intent",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "rotor_groups": {
            "items": {
              "$ref": "#/components/schemas/RotorGroupIn"
            },
            "maxItems": 10,
            "title": "Rotor Groups",
            "type": "array"
          },
          "rotors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/RotorIn"
                },
                "maxItems": 16,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "One entry per rotor. Preferred over rotor_groups, and required for coaxial stacks: set coax_stack_id to the same non-zero value on the rotors that share an axis, give each a distinct coax_position_m (metres, increasing downstream), and set opposite rotation_sense values for a contra-rotating stack. Supply either rotors or rotor_groups, not both.",
            "title": "Rotors"
          },
          "vertical_speed_m_s": {
            "default": 0.0,
            "maximum": 30.0,
            "minimum": -30.0,
            "title": "Vertical Speed M S",
            "type": "number"
          }
        },
        "required": [
          "project_id",
          "density_kg_m3",
          "airspeed_m_s"
        ],
        "title": "SimulationCreateBody",
        "type": "object"
      },
      "SimulationInputs": {
        "additionalProperties": false,
        "properties": {
          "airspeed_m_s": {
            "title": "Airspeed M S",
            "type": "number"
          },
          "battery_charge_pct": {
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "density_kg_m3": {
            "title": "Density Kg M3",
            "type": "number"
          },
          "solver": {
            "title": "Solver",
            "type": "string"
          }
        },
        "required": [
          "density_kg_m3",
          "airspeed_m_s",
          "battery_charge_pct",
          "solver"
        ],
        "title": "SimulationInputs",
        "type": "object"
      },
      "SimulationListResponse": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SimulationResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "SimulationListResponse",
        "type": "object"
      },
      "SimulationPatch": {
        "additionalProperties": false,
        "properties": {
          "is_starred": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Starred"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "plot_config_json": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plot Config Json"
          }
        },
        "title": "SimulationPatch",
        "type": "object"
      },
      "SimulationResource": {
        "additionalProperties": false,
        "properties": {
          "analysis_type": {
            "title": "Analysis Type",
            "type": "string"
          },
          "battery_component_id": {
            "title": "Battery Component Id",
            "type": "string"
          },
          "battery_topology": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Topology"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "credits_cost": {
            "title": "Credits Cost",
            "type": "integer"
          },
          "dispatched_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dispatched At"
          },
          "display_labels": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Labels"
          },
          "error": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "input_snapshot": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Snapshot"
          },
          "inputs": {
            "$ref": "#/components/schemas/SimulationInputs"
          },
          "is_starred": {
            "title": "Is Starred",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "simulation",
            "title": "Object",
            "type": "string"
          },
          "plot_config_json": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plot Config Json"
          },
          "progress": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Progress"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "project_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Project Name"
          },
          "result": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result"
          },
          "rotor_groups": {
            "items": {
              "$ref": "#/components/schemas/RotorGroupResource"
            },
            "title": "Rotor Groups",
            "type": "array"
          },
          "snapshot_version": {
            "default": 1,
            "title": "Snapshot Version",
            "type": "integer"
          },
          "solver_engine": {
            "default": "prom-rs/0.3.1",
            "title": "Solver Engine",
            "type": "string"
          },
          "status": {
            "enum": [
              "draft",
              "queued",
              "running",
              "completed",
              "failed",
              "canceled"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "progress",
          "created_at",
          "completed_at",
          "project_id",
          "inputs",
          "result",
          "error",
          "name",
          "is_starred",
          "analysis_type",
          "credits_cost",
          "battery_component_id",
          "rotor_groups",
          "plot_config_json"
        ],
        "title": "SimulationResource",
        "type": "object"
      },
      "SplineData": {
        "properties": {
          "control_points": {
            "items": {
              "type": "number"
            },
            "title": "Control Points",
            "type": "array"
          },
          "degree": {
            "default": 3,
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Degree",
            "type": "integer"
          },
          "knots": {
            "items": {
              "type": "number"
            },
            "title": "Knots",
            "type": "array"
          }
        },
        "required": [
          "knots",
          "control_points"
        ],
        "title": "SplineData",
        "type": "object"
      },
      "StarredComponentCreateBody": {
        "description": "Accepts either prefixed (``proj_<ksuid>`` / ``comp_<ksuid>``) or raw\nUUID strings \u2014 resolution happens in the handler so the same body shape\nworks during the reference-app transition.",
        "properties": {
          "component_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Component Id",
            "type": "string"
          },
          "component_type": {
            "pattern": "^(motor|battery|propeller)$",
            "title": "Component Type",
            "type": "string"
          },
          "project_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "project_id",
          "component_id",
          "component_type"
        ],
        "title": "StarredComponentCreateBody",
        "type": "object"
      },
      "StarredComponentListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/StarredComponentResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "StarredComponentListResponse",
        "type": "object"
      },
      "StarredComponentResource": {
        "properties": {
          "component_id": {
            "title": "Component Id",
            "type": "string"
          },
          "component_type": {
            "title": "Component Type",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "default": "starred_component",
            "title": "Object",
            "type": "string"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "project_id",
          "component_id",
          "component_type",
          "created_at"
        ],
        "title": "StarredComponentResource",
        "type": "object"
      },
      "SubmissionCreateBody": {
        "properties": {
          "component_type": {
            "pattern": "^(motor|battery)$",
            "title": "Component Type",
            "type": "string"
          },
          "data_json": {
            "additionalProperties": true,
            "title": "Data Json",
            "type": "object"
          },
          "manufacturer": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Manufacturer",
            "type": "string"
          },
          "name": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "source_url": {
            "maxLength": 500,
            "title": "Source Url",
            "type": "string"
          }
        },
        "required": [
          "component_type",
          "name",
          "manufacturer",
          "data_json",
          "source_url"
        ],
        "title": "SubmissionCreateBody",
        "type": "object"
      },
      "SubmissionPatch": {
        "description": "Withdraw/edit-before-review fields. component_type excluded \u2014\nstructural classifier; changing it would invalidate downstream\nreview pipelines.",
        "properties": {
          "data_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Data Json"
          },
          "manufacturer": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Manufacturer"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "source_url": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url"
          }
        },
        "title": "SubmissionPatch",
        "type": "object"
      },
      "SubmissionResource": {
        "properties": {
          "component_type": {
            "title": "Component Type",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "credit_reward": {
            "title": "Credit Reward",
            "type": "integer"
          },
          "data_json": {
            "additionalProperties": true,
            "title": "Data Json",
            "type": "object"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "manufacturer": {
            "title": "Manufacturer",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "object": {
            "default": "submission",
            "title": "Object",
            "type": "string"
          },
          "reviewed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewed At"
          },
          "reviewer_notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reviewer Notes"
          },
          "source_url": {
            "title": "Source Url",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "component_type",
          "name",
          "manufacturer",
          "data_json",
          "source_url",
          "notes",
          "status",
          "reviewer_notes",
          "credit_reward",
          "reviewed_at",
          "created_at"
        ],
        "title": "SubmissionResource",
        "type": "object"
      },
      "SweepCancelBody": {
        "additionalProperties": false,
        "properties": {
          "save_partial": {
            "default": false,
            "title": "Save Partial",
            "type": "boolean"
          }
        },
        "title": "SweepCancelBody",
        "type": "object"
      },
      "SweepConfigIn": {
        "additionalProperties": false,
        "properties": {
          "airspeed": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "battery_charge": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "component_axes": {
            "items": {
              "$ref": "#/components/schemas/ComponentSweepAxisIn"
            },
            "title": "Component Axes",
            "type": "array"
          },
          "density": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_pwm_frequency_khz": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_timing_values": {
            "anyOf": [
              {
                "items": {
                  "enum": [
                    "low",
                    "medium",
                    "high",
                    "auto"
                  ],
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Esc Timing Values"
          },
          "rotor_sweep_mask": {
            "description": "One bool per rotor group, same order as `rotor_groups`: true = this group follows the swept throttle axis. INERT when `sweep.throttle` is absent \u2014 with no throttle axis there is nothing to follow, and every group keeps its own persisted throttle. Length must equal `rotor_groups` (422 otherwise).",
            "items": {
              "type": "boolean"
            },
            "title": "Rotor Sweep Mask",
            "type": "array"
          },
          "throttle": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "tilt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "tilt_sweep_mask": {
            "description": "One bool per rotor group, same order as `rotor_groups`: true = this group sweeps the shared `tilt` angle range as its own grid dimension. Omit or leave empty when no tilt axis is swept. When non-empty its length must equal `rotor_groups` (422 otherwise).",
            "items": {
              "type": "boolean"
            },
            "title": "Tilt Sweep Mask",
            "type": "array"
          },
          "vertical_speed": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SweepParamRangeIn"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "rotor_sweep_mask"
        ],
        "title": "SweepConfigIn",
        "type": "object"
      },
      "SweepCreateBody": {
        "additionalProperties": false,
        "properties": {
          "airspeed_m_s": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Airspeed M S",
            "type": "number"
          },
          "ambient_temp_c": {
            "default": 25.0,
            "maximum": 85.0,
            "minimum": -60.0,
            "title": "Ambient Temp C",
            "type": "number"
          },
          "battery_charge_pct": {
            "default": 100.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "battery_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Battery Component Id"
          },
          "battery_esc_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Battery Esc Wire Resistance Mohm",
            "type": "number"
          },
          "cooling_source": {
            "default": "static",
            "description": "Cooling source for the battery convection coefficient \u2014 static (natural only) | airspeed (free-stream v_inf) | prop_slipstream (prop induced velocity) | forced_air (fixed velocity). Supersedes the fixed cooling-regime h-table..",
            "enum": [
              "static",
              "airspeed",
              "prop_slipstream",
              "forced_air"
            ],
            "title": "Cooling Source",
            "type": "string"
          },
          "custom_battery": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "density_kg_m3": {
            "exclusiveMinimum": 0.0,
            "maximum": 2.0,
            "title": "Density Kg M3",
            "type": "number"
          },
          "flight_duration": {
            "anyOf": [
              {
                "maximum": 86400.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": 60.0,
            "description": "Flight time (seconds) for the time-bounded steady-state thermal solve. 0 \u2264 x \u2264 86400 (24 h). null disables time-bounding (infinite-hover baseline)..",
            "title": "Flight Duration"
          },
          "forced_air_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Fixed cooling velocity (m/s) for cooling_source='forced_air' (fan/duct). Ignored for the other cooling sources; defaults to 10 m/s when omitted..",
            "title": "Forced Air Velocity M S"
          },
          "inflow_mode": {
            "default": "ground",
            "enum": [
              "ground",
              "components"
            ],
            "title": "Inflow Mode",
            "type": "string"
          },
          "launch_intent": {
            "default": "run",
            "description": "Launch intent. 'run' dispatches now; 'queue' reserves a credit slot but defers dispatch; 'draft' persists with no credit reservation and no dispatch..",
            "enum": [
              "run",
              "queue",
              "draft"
            ],
            "title": "Launch Intent",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "rotor_groups": {
            "items": {
              "$ref": "#/components/schemas/SweepRotorGroupIn"
            },
            "maxItems": 16,
            "title": "Rotor Groups",
            "type": "array"
          },
          "rotors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SweepRotorIn"
                },
                "maxItems": 16,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "One entry per rotor. Preferred over rotor_groups, and required for coaxial stacks. sweep.rotor_sweep_mask and sweep.tilt_sweep_mask carry one bool per entry of this list, and component_axes[].slots index into it. Supply either rotors or rotor_groups, not both.",
            "title": "Rotors"
          },
          "sweep": {
            "$ref": "#/components/schemas/SweepConfigIn"
          },
          "vertical_speed_m_s": {
            "default": 0.0,
            "maximum": 30.0,
            "minimum": -30.0,
            "title": "Vertical Speed M S",
            "type": "number"
          }
        },
        "required": [
          "project_id",
          "density_kg_m3",
          "airspeed_m_s",
          "sweep"
        ],
        "title": "SweepCreateBody",
        "type": "object"
      },
      "SweepInputs": {
        "additionalProperties": false,
        "properties": {
          "airspeed_m_s": {
            "title": "Airspeed M S",
            "type": "number"
          },
          "battery_charge_pct": {
            "title": "Battery Charge Pct",
            "type": "number"
          },
          "density_kg_m3": {
            "title": "Density Kg M3",
            "type": "number"
          },
          "solver": {
            "title": "Solver",
            "type": "string"
          }
        },
        "required": [
          "density_kg_m3",
          "airspeed_m_s",
          "battery_charge_pct",
          "solver"
        ],
        "title": "SweepInputs",
        "type": "object"
      },
      "SweepListResponse": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SweepResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "SweepListResponse",
        "type": "object"
      },
      "SweepParamRangeIn": {
        "additionalProperties": false,
        "properties": {
          "mode": {
            "enum": [
              "range",
              "custom"
            ],
            "title": "Mode",
            "type": "string"
          },
          "start": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Start"
          },
          "steps": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Steps"
          },
          "stop": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stop"
          },
          "values": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Values"
          }
        },
        "required": [
          "mode"
        ],
        "title": "SweepParamRangeIn",
        "type": "object"
      },
      "SweepPatch": {
        "additionalProperties": false,
        "properties": {
          "is_starred": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Starred"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "plot_config_json": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plot Config Json"
          }
        },
        "title": "SweepPatch",
        "type": "object"
      },
      "SweepPointComponentSelection": {
        "additionalProperties": true,
        "description": "The component this grid point resolved to on one component axis.",
        "properties": {
          "axis": {
            "description": "Which component was swapped: \"motor\", \"propeller\" or \"battery\".",
            "title": "Axis",
            "type": "string"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Public component id of the selected component.",
            "title": "Id"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Display name of the selected component.",
            "title": "Name"
          },
          "slot": {
            "description": "Rotor-group index the swap applied to (0 for a battery axis).",
            "title": "Slot",
            "type": "integer"
          }
        },
        "required": [
          "axis",
          "slot"
        ],
        "title": "SweepPointComponentSelection",
        "type": "object"
      },
      "SweepPointInputs": {
        "additionalProperties": true,
        "description": "ESC-13 item 4 \u2014 the operating condition this grid point was solved at.\n\nPreviously typed ``dict[str, Any]``, which is the wire equivalent of saying\nnothing: an SDK user got an untyped bag and had to learn the key set by\nrunning a sweep and reading one. ESC-13 already made the RUNTIME blob\nself-describing (it is built from the point rather than from a hardcoded\nfive-key literal, so a new axis appears the day it lands); this makes the\nCONTRACT say so too.\n\n``extra=\"allow\"`` is load-bearing, not laziness. Two families of key are\ngenerated per-sweep and cannot be enumerated in a static model:\n\n  * ``tilt_<group_index>`` \u2014 group-targeted tilt is one grid dimension per\n    MASKED rotor group, so the key set depends on the mask.\n  * ``component_<axis>_<slots>`` \u2014 a component axis contributes its selected\n    index under a name encoding the slots it spans (``component_motor_0``,\n    or ``component_motor_0-2`` when synced).\n\nDeclaring those away would be worse than leaving the model untyped, because\na strict model would DROP them at serialization \u2014 the same failure mode as\nthe 2026-06-02 aggregate-drop that ``rotors`` is deliberately non-coercing to\navoid. Every declared field is optional and permissively typed for the same\nreason: this model documents the shape, it does not police it.",
        "properties": {
          "airspeed": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Forward airspeed at this point, m/s.",
            "title": "Airspeed"
          },
          "battery_charge_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Pack state of charge at this point, %.",
            "title": "Battery Charge Pct"
          },
          "component": {
            "description": "Components selected at this point, one entry per swept slot. Empty when no component axis is active.",
            "items": {
              "$ref": "#/components/schemas/SweepPointComponentSelection"
            },
            "title": "Component",
            "type": "array"
          },
          "density": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Air density at this point, kg/m^3.",
            "title": "Density"
          },
          "esc_pwm_frequency_khz": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "ESC switching frequency at this point, kHz. Present only when an ESC PWM axis is swept.",
            "title": "Esc Pwm Frequency Khz"
          },
          "esc_timing": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Six-step commutation timing preset at this point (\"low\", \"medium\", \"high\", \"auto\"). Present only when an ESC timing axis is swept \u2014 absent means each rotor group used its own persisted setting.",
            "title": "Esc Timing"
          },
          "grid_index": {
            "anyOf": [
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Multi-dimensional coordinate of this point in the sweep grid, one entry per axis in the order the axes were declared. The flat `index` on the point itself is the pagination counter, not this.",
            "title": "Grid Index"
          },
          "throttle": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Commanded throttle % at this point. Always present. NOTE: this is the value of the throttle AXIS when one is swept; with no throttle axis it echoes rotor group 0's persisted throttle and applies to no other group (DM-6) \u2014 read the per-rotor results for what each group actually ran at.",
            "title": "Throttle"
          },
          "vertical_speed": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Signed vertical speed at this point, m/s (positive = climb).",
            "title": "Vertical Speed"
          }
        },
        "title": "SweepPointInputs",
        "type": "object"
      },
      "SweepPointListResponse": {
        "additionalProperties": false,
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SweepPointResource"
            },
            "title": "Data",
            "type": "array"
          },
          "display_labels": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Labels"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "SweepPointListResponse",
        "type": "object"
      },
      "SweepPointPatch": {
        "additionalProperties": false,
        "properties": {
          "is_starred": {
            "title": "Is Starred",
            "type": "boolean"
          }
        },
        "required": [
          "is_starred"
        ],
        "title": "SweepPointPatch",
        "type": "object"
      },
      "SweepPointResource": {
        "additionalProperties": false,
        "description": "A single sweep grid point.\n\n``rotors`` is the full per-point solver result dict \u2014 keyed per-rotor\n(\"1\", \"2\"...) plus the \"All\"/\"Battery\" aggregates \u2014 mirroring\n``SimulationResource.result``. Each per-rotor entry follows the canonical\nsnake_case ``SimulationResultV1`` shape (wired at read time in a later\nwave); the schema below references that shape so an SDK/consumer sees the\ncanonical per-rotor keys.\n\nNON-coercing rationale: the runtime type stays a raw\n``dict[str, dict[str, Any]]`` \u2014 NOT a coercing per-rotor ``SimulationResultV1``\nmodel. Coercing every rotor value through that model would re-introduce the\n2026-06-02 aggregate-drop regression on sweep points, silently dropping the\n\"All\"/\"Battery\" aggregate-only fields (Max T_core, Cell voltages...). See\nthe matching note on ``SimulationResource.result`` (serializers_simulations.py).\nThe per-rotor snake shape is documented via the schema reference only; the\nvalues are never re-validated through a model.",
        "properties": {
          "failed": {
            "title": "Failed",
            "type": "boolean"
          },
          "index": {
            "title": "Index",
            "type": "integer"
          },
          "inputs": {
            "$ref": "#/components/schemas/SweepPointInputs"
          },
          "is_starred": {
            "title": "Is Starred",
            "type": "boolean"
          },
          "object": {
            "const": "sweep_point",
            "title": "Object",
            "type": "string"
          },
          "rotors": {
            "anyOf": [
              {
                "additionalProperties": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-point rotor results, keyed per-rotor (\"1\", \"2\", ...) plus the \"All\"/\"Battery\" aggregates. Each per-rotor entry follows the canonical snake_case SimulationResultV1 shape; NON-coercing at runtime so aggregate-only fields are never dropped.",
            "per_rotor_snake_keys": [
              "battery_voltage_v",
              "beta_eff_deg",
              "bus_current_a",
              "compressibility_warning",
              "cp",
              "ct",
              "current_a",
              "dynamic_torque",
              "efficiency_pct",
              "electrical_power_w",
              "esc_efficiency",
              "esc_power_loss_w",
              "esc_voltage_drop_v",
              "exit_velocity",
              "frac_above_mdd",
              "frac_converged",
              "g_per_w",
              "gamma_cmd_deg",
              "irreversible_magnet_warning",
              "j",
              "mach",
              "max_rpm_shift",
              "mechanical_power_w",
              "motor",
              "motor_voltage_after_esc_v",
              "motor_voltage_v",
              "p_motor_w",
              "pe",
              "power",
              "propeller",
              "r_th_k_per_w",
              "reyn",
              "rpm",
              "shaft_power_w",
              "static_torque",
              "t_ambient_degc",
              "t_mag_degc",
              "t_w_degc",
              "thermal_converged",
              "thermal_iterations",
              "thr_per_pwr",
              "throttle_pct",
              "thrust",
              "thrust_n",
              "torque_per_amp_factor",
              "total_torque",
              "ve",
              "weight_g"
            ],
            "per_rotor_snake_shape": "SimulationResultV1",
            "title": "Rotors"
          }
        },
        "required": [
          "object",
          "index",
          "inputs",
          "rotors",
          "failed",
          "is_starred"
        ],
        "title": "SweepPointResource",
        "type": "object"
      },
      "SweepResource": {
        "additionalProperties": false,
        "properties": {
          "analysis_type": {
            "title": "Analysis Type",
            "type": "string"
          },
          "battery_component_id": {
            "title": "Battery Component Id",
            "type": "string"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "completed_points": {
            "title": "Completed Points",
            "type": "integer"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          },
          "credits_cost": {
            "title": "Credits Cost",
            "type": "integer"
          },
          "dispatched_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dispatched At"
          },
          "error": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "input_snapshot": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Snapshot"
          },
          "inputs": {
            "$ref": "#/components/schemas/SweepInputs"
          },
          "is_starred": {
            "title": "Is Starred",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "sweep",
            "title": "Object",
            "type": "string"
          },
          "plot_config_json": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plot Config Json"
          },
          "progress": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Progress"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "rotor_groups": {
            "items": {
              "$ref": "#/components/schemas/RotorGroupResource"
            },
            "title": "Rotor Groups",
            "type": "array"
          },
          "snapshot_version": {
            "default": 1,
            "title": "Snapshot Version",
            "type": "integer"
          },
          "solver_engine": {
            "default": "prom-rs/0.3.1",
            "title": "Solver Engine",
            "type": "string"
          },
          "status": {
            "enum": [
              "draft",
              "queued",
              "running",
              "completed",
              "failed",
              "canceled"
            ],
            "title": "Status",
            "type": "string"
          },
          "summary": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Summary"
          },
          "sweep_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sweep Config"
          },
          "total_points": {
            "title": "Total Points",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "progress",
          "created_at",
          "completed_at",
          "project_id",
          "inputs",
          "sweep_config",
          "total_points",
          "completed_points",
          "summary",
          "error",
          "name",
          "is_starred",
          "analysis_type",
          "credits_cost",
          "battery_component_id",
          "rotor_groups",
          "plot_config_json"
        ],
        "title": "SweepResource",
        "type": "object"
      },
      "SweepRotorGroupIn": {
        "additionalProperties": false,
        "description": "A sweep rotor group carries the SAME field set as the single-point\n``RotorGroupIn`` \u2014 the sweep AXES live on ``SweepConfigIn`` (the body), not on\nthe group. Inheriting ``RotorGroupIn`` fixes the historical bug where the sweep\ngroup's ``count`` was UNBOUNDED (it now inherits the bounded ``1..40`` count and\nthe shared cooling validator).",
        "properties": {
          "count": {
            "default": 1,
            "maximum": 40.0,
            "minimum": 1.0,
            "title": "Count",
            "type": "integer"
          },
          "custom_motor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_propeller": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "motor_t_mag": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed magnet temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T Mag"
          },
          "motor_t_w": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed winding temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T W"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "throttle_pct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Throttle Pct",
            "type": "number"
          },
          "tilt_deg": {
            "default": 0.0,
            "description": "Ground-mode rotor-axis tilt measured from the horizontal-forward (flight) direction (0\u00b0 = forward/cruise \u2014 the axis lies along the flight path and all airspeed becomes axial inflow; 90\u00b0 = lift/hover \u2014 the axis points up and forward airspeed becomes pure edgewise inflow). Decomposed host-side to V_axial = V_h\u00b7cos\u03b8 + V_v\u00b7sin\u03b8, V_edge = |V_v\u00b7cos\u03b8 \u2212 V_h\u00b7sin\u03b8|.",
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Tilt Deg",
            "type": "number"
          },
          "v_axial_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": -30.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode signed axial inflow (m/s); only with inflow_mode='components'.",
            "title": "V Axial M S"
          },
          "v_edge_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode edgewise inflow magnitude (m/s, \u22650); only with inflow_mode='components'.",
            "title": "V Edge M S"
          }
        },
        "required": [
          "throttle_pct",
          "label",
          "propeller_component_id"
        ],
        "title": "SweepRotorGroupIn",
        "type": "object"
      },
      "SweepRotorIn": {
        "additionalProperties": false,
        "description": "A sweep rotor carries the SAME field set as the single-point ``RotorIn``.\n\nSame reason as ``SweepRotorGroupIn``: the axes live on the body. Declared as\nits own name so the OpenAPI schema (and therefore the SDK) keeps the sweep\nand single-point request shapes separately addressable, matching the\nexisting group-side convention.",
        "properties": {
          "coax_position_m": {
            "default": 0.0,
            "description": "Position along the coaxial stack axis in metres, increasing downstream (in the direction the slipstream travels). The spacing between two rotors is the difference of their positions. Ignored when coax_stack_id is 0.",
            "maximum": 2.0,
            "minimum": -2.0,
            "title": "Coax Position M",
            "type": "number"
          },
          "coax_stack_id": {
            "default": 0,
            "description": "Coaxial stack this rotor belongs to. 0 (default) means the rotor is not stacked and is simulated in isolation. Rotors sharing a non-zero value form one contra-rotating or co-rotating stack.",
            "maximum": 16.0,
            "minimum": 0.0,
            "title": "Coax Stack Id",
            "type": "integer"
          },
          "custom_motor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_propeller": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/V1CustomComponentOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "esc_motor_wire_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Motor Wire Resistance Mohm",
            "type": "number"
          },
          "esc_pwm_frequency_khz": {
            "default": 24.0,
            "description": "ESC switching frequency (kHz)",
            "maximum": 48.0,
            "minimum": 8.0,
            "title": "Esc Pwm Frequency Khz",
            "type": "number"
          },
          "esc_resistance_mohm": {
            "default": 0.0,
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Esc Resistance Mohm",
            "type": "number"
          },
          "esc_sync_rectification": {
            "default": true,
            "description": "Synchronous rectification (comp_pwm); default ON",
            "title": "Esc Sync Rectification",
            "type": "boolean"
          },
          "esc_timing": {
            "default": "medium",
            "description": "Six-step commutation advance preset (low 7.5\u00b0/medium 15\u00b0/high 22.5\u00b0/auto duty-scheduled); FOC ignores it",
            "enum": [
              "low",
              "medium",
              "high",
              "auto"
            ],
            "title": "Esc Timing",
            "type": "string"
          },
          "esc_type": {
            "default": "six_step",
            "description": "ESC commutation type. Selects K_volt, copper_mult, iron_mult, the six-step commutation-advance physics and the throttle->duty map \u2014 not a cosmetic flag. Single-sourced (ESC-7): app/constants_esc.py.",
            "enum": [
              "foc",
              "six_step"
            ],
            "title": "Esc Type",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "motor_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Motor Component Id"
          },
          "motor_cooling_source": {
            "default": "prop_exit_velocity",
            "description": "Per-rotor-group motor cooling mode. cowling = still air; prop_exit_velocity = forced convection from the prop slipstream (default); custom = fixed velocity or direct thermal resistance.",
            "enum": [
              "cowling",
              "prop_exit_velocity",
              "custom"
            ],
            "title": "Motor Cooling Source",
            "type": "string"
          },
          "motor_cooling_velocity_m_s": {
            "anyOf": [
              {
                "maximum": 200.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom motor cooling convection velocity (m/s); only used when motor_cooling_source=custom.",
            "title": "Motor Cooling Velocity M S"
          },
          "motor_r_th": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom direct motor thermal resistance override (K/W); only used when motor_cooling_source=custom.",
            "title": "Motor R Th"
          },
          "motor_t_mag": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed magnet temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T Mag"
          },
          "motor_t_w": {
            "anyOf": [
              {
                "maximum": 250.0,
                "minimum": -60.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional fixed winding temperature (\u00b0C, -60\u2026250); omit to let the model compute it.",
            "title": "Motor T W"
          },
          "propeller_component_id": {
            "title": "Propeller Component Id",
            "type": "string"
          },
          "rotation_sense": {
            "default": 1,
            "description": "Direction of rotation about the downstream axis: 1 or -1. Opposite values in one stack give a contra-rotating pair, which recovers swirl energy and is the usual choice. Only read by coaxial pairing \u2014 a single rotor's value does not affect its own performance.",
            "enum": [
              1,
              -1
            ],
            "title": "Rotation Sense",
            "type": "integer"
          },
          "throttle_pct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Throttle Pct",
            "type": "number"
          },
          "tilt_deg": {
            "default": 0.0,
            "description": "Ground-mode rotor-axis tilt measured from the horizontal-forward (flight) direction (0\u00b0 = forward/cruise \u2014 the axis lies along the flight path and all airspeed becomes axial inflow; 90\u00b0 = lift/hover \u2014 the axis points up and forward airspeed becomes pure edgewise inflow). Decomposed host-side to V_axial = V_h\u00b7cos\u03b8 + V_v\u00b7sin\u03b8, V_edge = |V_v\u00b7cos\u03b8 \u2212 V_h\u00b7sin\u03b8|.",
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Tilt Deg",
            "type": "number"
          },
          "v_axial_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": -30.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode signed axial inflow (m/s); only with inflow_mode='components'.",
            "title": "V Axial M S"
          },
          "v_edge_m_s": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Components-mode edgewise inflow magnitude (m/s, \u22650); only with inflow_mode='components'.",
            "title": "V Edge M S"
          }
        },
        "required": [
          "throttle_pct",
          "label",
          "propeller_component_id"
        ],
        "title": "SweepRotorIn",
        "type": "object"
      },
      "TerminationIn": {
        "additionalProperties": false,
        "description": "Run-termination policy: the SOC / cell-voltage depletion cutoffs and the\nfixed-duration vs until-depleted run mode.",
        "properties": {
          "cell_voltage_cutoff_v": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cell Voltage Cutoff V"
          },
          "max_duration_s": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "maximum": 3600.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Duration S"
          },
          "mode": {
            "default": "until_depleted",
            "enum": [
              "fixed",
              "until_depleted"
            ],
            "title": "Mode",
            "type": "string"
          },
          "soc_cutoff_pct": {
            "default": 20.0,
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Soc Cutoff Pct",
            "type": "number"
          }
        },
        "title": "TerminationIn",
        "type": "object"
      },
      "UserResource": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "email_verified": {
            "title": "Email Verified",
            "type": "boolean"
          },
          "entitlements": {
            "$ref": "#/components/schemas/EntitlementsResource"
          },
          "first_name": {
            "title": "First Name",
            "type": "string"
          },
          "gate_required_tiers": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Gate Required Tiers",
            "type": "object"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_name": {
            "title": "Last Name",
            "type": "string"
          },
          "object": {
            "default": "user",
            "title": "Object",
            "type": "string"
          },
          "tier": {
            "title": "Tier",
            "type": "string"
          },
          "trial_days_remaining": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "readOnly": true,
            "title": "Trial Days Remaining"
          },
          "trial_end": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial End"
          },
          "trial_start": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Start"
          },
          "unit_system": {
            "enum": [
              "metric",
              "imperial"
            ],
            "title": "Unit System",
            "type": "string"
          }
        },
        "required": [
          "id",
          "email",
          "first_name",
          "last_name",
          "email_verified",
          "tier",
          "entitlements",
          "gate_required_tiers",
          "unit_system",
          "trial_start",
          "trial_end",
          "created_at",
          "trial_days_remaining"
        ],
        "title": "UserResource",
        "type": "object"
      },
      "V1CustomComponentOverride": {
        "additionalProperties": false,
        "description": "Per-request component override for custom-mode submissions.\n\nMirrors :class:`app.schemas.simulation.CustomComponentOverride` but accepts\na string base_component_id (raw UUID or ``comp_<ksuid>`` prefix) so callers\ncan use whichever identifier form they hold. Resolved to a UUID in the v1\nPOST handlers before handoff to the service layer.",
        "properties": {
          "base_component_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Component Id"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "spec_json": {
            "additionalProperties": true,
            "title": "Spec Json",
            "type": "object"
          }
        },
        "required": [
          "name",
          "spec_json"
        ],
        "title": "V1CustomComponentOverride",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "_WebhookEndpointCreate": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "events": {
            "items": {
              "type": "string"
            },
            "title": "Events",
            "type": "array"
          },
          "url": {
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "url",
          "events"
        ],
        "title": "_WebhookEndpointCreate",
        "type": "object"
      },
      "_WebhookEndpointPatch": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          },
          "events": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Events"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          }
        },
        "title": "_WebhookEndpointPatch",
        "type": "object"
      },
      "app__v1__serializers_components__ComponentListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ComponentResource"
            },
            "title": "Data",
            "type": "array"
          },
          "gated_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gated Count"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "ComponentListResponse",
        "type": "object"
      },
      "app__v1__serializers_projects__ProjectListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ProjectResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "ProjectListResponse",
        "type": "object"
      },
      "app__v1__serializers_submissions__SubmissionListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SubmissionResource"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "SubmissionListResponse",
        "type": "object"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Electric UAV powertrain simulation platform",
    "title": "ThrustLab API",
    "version": "v1-beta"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/airfoils": {
      "get": {
        "description": "Search the UIUC library (cached index) + the caller's custom airfoils.\n\nQuery params:\n* ``search`` \u2014 case-insensitive substring on the section name.\n* ``family`` \u2014 exact family facet (naca / clark-y / eppler / selig /...).\n* ``source`` \u2014 ``library`` (read-only UIUC) or ``mine`` (the caller's imports).\n* ``cursor`` / ``limit`` \u2014 offset-cursor pagination over the merged result.\n\nReturns the standard list envelope (``object:\"list\"`` / ``data`` /\n``has_more`` / ``next_cursor``). The library index is served from the\nmodule-global cache \u2014 never enumerated per request.",
        "operationId": "list_airfoils_v1_airfoils_get",
        "parameters": [
          {
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search"
            }
          },
          {
            "in": "query",
            "name": "family",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Family"
            }
          },
          {
            "in": "query",
            "name": "source",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(library|mine)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Source"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AirfoilListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Airfoils",
        "tags": [
          "v1",
          "airfoils"
        ]
      }
    },
    "/v1/airfoils/import": {
      "post": {
        "description": "Import a Selig or Lednicer ``.dat`` as a user-owned custom airfoil.\n\nmultipart/form-data: ``file`` (the ``.dat``) + ``name`` (display name).\n\nPipeline: byte-cap (DoS bound, BEFORE parse) -> auto-detect & Kulfan-fit\n(``airfoils_service.fit_dat``) -> persist a ``CustomAirfoil`` scoped to the\ncaller -> 201 with the ``afl_`` id.\n\nErrors:\n* Oversized upload -> 400 ``dat_too_large`` (bound BEFORE parse).\n* Unparseable bytes -> 400 ``invalid_dat``.\n* Unfittable section -> 422 ``airfoil_fit_failed``.",
        "operationId": "import_airfoil_v1_airfoils_import_post",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_airfoil_v1_airfoils_import_post"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AirfoilResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Import Airfoil",
        "tags": [
          "v1",
          "airfoils"
        ]
      }
    },
    "/v1/airfoils/{airfoil_id}": {
      "delete": {
        "description": "Delete one of the caller's custom airfoils (IDOR-safe).\n\nA foreign-owned or missing id returns the identical ``airfoil_not_found``\n404. Props already using the section keep their copied ``section_airfoils``\n(the solve source of truth) \u2014 there is no cascade.",
        "operationId": "delete_airfoil_v1_airfoils__airfoil_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "airfoil_id",
            "required": true,
            "schema": {
              "title": "Airfoil Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Airfoil",
        "tags": [
          "v1",
          "airfoils"
        ]
      },
      "get": {
        "description": "Fetch one of the caller's custom airfoils by ``afl_`` id.\n\nLibrary sections are not addressed here (they're listed, not fetched by id).\nA foreign-owned or missing id returns the identical 404 (anti-enumeration).",
        "operationId": "get_airfoil_v1_airfoils__airfoil_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "airfoil_id",
            "required": true,
            "schema": {
              "title": "Airfoil Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AirfoilResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Airfoil",
        "tags": [
          "v1",
          "airfoils"
        ]
      }
    },
    "/v1/components": {
      "get": {
        "description": "Return a paginated list spanning the public catalog and caller's customs.\n\nQuery parameters: `type` (optional; motor|battery|propeller \u2014 when omitted\nreturns all three types ordered by name/created_at only),\n`visibility` (optional; public/private; default: union),\n`limit` (1-100, default 25), `cursor` (pagination token),\n`search` (name substring match; `q` is an accepted alias \u2014 `search` wins\nif both are supplied, and `q` is length-capped identically),\n`sort_by` (name, brand, kv, etc.), `sort_order` (asc/desc).\n\nThe cursor is a sort-aware composite keyset: it carries the active\n`sort_by`/`sort_order`, so a cursor issued for one sort cannot be reused\nwith a different sort (400 `invalid_cursor`).\n\nNumeric spec_json fields are filterable via bracket syntax:\n?kv[gte]=900&kv[lt]=1100. Discrete fields accept [in]:\n?blades[in]=2,3. Per-type filters and per-type sort keys require ``type``\nto be set; without ``type`` only the generic ``name`` and ``created_at``\nsort keys are accepted.\n\nResults newest-first, cursor-paginated. Unknown filter keys are\nsilently dropped.",
        "operationId": "list_components_v1_components_get",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(motor|battery|propeller)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Type"
            }
          },
          {
            "in": "query",
            "name": "visibility",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(public|private)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Visibility"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search"
            }
          },
          {
            "description": "Alias for `search` (name substring match). If both are supplied, `search` wins. Length-capped identically to `search`.",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Alias for `search` (name substring match). If both are supplied, `search` wins. Length-capped identically to `search`.",
              "title": "Q"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "required": false,
            "schema": {
              "default": "name",
              "title": "Sort By",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "sort_order",
            "required": false,
            "schema": {
              "default": "asc",
              "title": "Sort Order",
              "type": "string"
            }
          },
          {
            "description": "When true, return ALL matching component ids in the requested sort order (bounded, NOT cursor-paginated) for Select-all. Response is {object,data:[ids],total,truncated}; cursor/limit are ignored. Bounded by a hard cap (truncated=true when exceeded).",
            "in": "query",
            "name": "ids_only",
            "required": false,
            "schema": {
              "default": false,
              "description": "When true, return ALL matching component ids in the requested sort order (bounded, NOT cursor-paginated) for Select-all. Response is {object,data:[ids],total,truncated}; cursor/limit are ignored. Bounded by a hard cap (truncated=true when exceeded).",
              "title": "Ids Only",
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/app__v1__serializers_components__ComponentListResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ComponentIdsResponse"
                    }
                  ],
                  "title": "Response List Components V1 Components Get"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Components",
        "tags": [
          "v1",
          "components"
        ]
      },
      "post": {
        "description": "Create a custom component scoped to the authenticated user.\n\nBody fields: `type` (required; motor|battery|propeller), `name` (required,\n1-255 chars), `spec_json` (required; type-specific map).\n\nEvery type's product-required spec_json fields are enforced at this\nboundary (2026-07-16); a missing field is a 400 naming the field, its\nmeaning, and its units. Motors need kv, n, R, weight, diameter, length,\nu_nominal, iq_nominal, and one of iq_max/power_max. Propellers need\ndiameter, pitch, weight, rotation, and parallel radius/chord/twist\nstation arrays. Batteries need a known chemistry plus, for a\nphysical pack, bounding-box dimensions, cell layout, capacity, mass, and\none internal-resistance figure (form_factor is derived from chemistry\nwhen omitted and stored); a source needs series_cells and source_voltage.\n\nReturns the new component resource (201) with source=\"user\",\nvisibility=\"private\", and user_id set to the caller. The response may\ncarry a non-blocking `warnings` list when a spec value looks physically\nimplausible (e.g. motor R far outside the expected range for its Kv,\nweight, and diameter \u2014 often a milliohm/ohm mix-up or a per-phase value\nwhere phase-to-phase is expected). A warning never rejects the write.",
        "operationId": "create_component_v1_components_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ComponentCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComponentWriteResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Component",
        "tags": [
          "v1",
          "components"
        ]
      }
    },
    "/v1/components/brands": {
      "get": {
        "description": "Public-catalog brand counts for a given component type, filter-aware.\n\nApplies spec-range and non-brand discrete filters from the query string\n(same bracket syntax as /v1/components LIST), plus optional ?search=name\nmatching. The ``brand[in]`` filter is intentionally ignored on this\nendpoint so selecting brands does not shrink the brand list to itself.\n\nBrandless rows (NULL or empty ``spec_json.brand``) are excluded per\nfeedback_brandless_custom_components.md. has_more is always false because\nthe brand list is bounded.",
        "operationId": "list_component_brands_v1_components_brands_get",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": true,
            "schema": {
              "pattern": "^(motor|battery|propeller)$",
              "title": "Type",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComponentBrandsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Component Brands",
        "tags": [
          "v1",
          "components"
        ]
      }
    },
    "/v1/components/{component_id}": {
      "delete": {
        "description": "Delete a user-owned custom component.\n\nPermissions: owner can delete their own private customs; cross-user\nor public-catalog access returns 403/404.\n\nReturns 204 No Content on success.",
        "operationId": "delete_component_v1_components__component_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "component_id",
            "required": true,
            "schema": {
              "title": "Component Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Component",
        "tags": [
          "v1",
          "components"
        ]
      },
      "get": {
        "description": "Retrieve a single component by prefixed id.\n\nPublic catalog: readable by any authenticated user.\nPrivate custom: readable by the owner only; cross-user access returns\n404 component_not_found.\n\nReturns the component resource (200).",
        "operationId": "get_component_v1_components__component_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "component_id",
            "required": true,
            "schema": {
              "title": "Component Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComponentResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Component",
        "tags": [
          "v1",
          "components"
        ]
      },
      "patch": {
        "description": "Update an editable field on a user-owned custom component.\n\nBody fields are optional: `name` (1-255 chars), `spec_json` (replaces\nentire spec_json on write, no deep merge).\n\nType, source, visibility, user_id, and base_component_id are not\neditable through /v1/.\n\nReturns the updated component resource (200), with the same non-blocking\n`warnings` behavior as create (a physically implausible spec value is\nflagged, never rejected).\n\nPermissions: owner can modify their own private customs; cross-user\nor public-catalog access returns 403/404.",
        "operationId": "patch_component_v1_components__component_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "component_id",
            "required": true,
            "schema": {
              "title": "Component Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ComponentPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComponentWriteResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Component",
        "tags": [
          "v1",
          "components"
        ]
      }
    },
    "/v1/components/{component_id}/specs": {
      "get": {
        "description": "The Turnstile-leased datasheet readout (spec gating, 2026-08-30 design).\n\nFree tier: 402 ``upgrade_required`` (the ``component_specs`` capability).\nPaid tiers, catalog motor/battery: the request must carry a valid\n``X-Turnstile-Token`` header OR ride an existing per-(user, component)\nlease \u2014 403 ``challenge_required`` / ``challenge_failed`` otherwise, and\n429 when the account's distinct-component grant budget is spent. API-key\ncallers skip the challenge (impossible in a programmatic client; the key\nis already payment-accountable) but consume the same caps. The caller's\nown custom row returns its raw spec with no challenge; other catalog\ntypes return the headline projection, uniform contract, no challenge.\n\nA passed challenge proves nothing about who drives the session afterward\n\u2014 the caps are the durable wall, so they bind to the ACCOUNT on every\nchannel.",
        "operationId": "get_component_specs_v1_components__component_id__specs_get",
        "parameters": [
          {
            "in": "path",
            "name": "component_id",
            "required": true,
            "schema": {
              "title": "Component Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComponentSpecsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Component Specs",
        "tags": [
          "v1",
          "components"
        ]
      }
    },
    "/v1/compute-units/balance": {
      "get": {
        "operationId": "get_credit_balance_v1_compute_units_balance_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalanceResource"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Credit Balance",
        "tags": [
          "v1",
          "compute-units"
        ]
      }
    },
    "/v1/compute-units/summary": {
      "get": {
        "description": "Owner-scoped usage meter read.\n\nReuses the metering primitives: ``used_in_window`` already SUMs\n``abs(amount)`` = per-rotor COMPUTE units (a 4-rotor static counts 4), so the\nmeter inherits compute-unit accounting. The tier is resolved via\n``entitlement_for`` (default-down: a forged/unknown tier \u2192 free, never\npro), never a raw dict lookup of the request-supplied tier.\n\nresets_at is the ROLLING window's next age-out instant \u2014 the oldest in-window\ndebit's ``created_at`` + the window length. With no in-window debit there is\nnothing pending to age out, so resets_at = now. It is NEVER ``since + window``\n(which equals ``now`` for every request because ``since = now - window``).",
        "operationId": "get_usage_summary_v1_compute_units_summary_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditUsageSummaryResource"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Usage Summary",
        "tags": [
          "v1",
          "compute-units"
        ]
      }
    },
    "/v1/compute-units/transactions": {
      "get": {
        "operationId": "list_credit_usage_v1_compute_units_transactions_get",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Type"
            }
          },
          {
            "in": "query",
            "name": "credit_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Credit Type"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "created_at[gte]",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Created At[Gte]"
            }
          },
          {
            "in": "query",
            "name": "created_at[lt]",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Created At[Lt]"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditUsageListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Credit Usage",
        "tags": [
          "v1",
          "compute-units"
        ]
      }
    },
    "/v1/dynamic-simulations": {
      "get": {
        "description": "List the caller's dynamic simulations (cursor-paginated, newest first).\n\nMirrors ``GET /v1/sweeps`` so the project page + queue strip can surface\ndynamic runs alongside steady/sweep runs. Ownership-scoped via the project\njoin (a caller never sees another user's runs). ``project`` accepts a raw\nUUID or proj_<ksuid>; the cursor is ``{created_at.isoformat()}|{public_id}``.",
        "operationId": "list_dynamic_v1_v1_dynamic_simulations_get",
        "parameters": [
          {
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Project"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      },
      "post": {
        "description": "Submit a transient (time-domain) powertrain run.\n\nPro-gated (free -> 403 ``pro_required``); the schedule is validated and the\ncredit cost (the coulombic upfront estimate) reserved server-side\nBEFORE the worker is dispatched. Returns ``202 Accepted`` with a\n``dyn_``-prefixed resource; poll ``GET`` or stream progress via SSE.",
        "operationId": "create_dynamic_v1_v1_dynamic_simulations_post",
        "parameters": [
          {
            "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
              "title": "Idempotency-Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DynamicCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/dynamic-simulations/estimate": {
      "post": {
        "description": "Estimate the credit cost + run duration WITHOUT running the solver.\n\nCoulombic only \u2014 resolves the battery capacity + reads the schedule mean\nthrottle and returns in milliseconds (no diffrax compile, no Celery dispatch;).\n\n``estimated_credits`` MUST equal what create will actually reserve \u2014 the\n3xR cap unit (create_dynamic_simulation: ``credits = 3 * R``), NOT the\ncoulombic minutes. The coulombic figure only sizes ``estimated_duration_s``\n(the worker's first integrate window); quoting it here under-stated the\ncharge for any multi-rotor run (e.g. a count-4 quad: quoted 2, billed 12).",
        "operationId": "estimate_dynamic_v1_v1_dynamic_simulations_estimate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DynamicEstimateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicEstimateResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Estimate Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/dynamic-simulations/{public_id}": {
      "get": {
        "operationId": "get_dynamic_v1_v1_dynamic_simulations__public_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      },
      "patch": {
        "description": "Rename or star/unstar a dynamic run.\n\nOwnership-scoped via ``_load_owned_dynamic`` FIRST (a foreign / missing id\n404s with no existence leak) before any mutation.",
        "operationId": "patch_dynamic_v1_v1_dynamic_simulations__public_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DynamicPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/dynamic-simulations/{public_id}/cancel": {
      "post": {
        "operationId": "cancel_dynamic_v1_v1_dynamic_simulations__public_id__cancel_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DynamicResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/dynamic-simulations/{public_id}/export.csv": {
      "get": {
        "description": "Stream the full-resolution time series as CSV (ownership-scoped FIRST).\n\nThe solver's full-resolution save-cadence output is persisted at run time\nas the export source; this route is a pure read+stream \u2014 NO re-integration\nin-request.",
        "operationId": "export_dynamic_csv_v1_v1_dynamic_simulations__public_id__export_csv_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Export Dynamic Csv V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/dynamic-simulations/{public_id}/stream": {
      "get": {
        "operationId": "stream_dynamic_v1_v1_dynamic_simulations__public_id__stream_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Dynamic V1",
        "tags": [
          "v1",
          "dynamic-simulations"
        ]
      }
    },
    "/v1/events": {
      "get": {
        "description": "List events for the authenticated principal, newest first.\n\nFilters are flat per surface-audit \u00a73 (no Stripe-style ``[lookup]``\nsuffixes for equality), with the exception of ``created_at[gte]`` and\n``created_at[lt]`` for time-range queries (parsed from the raw query\nstring since FastAPI cannot bind brackets to ordinary parameter names).",
        "operationId": "list_events_v1_events_get",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Type"
            }
          },
          {
            "in": "query",
            "name": "resource_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Resource Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Events V1 Events Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Events",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/events/{event_id}": {
      "get": {
        "description": "Retrieve a single event scoped to the authenticated principal.\n\nCross-user lookups return 404 (not 403) so the event id namespace\nleaks no information about other tenants..",
        "operationId": "get_event_v1_events__event_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "event_id",
            "required": true,
            "schema": {
              "title": "Event Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Event V1 Events  Event Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Event",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/geometry/analyze": {
      "post": {
        "description": "Aero-only operating-point analysis (point / sweep / solve-to-target).\n\nWraps the analyze service on the editor's live working geometry.\nAERO-ONLY \u2014 there is NO motor/battery/ESC field anywhere; the strict\n``extra=\"forbid\"`` serializer is the guard. SYNCHRONOUS on the warm JIT\ncache \u2014 a plain 200 with the result, never a 202/job id. STATELESS:\nthe editor's inline arrays carry everything, so this touches NO DB and reads\nno current user (no saved-component path -> no IDOR surface).\n\nA genuine build/solve failure (degenerate geometry, bad target) rewraps\n``ValueError -> 422`` with a user-safe message and no traceback (mirrors the process_image idiom). A NON-converged solve-to-target is NOT an\nerror: it returns a normal 200 with ``converged: false`` + a ``reason``.",
        "operationId": "analyze_geometry_v1_geometry_analyze_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnalyzeGeometryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyzeGeometryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Analyze Geometry",
        "tags": [
          "v1",
          "geometry"
        ]
      }
    },
    "/v1/geometry/design": {
      "post": {
        "description": "Generate an optimal MIL starting blade from design targets; returns 202 + id.\n\nDispatches the two-stage MIL design (Betz seed -> L-BFGS efficiency polish,) to the concurrency=1 Celery worker. Stream\nprogress at ``GET /v1/geometry/design/{id}/stream``. Creating a blade is FREE \u2014\nthis runs OUTSIDE the credits ledger. The owner is stamped into the Redis\npayload at dispatch (IDOR) and the job id starts with ``geom_``.",
        "operationId": "design_geometry_v1_geometry_design_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalibrateAcceptedResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Design Geometry",
        "tags": [
          "v1",
          "geometry"
        ]
      }
    },
    "/v1/geometry/design/{job_id}/stream": {
      "get": {
        "description": "SSE relay for a design job's progress (ownership-guarded).\n\nClone of ``stream_calibration``: text/event-stream, Cache-Control no-cache,\nX-Accel-Buffering no; OWNERSHIP FIRST \u2014 a foreign or missing\njob id returns 404 resource_missing (no enumeration signal). Then subscribe\nf\"design_events:{id}\", emit an initial ``queued`` snapshot, keepalive ~30s,\nunwrap the worker's {\"object\": {...}} envelope, break on terminal status,\nfinally unsubscribe + aclose. Distinct ``design.updated`` SSE event name\n so a stale calibration client cannot read design frames.",
        "operationId": "stream_design_v1_geometry_design__job_id__stream_get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Design",
        "tags": [
          "v1",
          "geometry"
        ]
      }
    },
    "/v1/geometry/export": {
      "post": {
        "description": "Export the caller's OWN working/saved geometry to STEP / IGES / STL bytes.\n\nGATED: CAD export requires the ``cad_export`` capability\n(Pro) AND exports OWN-CUSTOM geometry only. The capability gate runs\nFIRST (before any geometry is resolved) so a non-Pro user gets a legible 402\n``upgrade_required`` rather than a 404. A CATALOG (public) ``component_id`` is\nNEVER the export source \u2014 only the caller's OWN custom prop or their inline\nworking geometry. The curated propeller geometry moat thus reaches CAD\nbytes, not just component specs.\n\nSYNC binary download: lofts the geometry into a watertight N-blade solid in\nan isolated one-shot subprocess and returns the bytes with a\n``Content-Disposition: attachment`` header + the CAD MIME per format. NO\n``response_model`` (raw bytes; mirrors export.csv).\n\nTwo input paths (exactly one, enforced by the serializer):\n* inline ``section_coords`` + chord/twist/radius \u2014 the primary path; the editor\n already holds these from ``/v1/geometry/generate`` (the user's OWN design, no\n DB read \u2014 allowed for a cad_export-capable user).\n* ``component_id`` \u2014 re-derives the section_coords from the saved ``spec_json``\n via the deterministic generator, resolved to the caller's OWN CUSTOM\n prop only (a catalog/public id -> the same 404 as a foreign-private id;, anti-enumeration).\n\nA loft that cannot close to a valid solid -> 422 ``geometry_not_loftable``\n(CadExportError, never a 500). The filename is sanitized.",
        "operationId": "export_geometry_v1_geometry_export_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExportGeometryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Export Geometry",
        "tags": [
          "v1",
          "geometry"
        ]
      }
    },
    "/v1/geometry/generate": {
      "post": {
        "description": "Generate full propeller geometry from explicit spline definitions.\n\nUse this for custom designs that aren't in the catalog.\n\nBody fields: diameter, pitch, num_blades, chord_spline, thickness_spline,\nthickness_scale, airfoil, and the optional editor-intent DOFs\ntwist_spline (explicit twist B-spline; absent => pitch-derived twist) and\nairfoil_layout (per-station airfoil breakpoints; absent => single airfoil).\n\nReturns a geometry resource with the preview array fields (radius, chord,\ntwist, thickness, hub_radius, section_airfoils) PLUS loft-ready\nsection_coords (cosine-sampled per station) for the 3D viewer / CAD export.\n\nStateless compute; the DB is touched ONLY to resolve caller-owned ``afl_``\ncustom airfoils referenced in airfoil_layout (caller-scoped).\nAn unknown airfoil name or an unfittable layout -> 422 unknown_airfoil.",
        "operationId": "generate_geometry_v1_geometry_generate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateGeometryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeometryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Generate Geometry",
        "tags": [
          "v1",
          "geometry"
        ]
      }
    },
    "/v1/geometry_styles": {
      "get": {
        "description": "List the full catalog of pre-defined blade geometry styles.\n\nThe response uses the standard list envelope, but has_more is always false\nbecause the catalog is small enough not to need cursor pagination today.\n\nOrdering is stable: (manufacturer, label).\n\nReturns a list response with data, has_more=false, and next_cursor=null.",
        "operationId": "list_geometry_styles_v1_geometry_styles_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeometryStylesListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Geometry Styles",
        "tags": [
          "v1",
          "geometry_styles"
        ]
      }
    },
    "/v1/geometry_styles/{slug}": {
      "get": {
        "description": "Retrieve a single geometry style by stable slug id.\n\nThe id field is a stable slug (e.g. 'apc-e'), not a prefixed KSUID.\nGeometry styles are a small finite catalog with intentionally human-readable\nslug ids.\n\nReturns a geometry_style resource (200), or 404 geometry_style_not_found\nif the slug is unknown.",
        "operationId": "get_geometry_style_v1_geometry_styles__slug__get",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeometryStyleResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Geometry Style",
        "tags": [
          "v1",
          "geometry_styles"
        ]
      }
    },
    "/v1/health": {
      "get": {
        "description": "Liveness probe for the v1 surface.\n\nReturns a minimal resource-shaped object so SDK smoke tests can exercise\nthe full response-shape pipeline without needing auth.",
        "operationId": "v1_health_v1_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response V1 Health V1 Health Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [],
        "summary": "V1 Health",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/projects": {
      "get": {
        "description": "List projects owned by the authenticated user.\n\nResults are newest-first and cursor-paginated. Query parameters:\n`limit` (1-100, default 25), `cursor` (opaque pagination token).\n\nReturns a list response with `data`, `has_more`, and `next_cursor` fields.",
        "operationId": "list_projects_v1_projects_get",
        "parameters": [
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__v1__serializers_projects__ProjectListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Projects",
        "tags": [
          "v1",
          "projects"
        ]
      },
      "post": {
        "description": "Create a new project owned by the authenticated user.\n\nBody fields: `name` (required, 1-255 chars), `aircraft_type_tag` (optional,\nup to 50 chars), `notes` (optional, no length cap).\n\nReturns the new project resource (201).",
        "operationId": "create_project_v1_projects_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Project",
        "tags": [
          "v1",
          "projects"
        ]
      }
    },
    "/v1/projects/{project_id}": {
      "delete": {
        "description": "Delete the project and cascade-delete all child rows.\n\nCascade deletes all simulations, sweeps, and starred components\nbelonging to the project. This is destructive with no soft-delete or\nundo at the /v1/ surface. If you need to retain historical results,\nfetch them before deleting the parent project.\n\nReturns 204 No Content on success.",
        "operationId": "delete_project_v1_projects__project_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Project",
        "tags": [
          "v1",
          "projects"
        ]
      },
      "get": {
        "description": "Retrieve a single project by prefixed id.\n\nThe path parameter accepts both `proj_<ksuid>` and UUID forms.\nCross-user access returns 404 (anti-enumeration).\n\nReturns the project resource (200).",
        "operationId": "get_project_v1_projects__project_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Project",
        "tags": [
          "v1",
          "projects"
        ]
      },
      "patch": {
        "description": "Update one or more editable fields.\n\nBody fields are all optional: `name` (1-255 chars), `aircraft_type_tag`\n(up to 50 chars), `notes` (no length cap). Only fields included in the\nrequest body are updated; omitted fields preserve their current values.\n\nEmpty body is a 200 idempotent no-op.\n\nReturns the updated project resource (200).",
        "operationId": "patch_project_v1_projects__project_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "project_id",
            "required": true,
            "schema": {
              "title": "Project Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Project",
        "tags": [
          "v1",
          "projects"
        ]
      }
    },
    "/v1/public/propellers": {
      "get": {
        "description": "Unauthenticated curated-propeller GEOMETRY-only list.\n\nHard curated/public WHERE clause; geometry-only projection; allowlisted\nsort + optional bracket-range filters; page-size capped; per-IP rate limited.",
        "operationId": "list_public_propellers_v1_public_propellers_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "sort_by",
            "required": false,
            "schema": {
              "default": "name",
              "title": "Sort By",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "sort_order",
            "required": false,
            "schema": {
              "default": "asc",
              "title": "Sort Order",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Public Propellers V1 Public Propellers Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [],
        "summary": "List Public Propellers",
        "tags": [
          "v1",
          "public"
        ]
      }
    },
    "/v1/public/results/{slug}": {
      "get": {
        "description": "One curated public sim resolved on curated_slug + is_curated==True ONLY.\n\nHard 404 if not found / not curated (a private or non-curated sim is never\nreachable here \u2014 no slug enumeration leaks private rows).",
        "operationId": "get_public_result_v1_public_results__slug__get",
        "parameters": [
          {
            "in": "path",
            "name": "slug",
            "required": true,
            "schema": {
              "title": "Slug",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Public Result V1 Public Results  Slug  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [],
        "summary": "Get Public Result",
        "tags": [
          "v1",
          "public"
        ]
      }
    },
    "/v1/public/share/{share_token}": {
      "get": {
        "description": "One share-token-matched sim (feeds the noindex /share/[token] page).\n\nResolves on the exact opaque share_token ONLY; hard 404 on no match. The\ntoken is unguessable (new_public_id), so this is not an enumeration surface.",
        "operationId": "get_shared_result_v1_public_share__share_token__get",
        "parameters": [
          {
            "in": "path",
            "name": "share_token",
            "required": true,
            "schema": {
              "title": "Share Token",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Shared Result V1 Public Share  Share Token  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [],
        "summary": "Get Shared Result",
        "tags": [
          "v1",
          "public"
        ]
      }
    },
    "/v1/simulations": {
      "get": {
        "description": "List single-point simulations owned by the caller with cursor pagination.",
        "operationId": "list_simulations_v1_v1_simulations_get",
        "parameters": [
          {
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Project"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Simulations V1",
        "tags": [
          "v1",
          "simulations"
        ]
      },
      "post": {
        "operationId": "create_simulation_v1_v1_simulations_post",
        "parameters": [
          {
            "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
              "title": "Idempotency-Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulationCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/cancel-queued": {
      "post": {
        "description": "Cancel EVERY queued run the caller owns \u2014 sims, sweeps and dynamic\nmissions \u2014 optionally within one project. Running runs are left alone\n(cancel them with ``cancel-selected``). Each queued row is cancelled with a\nfull refund, oldest first. Cross-project by default, like ``run-queued``.",
        "operationId": "cancel_queued_v1_v1_simulations_cancel_queued_post",
        "parameters": [
          {
            "description": "Restrict to one project (proj_ id). Default: every project the caller owns.",
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Restrict to one project (proj_ id). Default: every project the caller owns.",
              "title": "Project"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelBatchResult"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Queued V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/cancel-selected": {
      "post": {
        "description": "Cancel a caller-selected set of runs of any kind in one call.\n\nEvery id is ownership-checked BEFORE anything is cancelled \u2014 a cross-user or\nmissing id fails the whole call with 404 ``resource_missing`` and no\nexistence leak, exactly like ``run-selected``. Rows that cannot be cancelled\nare *skipped* with a reason rather than failing the batch: terminal rows,\ndrafts (delete those instead) and running single-points (they finish in\nseconds). Queued rows are cancelled immediately with a full refund; a\nrunning sweep gets a durable cancel request the worker honours at its next\npoint (``requested``); a running dynamic mission stops at its next\nintegration window and is reported as ``canceled`` because its status\nflips now.",
        "operationId": "cancel_selected_v1_v1_simulations_cancel_selected_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelSelectedBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelBatchResult"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Selected V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/export/fmu/{job_id}": {
      "get": {
        "description": "Read an FMU export job's status (ownership-guarded).\n\n``status`` walks queued \u2192 solving \u2192 completed | failed. While it solves,\n``units_done``/``units_total`` give weighted, monotone progress over the\nWHOLE job, ``phase`` names the surface being sampled and ``eta_s`` is the\nserver's estimate of the seconds left (null until measurable).\n``chunks_done``/``chunks_total`` remain the current phase's own counters.\nA completed job carries ``filename`` and ``artifact_available``; fetch\n``.../download`` while it is true (24 h).",
        "operationId": "get_fmu_export_v1_v1_simulations_export_fmu__job_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FmuExportStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Fmu Export V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/export/fmu/{job_id}/cancel": {
      "post": {
        "description": "Request cancellation of a running FMU export (ownership-guarded).\n\nCooperative: the worker stops at the next sweep chunk boundary and the job\nterminates as ``failed`` with ``error_code: export_cancelled``. Cancelling\nan already-terminal job changes nothing.",
        "operationId": "cancel_fmu_export_v1_v1_simulations_export_fmu__job_id__cancel_post",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FmuExportStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Fmu Export V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/export/fmu/{job_id}/download": {
      "get": {
        "description": "Download a completed FMU export's ``.fmu`` (ownership-guarded).\n\nAvailable for 24 hours after completion; afterwards the artifact expires\nand the export must be run again.",
        "operationId": "download_fmu_export_v1_v1_simulations_export_fmu__job_id__download_get",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Download Fmu Export V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/run-queued": {
      "post": {
        "description": "Run ALL the caller's queued simulations as warm batches grouped by rotor\ncount. Cross-project. Returns the dispatcher result including\n``compiles_needed`` so the frontend can render the mixed-rotor warning (non-blocking).",
        "operationId": "run_queued_v1_v1_simulations_run_queued_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Run Queued V1 V1 Simulations Run Queued Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Run Queued V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/run-selected": {
      "post": {
        "description": "Run a caller-selected subset of queued sims as warm batches grouped by\nrotor count. Each id is ownership-checked (cross-user \u2192 404) and\nmust be status==\"queued\".",
        "operationId": "run_selected_v1_v1_simulations_run_selected_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunSelectedBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Run Selected V1 V1 Simulations Run Selected Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Run Selected V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}": {
      "delete": {
        "operationId": "delete_simulation_v1_v1_simulations__public_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      },
      "get": {
        "operationId": "get_simulation_v1_v1_simulations__public_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      },
      "patch": {
        "operationId": "patch_simulation_v1_v1_simulations__public_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulationPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}/cancel": {
      "post": {
        "operationId": "cancel_simulation_v1_v1_simulations__public_id__cancel_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SimulationCancelBody"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}/export/fmu": {
      "post": {
        "description": "Export a powertrain as an FMI 3.0 Co-Simulation FMU (asynchronous).\n\nQueues a sampling job (202 + ``fmu_<ksuid>``): the powertrain's component\nsurfaces \u2014 aero, motor and pack \u2014 are sampled through the same engine that\nproduced the on-screen result and packaged as a win64 + linux64 ``.fmu``\nthat integrates each rotor's speed. Poll\n``GET /v1/simulations/export/fmu/{id}`` (or stream ``.../stream``), then\nfetch ``.../download`` \u2014 the artifact stays available for 24 hours.\n\nRequires the ``fmi_export`` capability (Pro). The source run must be a\ncompleted single-point simulation with no multi-pack battery topology,\nsolved on the current engine. Heterogeneous rotor groups ARE supported \u2014\nschema 3 samples one set of component surfaces per distinct hardware group\nand binds each rotor to one through the manifest. A coaxial pair exports\none interference-baked lane table per rotor, with the partner's speed\nratio as an extra axis (a coax export samples substantially longer). One\nexport job runs per account at a time.\n\nSend an ``Idempotency-Key`` header and a repeat of the same request replays\nthe same 202 \u2014 the same job id \u2014 instead of queueing a second export. The\nreplay is available for 24 hours, the same window the job itself lives for.",
        "operationId": "export_simulation_fmu_v1_v1_simulations__public_id__export_fmu_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FmuExportAcceptedResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Export Simulation Fmu V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}/promote": {
      "post": {
        "operationId": "promote_draft_v1_v1_simulations__public_id__promote_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulationCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulationResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Promote Draft V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}/share": {
      "post": {
        "description": "Mint (or return the existing) share_token for a sim the caller owns.\n\nOwner-scoped and idempotent for single-point (``sim_``), sweep (``sweep_``),\nand dynamic (``dyn_``) sims: the id prefix selects the owner-scoped loader,\nboth of which 404 a non-owner / missing / wrong-prefix id (no existence\nleak), and the token is set once (a re-call returns the same token).",
        "operationId": "make_simulation_public_v1_simulations__public_id__share_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Make Simulation Public",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/simulations/{public_id}/stream": {
      "get": {
        "operationId": "stream_simulation_v1_v1_simulations__public_id__stream_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Simulation V1",
        "tags": [
          "v1",
          "simulations"
        ]
      }
    },
    "/v1/starred_components": {
      "get": {
        "description": "List the caller's stars across all projects, newest first, cursor-paginated.\n\nSupports flat-filter narrowing by project and component type.\n\nQuery parameters: project (optional, prefixed or UUID; cross-user \u2192 404),\ncomponent_type (optional; motor|battery|propeller), limit (1-100,\ndefault 25), cursor (pagination token).\n\nReturns a list response with data, has_more, and next_cursor fields.\nEach row carries its own star_<ksuid> id, both parent prefixed identifiers,\nand created_at timestamp.",
        "operationId": "list_starred_components_v1_starred_components_get",
        "parameters": [
          {
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Project"
            }
          },
          {
            "in": "query",
            "name": "component_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(motor|battery|propeller)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Component Type"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StarredComponentListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Starred Components",
        "tags": [
          "v1",
          "starred_components"
        ]
      },
      "post": {
        "description": "Star a component within a project.\n\nBody fields: project_id (required, prefixed or UUID), component_id\n(required, prefixed or UUID), component_type (motor|battery|propeller).\n\nBoth project_id and component_id accept prefixed or UUID forms \u2014 useful\nduring reference-app transition. Cross-user access returns 404s.\n\nReturns the new starred_component resource (201).\n\nError 409 if the (project_id, component_id) pair is already starred.",
        "operationId": "star_component_v1_starred_components_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StarredComponentCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StarredComponentResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Star Component",
        "tags": [
          "v1",
          "starred_components"
        ]
      }
    },
    "/v1/starred_components/{star_id}": {
      "delete": {
        "description": "Unstar a component.\n\nThe path parameter is the star's own star_<ksuid> id, not the underlying\ncomponent id. Also accepts the underlying UUID form for transition-period\ncompatibility; new integrations should use the prefixed form.\n\nReturns 204 No Content on success.\n\nError 404 if the star id is unknown or cross-user.",
        "operationId": "unstar_component_v1_starred_components__star_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "star_id",
            "required": true,
            "schema": {
              "title": "Star Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Unstar Component",
        "tags": [
          "v1",
          "starred_components"
        ]
      }
    },
    "/v1/submissions": {
      "get": {
        "description": "List the caller's own submissions, newest first, cursor-paginated.\n\nQuery parameters: status (optional filter by exact status), limit (1-100,\ndefault 25), cursor (pagination token).\n\nReturns a list response with data, has_more, and next_cursor fields.",
        "operationId": "list_submissions_v1_submissions_get",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "pattern": "^(submitted|under_review|approved|rejected)$",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__v1__serializers_submissions__SubmissionListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Submissions",
        "tags": [
          "v1",
          "submissions"
        ]
      },
      "post": {
        "description": "Create a new community-contribution submission.\n\nPropose a motor or battery for inclusion in the public catalog.\n\nBody fields: component_type (motor|battery), name, manufacturer, data_json\n(type-specific spec map), source_url, notes (optional).\n\nMotor data_json.R is the PHASE-TO-PHASE winding resistance in ohms \u2014 the\ndatasheet value, what a meter reads across two motor leads. This matches\nthe component spec_json.R convention, so an approved submission's\ndata_json copies verbatim into a catalog spec (2026-07-16 unification;\ndata_json was previously per-phase). Curation note: add_motor takes\nterminal milliohms, so a motortoolbox import is R x 1000.\n\nReturns the new submission resource (201) with status=\"submitted\".\n\nA component.submitted webhook event fires for every successful create.",
        "operationId": "create_submission_v1_submissions_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Submission",
        "tags": [
          "v1",
          "submissions"
        ]
      }
    },
    "/v1/submissions/{submission_id}": {
      "delete": {
        "description": "Withdraw a submission. Only allowed while status='submitted'.\n\nThe row is hard-deleted. No deletion event is emitted \u2014 withdrawn\nsubmissions simply disappear from the user's listing.\n\nReturns 204 No Content on success.\n\nError 409 if status has moved past 'submitted' (already under review).",
        "operationId": "delete_submission_v1_submissions__submission_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "submission_id",
            "required": true,
            "schema": {
              "title": "Submission Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Submission",
        "tags": [
          "v1",
          "submissions"
        ]
      },
      "get": {
        "description": "Retrieve a single submission by prefixed id.\n\nCross-user access returns 404 submission_not_found.\n\nReturns the submission resource (200).",
        "operationId": "get_submission_v1_submissions__submission_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "submission_id",
            "required": true,
            "schema": {
              "title": "Submission Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Submission",
        "tags": [
          "v1",
          "submissions"
        ]
      },
      "patch": {
        "description": "Edit a submission before review.\n\nAllowed fields: name, manufacturer, data_json, source_url, notes.\ncomponent_type is not editable \u2014 it determines moderation routing.\n\nEmpty body returns 200 with the unchanged resource (idempotent no-op).\n\nReturns the updated submission resource (200).\n\nError 409 if status has moved past 'submitted' (a moderator has reviewed).",
        "operationId": "patch_submission_v1_submissions__submission_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "submission_id",
            "required": true,
            "schema": {
              "title": "Submission Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmissionPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Submission",
        "tags": [
          "v1",
          "submissions"
        ]
      }
    },
    "/v1/sweeps": {
      "get": {
        "description": "List parameter sweeps owned by the caller with cursor pagination.",
        "operationId": "list_sweeps_v1_v1_sweeps_get",
        "parameters": [
          {
            "in": "query",
            "name": "project",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Project"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Sweeps V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      },
      "post": {
        "description": "Submit a batch parameter sweep (one Cartesian grid of operating points).\n\nEvery grid point is one powertrain solve; a sweep can range from a handful to\nthe 10,000-point ceiling.\n\nSubmit the grid as ONE sweep rather than N single-point POSTs: the batch is\nprepared once and reused across every compatible point, so a large grid\nreturns far sooner than the same points submitted one at a time. One request\nreplaces N, with no offsetting cost.\n\nIt is not a price advantage. A sweep bills one compute unit per evaluation\npoint per physical rotor \u2014 the same as running those points individually \u2014\nso a 400-point grid on a quad costs 1,600 CU either way. Two limits bound a\nsubmission: at most 10,000 points per sweep, and\n`rotors x points <= max_sweep_work` for the caller's plan (`422`\n`sweep_limit_exceeded` names the plan's ceiling and the requested figure).\n\nExample::\n\n    POST /v1/sweeps\n    Idempotency-Key: <uuid>\n    {\n      \"project_id\": \"proj_\u2026\",\n      \"rotors\": [{\"label\": \"Main\",\n                  \"motor_component_id\": \"comp_\u2026\",\n                  \"propeller_component_id\": \"comp_\u2026\",\n                  \"throttle_pct\": 100}],\n      \"battery_component_id\": \"comp_\u2026\",\n      \"density_kg_m3\": 1.225,\n      \"airspeed_m_s\": 0,\n      \"cooling_source\": \"prop_slipstream\",\n      \"sweep\": {\"throttle\": {\"mode\": \"range\", \"start\": 40, \"stop\": 100, \"steps\": 7},\n                \"rotor_sweep_mask\": [true]}\n    }\n\nReturns `202 Accepted` with the sweep resource (`total_points`,\n`completed_points`); poll `GET /v1/sweeps/{id}` or stream progress via SSE.",
        "operationId": "create_sweep_v1_v1_sweeps_post",
        "parameters": [
          {
            "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
              "title": "Idempotency-Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SweepCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}": {
      "delete": {
        "operationId": "delete_sweep_v1_v1_sweeps__public_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      },
      "get": {
        "operationId": "get_sweep_v1_v1_sweeps__public_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      },
      "patch": {
        "operationId": "patch_sweep_v1_v1_sweeps__public_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SweepPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}/cancel": {
      "post": {
        "operationId": "cancel_sweep_v1_v1_sweeps__public_id__cancel_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SweepCancelBody"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}/points": {
      "get": {
        "description": "Return sweep_point rows for a /v1/ sweep with cursor pagination.",
        "operationId": "list_sweep_points_v1_v1_sweeps__public_id__points_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "maximum": 1000,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepPointListResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Sweep Points V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}/points/{index}": {
      "patch": {
        "description": "Star/unstar a single sweep point. Ownership enforced via _load_owned_sweep\n before any mutation; out-of-range index \u2192 404.",
        "operationId": "patch_sweep_point_v1_v1_sweeps__public_id__points__index__patch",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "index",
            "required": true,
            "schema": {
              "title": "Index",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SweepPointPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepPointResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Sweep Point V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}/promote": {
      "post": {
        "operationId": "promote_sweep_v1_v1_sweeps__public_id__promote_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": true,
            "schema": {
              "description": "Unique key (max 255 chars) making this POST safe to retry. Required on all v1 write requests; replays return the cached response.",
              "title": "Idempotency-Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SweepCreateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SweepResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Promote Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/sweeps/{public_id}/stream": {
      "get": {
        "operationId": "stream_sweep_v1_v1_sweeps__public_id__stream_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Sweep V1",
        "tags": [
          "v1",
          "sweeps"
        ]
      }
    },
    "/v1/users/me": {
      "get": {
        "description": "Return the authenticated user's profile.\n\nIncludes: id, email, email_verified, tier (free|beta_tester|hobbyist|pro),\nunit_system (metric|imperial display preference; storage stays metric),\ntrial_start/trial_end (or null), trial_days_remaining, and created_at.\n\nThe `id` is a stable `user_<ksuid>`; safe to store in your own systems\nas a long-term identifier.",
        "operationId": "get_users_me_v1_users_me_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResource"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Users Me",
        "tags": [
          "v1",
          "users"
        ]
      }
    },
    "/v1/webhook_endpoints": {
      "get": {
        "operationId": "list_webhook_endpoints_v1_webhook_endpoints_get",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          },
          {
            "in": "query",
            "name": "enabled",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Enabled"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Webhook Endpoints V1 Webhook Endpoints Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Webhook Endpoints",
        "tags": [
          "v1"
        ]
      },
      "post": {
        "operationId": "create_webhook_endpoint_v1_webhook_endpoints_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_WebhookEndpointCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Create Webhook Endpoint V1 Webhook Endpoints Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Webhook Endpoint",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}": {
      "delete": {
        "operationId": "delete_webhook_endpoint_v1_webhook_endpoints__public_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Webhook Endpoint",
        "tags": [
          "v1"
        ]
      },
      "get": {
        "operationId": "get_webhook_endpoint_v1_webhook_endpoints__public_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Webhook Endpoint V1 Webhook Endpoints  Public Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Webhook Endpoint",
        "tags": [
          "v1"
        ]
      },
      "patch": {
        "operationId": "patch_webhook_endpoint_v1_webhook_endpoints__public_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_WebhookEndpointPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Patch Webhook Endpoint V1 Webhook Endpoints  Public Id  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Patch Webhook Endpoint",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}/deliveries": {
      "get": {
        "description": "List deliveries for one endpoint, filterable + cursor-paginated.\n\nFilters: ``status`` (delivery state), ``event_type`` (JOIN to events.type),\n``created_at[gte]`` (raw query-param parsed off ``request.query_params``\nbecause FastAPI can't bind keys with brackets to function arguments).\nSort + cursor format match the endpoints list (created_at desc, public_id\ndesc tie-breaker) so :func:`_encode_cursor` / :func:`_decode_cursor` are\nreused unchanged.",
        "operationId": "list_deliveries_v1_webhook_endpoints__public_id__deliveries_get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "event_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Event Type"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 25,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Deliveries V1 Webhook Endpoints  Public Id  Deliveries Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Deliveries",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}/deliveries/{delivery_public_id}": {
      "get": {
        "operationId": "get_delivery_v1_webhook_endpoints__public_id__deliveries__delivery_public_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "delivery_public_id",
            "required": true,
            "schema": {
              "title": "Delivery Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Delivery V1 Webhook Endpoints  Public Id  Deliveries  Delivery Public Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Delivery",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}/deliveries/{delivery_public_id}/retry": {
      "post": {
        "description": "Manually replay a terminal delivery.\n\nCreates a brand-new delivery row with ``manual_retry_of`` pointing back\nat the source delivery and a fresh attempt budget. Reuses the original's\n``request_body`` so the worker re-signs the same canonical bytes \u2014 this\nmatters when the source event has since been pruned by the retention\nsweep, since the body lives on the delivery row, not the event row.\n\nRejects with 409 when the source is still ``pending`` so a stuck delivery\ncan't be cloned into a duplicate-fire pair.",
        "operationId": "retry_delivery_v1_webhook_endpoints__public_id__deliveries__delivery_public_id__retry_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "delivery_public_id",
            "required": true,
            "schema": {
              "title": "Delivery Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Retry Delivery V1 Webhook Endpoints  Public Id  Deliveries  Delivery Public Id  Retry Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Retry Delivery",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}/rotate_secret": {
      "post": {
        "description": "Generate a new secret, replace stored value, return it once.\n\nOld secret is invalidated immediately \u2014 no overlap window. Documented\nbehavior per: rotate during a maintenance window.",
        "operationId": "rotate_webhook_secret_v1_webhook_endpoints__public_id__rotate_secret_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Rotate Webhook Secret V1 Webhook Endpoints  Public Id  Rotate Secret Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Rotate Webhook Secret",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/webhook_endpoints/{public_id}/test": {
      "post": {
        "description": "Fire a synthetic ``webhook.test`` event scoped to one endpoint.\n\nInserts the event row with ``delivered_at=NOW()`` so the regular fan-out\npass skips it, then inserts a single ``webhook_deliveries`` row pointing\nat this endpoint, and dispatches the worker.",
        "operationId": "fire_test_event_v1_webhook_endpoints__public_id__test_post",
        "parameters": [
          {
            "in": "path",
            "name": "public_id",
            "required": true,
            "schema": {
              "title": "Public Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Fire Test Event V1 Webhook Endpoints  Public Id  Test Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Fire Test Event",
        "tags": [
          "v1"
        ]
      }
    }
  },
  "security": [
    {
      "HTTPBearer": []
    }
  ],
  "servers": [
    {
      "description": "Production",
      "url": "https://thrustlab.com"
    }
  ]
}
