{
  "$defs": {
    "ActiveManifest": {
      "additionalProperties": false,
      "description": "The global active-storms manifest \u2014 written last.\n\n``degraded`` / ``sources_down`` make the entry point self-describing: a reader must be\nable to tell a genuine \"no active storms\" (empty list, not degraded) from an upstream\noutage (possibly empty list, degraded) without a second request (invariant 4).\n\n``overviews`` are the multi-storm maps for the landing view \u2014 the ``global`` frame plus\none per active basin \u2014 so the site can offer region tabs without a second request.\n\n``invests`` are areas of possible formation (NHC GTWO + JTWC ABPW), listed separately\nfrom active storms \u2014 important but categorically distinct from a tracked cyclone.",
      "properties": {
        "degraded": {
          "default": false,
          "title": "Degraded",
          "type": "boolean"
        },
        "generated_at": {
          "format": "date-time",
          "title": "Generated At",
          "type": "string"
        },
        "invests": {
          "default": [],
          "items": {
            "$ref": "#/$defs/InvestSummary"
          },
          "title": "Invests",
          "type": "array"
        },
        "overviews": {
          "default": [],
          "items": {
            "$ref": "#/$defs/OverviewMap"
          },
          "title": "Overviews",
          "type": "array"
        },
        "schema_version": {
          "default": "1.5",
          "title": "Schema Version",
          "type": "string"
        },
        "source_stale_after_seconds": {
          "default": 43200,
          "title": "Source Stale After Seconds",
          "type": "integer"
        },
        "sources_down": {
          "default": [],
          "items": {
            "type": "string"
          },
          "title": "Sources Down",
          "type": "array"
        },
        "stale_after_seconds": {
          "default": 7200,
          "title": "Stale After Seconds",
          "type": "integer"
        },
        "storms": {
          "items": {
            "$ref": "#/$defs/ActiveStormSummary"
          },
          "title": "Storms",
          "type": "array"
        }
      },
      "required": [
        "generated_at",
        "storms"
      ],
      "title": "ActiveManifest",
      "type": "object"
    },
    "ActiveStormSummary": {
      "additionalProperties": false,
      "description": "One active storm's entry in the global manifest (pointer, not products).\n\nCarries its own ``source_stale_after_seconds`` because the global manifest mixes basins:\na single number at the top could only be right for one agency, and ``/health`` judges\nevery storm here against its own.",
      "properties": {
        "advisory_number": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Advisory Number"
        },
        "basin": {
          "title": "Basin",
          "type": "string"
        },
        "final_advisory": {
          "default": false,
          "title": "Final Advisory",
          "type": "boolean"
        },
        "forecast_init_time": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Forecast Init Time"
        },
        "issue_ts": {
          "title": "Issue Ts",
          "type": "string"
        },
        "manifest_url": {
          "title": "Manifest Url",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Name"
        },
        "source_issue_time": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source Issue Time"
        },
        "source_retrieved_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source Retrieved At"
        },
        "source_stale_after_seconds": {
          "default": 43200,
          "title": "Source Stale After Seconds",
          "type": "integer"
        },
        "status": {
          "title": "Status",
          "type": "string"
        },
        "storm_id": {
          "title": "Storm Id",
          "type": "string"
        },
        "summary": {
          "anyOf": [
            {
              "$ref": "#/$defs/StormSummary"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "updated_at": {
          "format": "date-time",
          "title": "Updated At",
          "type": "string"
        }
      },
      "required": [
        "storm_id",
        "name",
        "basin",
        "status",
        "issue_ts",
        "manifest_url",
        "updated_at"
      ],
      "title": "ActiveStormSummary",
      "type": "object"
    },
    "ArchiveManifest": {
      "additionalProperties": false,
      "description": "Durable, browseable index of every storm retained by the publisher.",
      "properties": {
        "generated_at": {
          "format": "date-time",
          "title": "Generated At",
          "type": "string"
        },
        "schema_version": {
          "default": "1.5",
          "title": "Schema Version",
          "type": "string"
        },
        "storms": {
          "default": [],
          "items": {
            "$ref": "#/$defs/ArchiveStormSummary"
          },
          "title": "Storms",
          "type": "array"
        }
      },
      "required": [
        "generated_at"
      ],
      "title": "ArchiveManifest",
      "type": "object"
    },
    "ArchiveStormSummary": {
      "additionalProperties": false,
      "description": "Stable public index entry for an active or completed tropical cyclone.\n\n``storm_id`` is the immutable basin/ATCF-number/season identifier and is the\ncanonical route key. Entries are never deleted by normal publishing: when a storm\nleaves the active feed, it becomes archived and keeps pointing at its final manifest.",
      "properties": {
        "active": {
          "title": "Active",
          "type": "boolean"
        },
        "archived_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Archived At"
        },
        "basin": {
          "title": "Basin",
          "type": "string"
        },
        "final_advisory": {
          "default": false,
          "title": "Final Advisory",
          "type": "boolean"
        },
        "first_seen_at": {
          "format": "date-time",
          "title": "First Seen At",
          "type": "string"
        },
        "issue_ts": {
          "title": "Issue Ts",
          "type": "string"
        },
        "last_seen_at": {
          "format": "date-time",
          "title": "Last Seen At",
          "type": "string"
        },
        "manifest_url": {
          "title": "Manifest Url",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Name"
        },
        "status": {
          "title": "Status",
          "type": "string"
        },
        "storm_id": {
          "title": "Storm Id",
          "type": "string"
        },
        "summary": {
          "anyOf": [
            {
              "$ref": "#/$defs/StormSummary"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        }
      },
      "required": [
        "storm_id",
        "name",
        "basin",
        "status",
        "issue_ts",
        "manifest_url",
        "first_seen_at",
        "last_seen_at",
        "active"
      ],
      "title": "ArchiveStormSummary",
      "type": "object"
    },
    "CompactGraphic": {
      "additionalProperties": false,
      "description": "The phone-sized redraw of a graphic: larger type, fewer annotations.\n\nNot a rendition, and deliberately a different object: it is a different *picture* of the\nsame data, drawn from the same canonical snapshot at a frame a phone can read. Type is\nspecified in points and a figure in inches, so every label keeps its share of the frame\nhowever small the file gets \u2014 which means the only way to make a 2400 px graphic legible\nat 320 CSS px is to draw it again with less on it.\n\nIt is offered as art direction (``<source media>``), never as another rung of\n:attr:`PublishedProduct.renditions`: a browser choosing on width alone would happily\nserve this abbreviated picture to a desktop with room for the full one.",
      "properties": {
        "graphic_type": {
          "title": "Graphic Type",
          "type": "string"
        },
        "renditions": {
          "items": {
            "$ref": "#/$defs/Rendition"
          },
          "title": "Renditions",
          "type": "array"
        }
      },
      "required": [
        "graphic_type",
        "renditions"
      ],
      "title": "CompactGraphic",
      "type": "object"
    },
    "ForecastPointSummary": {
      "additionalProperties": false,
      "description": "Accessible forecast-point data, copied from the canonical official forecast.",
      "properties": {
        "max_sustained_wind_kt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Max Sustained Wind Kt"
        },
        "position_lat": {
          "title": "Position Lat",
          "type": "number"
        },
        "position_lon": {
          "title": "Position Lon",
          "type": "number"
        },
        "status": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Status"
        },
        "status_origin": {
          "default": "stated",
          "title": "Status Origin",
          "type": "string"
        },
        "tau": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Tau"
        },
        "valid_time": {
          "format": "date-time",
          "title": "Valid Time",
          "type": "string"
        }
      },
      "required": [
        "valid_time",
        "position_lat",
        "position_lon"
      ],
      "title": "ForecastPointSummary",
      "type": "object"
    },
    "InvestAreas": {
      "additionalProperties": false,
      "description": "``api/v1/invests.geojson`` \u2014 the outlook areas as a GeoJSON FeatureCollection.\n\nAn empty ``features`` list is a real, publishable state (a quiet outlook) and is\nwritten rather than skipped: leaving the previous file in place would keep serving\nyesterday's areas as though they were current, which is the same shape of lie as an\noutage reading as clear skies (invariant 4).",
      "properties": {
        "attribution": {
          "default": "Areas: NOAA/NHC Tropical Weather Outlook",
          "title": "Attribution",
          "type": "string"
        },
        "features": {
          "default": [],
          "items": {
            "$ref": "#/$defs/InvestFeature"
          },
          "title": "Features",
          "type": "array"
        },
        "generated_at": {
          "format": "date-time",
          "title": "Generated At",
          "type": "string"
        },
        "type": {
          "const": "FeatureCollection",
          "default": "FeatureCollection",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "generated_at"
      ],
      "title": "InvestAreas",
      "type": "object"
    },
    "InvestFeature": {
      "additionalProperties": false,
      "description": "One formation-outlook area as a GeoJSON Feature.\n\nModelled rather than hand-built as a dict so it lands in the generated schema like\nevery other published object, and so a malformed ring fails at publish time instead of\nat draw time in somebody's browser.",
      "properties": {
        "geometry": {
          "$ref": "#/$defs/InvestGeometry"
        },
        "id": {
          "title": "Id",
          "type": "string"
        },
        "properties": {
          "$ref": "#/$defs/InvestProperties"
        },
        "type": {
          "const": "Feature",
          "default": "Feature",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "id",
        "geometry",
        "properties"
      ],
      "title": "InvestFeature",
      "type": "object"
    },
    "InvestGeometry": {
      "additionalProperties": false,
      "description": "A GeoJSON Polygon: one closed exterior ring of ``[lon, lat]`` pairs.\n\nPairs, not the canonical ``Position`` objects, because this is a display product read\nby a map library \u2014 and at ~300 points a ring the object form more than doubles the\npayload. Order is ``[lon, lat]``: getting it backwards throws nowhere and silently\ndraws the Atlantic outlook over Somalia.",
      "properties": {
        "coordinates": {
          "items": {
            "items": {
              "maxItems": 2,
              "minItems": 2,
              "prefixItems": [
                {
                  "type": "number"
                },
                {
                  "type": "number"
                }
              ],
              "type": "array"
            },
            "type": "array"
          },
          "title": "Coordinates",
          "type": "array"
        },
        "type": {
          "const": "Polygon",
          "default": "Polygon",
          "title": "Type",
          "type": "string"
        }
      },
      "required": [
        "coordinates"
      ],
      "title": "InvestGeometry",
      "type": "object"
    },
    "InvestProperties": {
      "additionalProperties": false,
      "description": "What the map shows about an area when someone taps it.",
      "properties": {
        "basin": {
          "title": "Basin",
          "type": "string"
        },
        "invest_id": {
          "title": "Invest Id",
          "type": "string"
        },
        "observed_time": {
          "format": "date-time",
          "title": "Observed Time",
          "type": "string"
        },
        "prob_2day": {
          "anyOf": [
            {
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Prob 2Day"
        },
        "prob_7day": {
          "anyOf": [
            {
              "maximum": 100,
              "minimum": 0,
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Prob 7Day"
        },
        "risk_2day": {
          "title": "Risk 2Day",
          "type": "string"
        },
        "risk_7day": {
          "title": "Risk 7Day",
          "type": "string"
        },
        "source": {
          "title": "Source",
          "type": "string"
        }
      },
      "required": [
        "invest_id",
        "basin",
        "source",
        "risk_2day",
        "risk_7day",
        "observed_time"
      ],
      "title": "InvestProperties",
      "type": "object"
    },
    "InvestSummary": {
      "additionalProperties": false,
      "description": "A published invest (area of possible formation), listed separately from storms.\n\nCarries what the site's invest list needs \u2014 id, basin, a representative point, and the\n2-day / 7-day formation probability + risk. The formation *area* polygon is not included\nhere (it is drawn onto the overview map); this keeps ``active.json`` small.",
      "properties": {
        "basin": {
          "title": "Basin",
          "type": "string"
        },
        "guidance": {
          "anyOf": [
            {
              "$ref": "#/$defs/PublishedProduct"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "guidance_latest": {
          "anyOf": [
            {
              "$ref": "#/$defs/PublishedProduct"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "invest_id": {
          "title": "Invest Id",
          "type": "string"
        },
        "observed_time": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Observed Time"
        },
        "position_lat": {
          "title": "Position Lat",
          "type": "number"
        },
        "position_lon": {
          "title": "Position Lon",
          "type": "number"
        },
        "prob_2day": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Prob 2Day"
        },
        "prob_7day": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Prob 7Day"
        },
        "risk_2day": {
          "title": "Risk 2Day",
          "type": "string"
        },
        "risk_7day": {
          "title": "Risk 7Day",
          "type": "string"
        },
        "source": {
          "title": "Source",
          "type": "string"
        }
      },
      "required": [
        "invest_id",
        "basin",
        "source",
        "position_lat",
        "position_lon",
        "risk_2day",
        "risk_7day"
      ],
      "title": "InvestSummary",
      "type": "object"
    },
    "NoticesManifest": {
      "additionalProperties": false,
      "description": "``api/v1/notices.json`` \u2014 the operator's maintenance notices, published to R2 (A17.5).\n\nPublished to the bucket rather than served from the admin service for one reason worth\nstating: **the notice most likely to matter is the one announcing that the machine\npublishing it is broken.** R2 is more available than the VPS, so a notice must not depend on\nthe VPS being up to be seen.\n\nInvariant 4 then falls out for free. The object **always exists**, always carries\n:attr:`generated_at`, and says ``\"notices\": []`` explicitly when there are none \u2014 so a\nreader (and a monitor) can tell \"nothing wrong\" from \"could not fetch\", which are the same\nsilence if the object is simply absent. The consumer treats a failed fetch as unknown and\nshows nothing, and an empty list as the all-clear it is.",
      "properties": {
        "generated_at": {
          "format": "date-time",
          "title": "Generated At",
          "type": "string"
        },
        "notices": {
          "default": [],
          "items": {
            "$ref": "#/$defs/PublishedNotice"
          },
          "title": "Notices",
          "type": "array"
        },
        "schema_version": {
          "default": "1.0",
          "title": "Schema Version",
          "type": "string"
        }
      },
      "required": [
        "generated_at"
      ],
      "title": "NoticesManifest",
      "type": "object"
    },
    "OverviewMap": {
      "additionalProperties": false,
      "description": "A published multi-storm overview map for one region (``global`` or a basin).",
      "properties": {
        "compact": {
          "anyOf": [
            {
              "$ref": "#/$defs/CompactGraphic"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "height_px": {
          "title": "Height Px",
          "type": "integer"
        },
        "label": {
          "title": "Label",
          "type": "string"
        },
        "png_url": {
          "title": "Png Url",
          "type": "string"
        },
        "region": {
          "title": "Region",
          "type": "string"
        },
        "renditions": {
          "default": [],
          "items": {
            "$ref": "#/$defs/Rendition"
          },
          "title": "Renditions",
          "type": "array"
        },
        "webp_url": {
          "title": "Webp Url",
          "type": "string"
        },
        "width_px": {
          "title": "Width Px",
          "type": "integer"
        }
      },
      "required": [
        "region",
        "label",
        "png_url",
        "webp_url",
        "width_px",
        "height_px"
      ],
      "title": "OverviewMap",
      "type": "object"
    },
    "PublishedNotice": {
      "additionalProperties": false,
      "description": "One maintenance notice, as the site reads it \u2014 and no more than that.\n\nDeliberately *not* the stored row. The console's SQLite table also holds ``created_by``,\n``status`` and its timestamps; none of those belong on a public object, so the shape a\nreader consumes carries the message, its window and nothing that names an operator. The\nadmin's writer (`admin/src/notices/model.ts`) is held to this shape by parity test, the\nway ``worker/render-record.ts`` is held to ``RunRecord``.",
      "properties": {
        "body": {
          "title": "Body",
          "type": "string"
        },
        "ends_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Ends At"
        },
        "id": {
          "title": "Id",
          "type": "string"
        },
        "kind": {
          "enum": [
            "info",
            "maintenance",
            "incident"
          ],
          "title": "Kind",
          "type": "string"
        },
        "scope": {
          "default": "all",
          "enum": [
            "all",
            "storms",
            "radar",
            "developers",
            "archive",
            "about",
            "nws"
          ],
          "title": "Scope",
          "type": "string"
        },
        "starts_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Starts At"
        },
        "title": {
          "title": "Title",
          "type": "string"
        }
      },
      "required": [
        "id",
        "kind",
        "title",
        "body"
      ],
      "title": "PublishedNotice",
      "type": "object"
    },
    "PublishedProduct": {
      "additionalProperties": false,
      "description": "One graphic type as published: immutable URLs + verification hash.",
      "properties": {
        "compact": {
          "anyOf": [
            {
              "$ref": "#/$defs/CompactGraphic"
            },
            {
              "type": "null"
            }
          ],
          "default": null
        },
        "graphic_type": {
          "title": "Graphic Type",
          "type": "string"
        },
        "height_px": {
          "title": "Height Px",
          "type": "integer"
        },
        "image_sha256": {
          "pattern": "^[0-9a-f]{64}$",
          "title": "Image Sha256",
          "type": "string"
        },
        "png_url": {
          "title": "Png Url",
          "type": "string"
        },
        "renditions": {
          "default": [],
          "items": {
            "$ref": "#/$defs/Rendition"
          },
          "title": "Renditions",
          "type": "array"
        },
        "sidecar_url": {
          "title": "Sidecar Url",
          "type": "string"
        },
        "webp_url": {
          "title": "Webp Url",
          "type": "string"
        },
        "width_px": {
          "title": "Width Px",
          "type": "integer"
        }
      },
      "required": [
        "graphic_type",
        "png_url",
        "webp_url",
        "sidecar_url",
        "image_sha256",
        "width_px",
        "height_px"
      ],
      "title": "PublishedProduct",
      "type": "object"
    },
    "Rendition": {
      "additionalProperties": false,
      "description": "One delivered size of a published graphic \u2014 its own bytes, hash and sidecar.\n\nA rendition is a *product*, not a hint: it is keyed by issuance, immutable, verified on\nthe way in and traceable through its own sidecar like anything else this pipeline\npublishes (invariant 3). What makes it a rendition rather than a separate graphic is\nonly that it was resampled from a master rather than drawn \u2014 which its sidecar records\nas ``rendition_of``.",
      "properties": {
        "height_px": {
          "title": "Height Px",
          "type": "integer"
        },
        "image_sha256": {
          "pattern": "^[0-9a-f]{64}$",
          "title": "Image Sha256",
          "type": "string"
        },
        "min_label_px": {
          "default": 0,
          "title": "Min Label Px",
          "type": "integer"
        },
        "png_url": {
          "title": "Png Url",
          "type": "string"
        },
        "sidecar_url": {
          "title": "Sidecar Url",
          "type": "string"
        },
        "webp_url": {
          "title": "Webp Url",
          "type": "string"
        },
        "width_px": {
          "title": "Width Px",
          "type": "integer"
        }
      },
      "required": [
        "width_px",
        "height_px",
        "png_url",
        "webp_url",
        "sidecar_url",
        "image_sha256"
      ],
      "title": "Rendition",
      "type": "object"
    },
    "StatusManifest": {
      "additionalProperties": false,
      "description": "Pipeline-health mirror (populated more fully by the Phase 13 pipeline).\n\nWritten at the end of a run, so it describes a run that *finished*. The run in flight \u2014\nand the one that died without finishing \u2014 is in the record under ``ops/runs/``, which is\nwhat `/health` reads; this is the public mirror of the same run, and :attr:`run_id` is\nthe join between them (A16). See :mod:`app.publish.runs` for why the two are separate\nobjects rather than one.",
      "properties": {
        "active_storms": {
          "title": "Active Storms",
          "type": "integer"
        },
        "degraded": {
          "default": false,
          "title": "Degraded",
          "type": "boolean"
        },
        "detail": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Detail"
        },
        "generated_at": {
          "format": "date-time",
          "title": "Generated At",
          "type": "string"
        },
        "last_publish_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Last Publish At"
        },
        "run_finished_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Run Finished At"
        },
        "run_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Run Id"
        },
        "schema_version": {
          "default": "1.5",
          "title": "Schema Version",
          "type": "string"
        }
      },
      "required": [
        "generated_at",
        "active_storms"
      ],
      "title": "StatusManifest",
      "type": "object"
    },
    "StormManifest": {
      "additionalProperties": false,
      "description": "A storm's current issuance and its products (the mutable per-storm pointer).",
      "properties": {
        "advisory_number": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Advisory Number"
        },
        "attribution": {
          "title": "Attribution",
          "type": "string"
        },
        "basin": {
          "title": "Basin",
          "type": "string"
        },
        "current_state_product_id": {
          "default": "unknown",
          "title": "Current State Product Id",
          "type": "string"
        },
        "final_advisory": {
          "default": false,
          "title": "Final Advisory",
          "type": "boolean"
        },
        "forecast": {
          "default": [],
          "items": {
            "$ref": "#/$defs/ForecastPointSummary"
          },
          "title": "Forecast",
          "type": "array"
        },
        "forecast_init_time": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Forecast Init Time"
        },
        "issue_ts": {
          "title": "Issue Ts",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Name"
        },
        "normalize_revision": {
          "default": "",
          "title": "Normalize Revision",
          "type": "string"
        },
        "official_source_url": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Official Source Url"
        },
        "products": {
          "items": {
            "$ref": "#/$defs/PublishedProduct"
          },
          "title": "Products",
          "type": "array"
        },
        "published_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Published At"
        },
        "render_revision": {
          "default": "",
          "title": "Render Revision",
          "type": "string"
        },
        "retained": {
          "default": false,
          "title": "Retained",
          "type": "boolean"
        },
        "retained_reason": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Retained Reason"
        },
        "schema_version": {
          "default": "1.5",
          "title": "Schema Version",
          "type": "string"
        },
        "snapshot_sha256": {
          "pattern": "^[0-9a-f]{64}$",
          "title": "Snapshot Sha256",
          "type": "string"
        },
        "snapshot_url": {
          "title": "Snapshot Url",
          "type": "string"
        },
        "source_issue_time": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Source Issue Time"
        },
        "source_retrieved_at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Source Retrieved At"
        },
        "source_stale_after_seconds": {
          "default": 43200,
          "title": "Source Stale After Seconds",
          "type": "integer"
        },
        "stale_after_seconds": {
          "default": 7200,
          "title": "Stale After Seconds",
          "type": "integer"
        },
        "status": {
          "title": "Status",
          "type": "string"
        },
        "storm_id": {
          "title": "Storm Id",
          "type": "string"
        },
        "summary": {
          "$ref": "#/$defs/StormSummary"
        },
        "updated_at": {
          "format": "date-time",
          "title": "Updated At",
          "type": "string"
        }
      },
      "required": [
        "storm_id",
        "name",
        "basin",
        "status",
        "issue_ts",
        "source_issue_time",
        "updated_at",
        "attribution",
        "snapshot_url",
        "snapshot_sha256",
        "summary",
        "products"
      ],
      "title": "StormManifest",
      "type": "object"
    },
    "StormSummary": {
      "additionalProperties": false,
      "description": "Compact current-state numbers, denormalized from the snapshot.\n\nLets a reader (the website, a consumer app) show intensity/motion without fetching the\nfull snapshot, which carries the whole forecast + model guidance and runs to hundreds of\nkilobytes. Values are the canonical raw units \u2014 wind/gust in knots, pressure in hPa,\nbearing in degrees, speed in knots, position in signed decimal degrees. Presentation\n(mph, Saffir-Simpson category, compass points) is deliberately the reader's job, so this\nstays a data record rather than a rendering. A field is ``null`` when the source omits it.",
      "properties": {
        "gust_kt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Gust Kt"
        },
        "has_cone": {
          "default": false,
          "title": "Has Cone",
          "type": "boolean"
        },
        "max_sustained_wind_kt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Max Sustained Wind Kt"
        },
        "min_pressure_hpa": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Min Pressure Hpa"
        },
        "movement_bearing_deg": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Movement Bearing Deg"
        },
        "movement_speed_kt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Movement Speed Kt"
        },
        "peak_forecast_wind_kt": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Peak Forecast Wind Kt"
        },
        "position_lat": {
          "title": "Position Lat",
          "type": "number"
        },
        "position_lon": {
          "title": "Position Lon",
          "type": "number"
        },
        "wind_radii": {
          "default": [],
          "items": {
            "$ref": "#/$defs/WindRadiiSummary"
          },
          "title": "Wind Radii",
          "type": "array"
        }
      },
      "required": [
        "position_lat",
        "position_lon"
      ],
      "title": "StormSummary",
      "type": "object"
    },
    "WindRadiiSummary": {
      "additionalProperties": false,
      "description": "Source-reported wind-field extent at one threshold, by quadrant, in nautical miles.\n\nPublished because its **absence** is a statement a reader has to be able to make. A page\nthat shows a forecast track and says nothing about the wind field invites the single most\ncommon misreading of a tropical graphic \u2014 that the line, or the cone around it, is the\nsize of the storm. Saying \"the source reported none\" needs the empty list to be a\npublished fact rather than a field nobody thought to send.\n\nA quadrant is ``null`` when the source did not report that direction, which is\nmeaningfully different from ``0`` (winds reported, radius zero) \u2014 the same distinction\n:class:`~app.models.cyclone.QuadrantRadii` keeps canonically. Nothing here is\ninterpolated, buffered or inferred: it is the centre's own numbers or it is absent.",
      "properties": {
        "ne_nm": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Ne Nm"
        },
        "nw_nm": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Nw Nm"
        },
        "se_nm": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Se Nm"
        },
        "sw_nm": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Sw Nm"
        },
        "threshold_kt": {
          "title": "Threshold Kt",
          "type": "integer"
        }
      },
      "required": [
        "threshold_kt"
      ],
      "title": "WindRadiiSummary",
      "type": "object"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "The static JSON objects served under api/v1/. See /docs.html.",
  "title": "Maverick Wx published API",
  "version": "1.5",
  "x-endpoints": {
    "api/v1/active.json": "ActiveManifest",
    "api/v1/archive.json": "ArchiveManifest",
    "api/v1/invests.geojson": "InvestAreas",
    "api/v1/notices.json": "NoticesManifest",
    "api/v1/status.json": "StatusManifest",
    "api/v1/storms/<storm_id>.json": "StormManifest"
  }
}
