{
  "openapi": "3.1.0",
  "info": {
    "title": "Yagra northbound API",
    "description": "The REST surface of Yagra-core: inventory, metrics, alerts, passive events and configuration.\n\nThis document is generated from the Rust handlers — it is the contract, not a description of one.",
    "contact": {
      "name": "horryworks"
    },
    "license": {
      "name": "AGPL-3.0-only",
      "identifier": "AGPL-3.0-only"
    },
    "version": "0.2.1"
  },
  "paths": {
    "/api/v1/alerts": {
      "get": {
        "tags": [
          "alerts"
        ],
        "operationId": "list_alerts",
        "responses": {
          "200": {
            "description": "Every active alert, each decorated with its inbound ack state",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ActiveAlertView"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/ack": {
      "post": {
        "tags": [
          "alerts"
        ],
        "operationId": "ack_alert",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AckRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The ack was recorded (or cleared) and broadcast",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AckResult"
                }
              }
            }
          },
          "400": {
            "description": "Neither `node` nor a readable `subject` was supplied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the alert-acknowledgement permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The subject is outside the caller's group scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no ack store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/calendar": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Alert fires bucketed weekday×hour over the last `days` (for the calendar heatmap).",
        "operationId": "alert_calendar",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Weekday×hour fire counts; empty when this deployment keeps no history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CalendarBucket"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/history": {
      "get": {
        "tags": [
          "alerts"
        ],
        "operationId": "list_alert_history",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of history rows, newest first; empty when this deployment keeps no history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertHistoryView"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`before` is not an RFC 3339 timestamp",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/top-nodes": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Nodes generating the most alert fires over a trailing window (chronic offenders).",
        "operationId": "alert_top_nodes",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Nodes ranked by alert fires; empty when this deployment keeps no history, and `partial` says the scope filter may have shortened the list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ranked_AlertNodeCount"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/transitions": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Recent up/down transitions (latest fires and resolutions), node names joined.",
        "description": "Only `limit` is documented, though the handler borrows the history query type: this endpoint\nreads no cursor, and advertising one would promise paging it does not do.",
        "operationId": "alert_transitions",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "How many transitions to return (default 12)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The latest fires and resolutions; empty when this deployment keeps no history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertTransition"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/findings": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "Findings across every run — the Saved-findings screen.",
        "description": "Complements `GET /analysis/jobs/{id}/findings`, which answers \"what did this run find\". This one\nanswers the question an operator actually starts from — \"has anything been found about this node\n/ this site / this week\" — which no single run can answer because the runs are what get\nenumerated otherwise.\n\nSkeleton mode has no job store, so it answers an empty list rather than a 503: the screen is a\nsearch, and an error where \"nothing yet\" is the truthful answer reads as a broken page.",
        "operationId": "saved_findings",
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "description": "Page cursor: the `at` of the previous page's last row (RFC 3339).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before_id",
            "in": "query",
            "description": "Page cursor tiebreak: that same row's `id`. Findings written by one run share a millisecond\nroutinely, so a cursor without it would repeat or skip the rows sharing the boundary\ninstant. Omitting it reads as \"strictly before this instant\".",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Inclusive lower bound on finding time, RFC 3339 — the range filter, not the cursor.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tool",
            "in": "query",
            "description": "Restrict to one diagnostic (an `AnalysisTool` token, e.g. `anomaly`).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "severity",
            "in": "query",
            "description": "Restrict to `crit`, `warn` or `info`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "description": "Restrict to findings about one node.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "group_id",
            "in": "query",
            "description": "Restrict to findings about nodes in one folder group **and everything beneath it**.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size, clamped to 200 (default 100).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching findings, newest first; empty when this deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SavedFinding"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A cursor or range bound is not RFC 3339, or the tool/severity is unknown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The requested node or group filter is outside the caller's scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/jobs": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "Recent analysis jobs (the runs list). `?limit=` (default 50).",
        "description": "Skeleton mode has no runner, so this answers an empty list rather than a 503: the runs list is\na panel on a page that otherwise works, and an error there would break the page.",
        "operationId": "list_analysis_jobs",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent runs, newest first; empty when this deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AnalysisJob"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "analysis"
        ],
        "summary": "Launch a background analysis job (operator+).",
        "operationId": "create_analysis_job",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAnalysisJob"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The queued job row; it progresses over `/api/v1/stream/analysis`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalysisJob"
                }
              }
            }
          },
          "400": {
            "description": "Unknown tool, unknown scope kind, or a group/node scope with no `scope_id`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Operator",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "The runner is at its concurrency or rate limit — retryable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/jobs/{id}": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "One analysis job by id.",
        "operationId": "get_analysis_job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Analysis job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job row, including its state and progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalysisJob"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such job — also the answer when this deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/jobs/{id}/cancel": {
      "post": {
        "tags": [
          "analysis"
        ],
        "summary": "Cancel a running analysis job (operator+). The task observes the flag between phases.",
        "operationId": "cancel_analysis_job",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Analysis job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The run was flagged for cancellation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Cancelled"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Operator",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No job by that id is currently running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/jobs/{id}/findings": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "A job's findings (the report list). Empty in skeleton mode.",
        "operationId": "analysis_findings",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Analysis job id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The run's findings; empty for a job that has not succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AnalysisFinding"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/schedules": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "Every analysis schedule, soonest first. Empty in skeleton mode.",
        "operationId": "list_analysis_schedules",
        "responses": {
          "200": {
            "description": "Every schedule the caller may see; empty when this deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AnalysisSchedule"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "analysis"
        ],
        "summary": "Create an analysis schedule (operator+).",
        "operationId": "create_analysis_schedule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnalysisScheduleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Schedule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Unknown tool or cadence, a group/node scope with no `scope_id`, or a flow analysis on a deployment with no flow store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Operator, or a fleet-wide schedule from a group-scoped account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The named node or group is outside the caller's scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analysis/schedules/{id}": {
      "put": {
        "tags": [
          "analysis"
        ],
        "summary": "Update a schedule. Recomputes `next_run_at` from the new cadence, so an edit takes effect at the\nnext matching instant rather than whenever the old one happened to be.",
        "operationId": "update_analysis_schedule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Analysis schedule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnalysisScheduleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Schedule updated"
          },
          "400": {
            "description": "Unknown tool or cadence, a group/node scope with no `scope_id`, or a flow analysis on a deployment with no flow store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Operator, or a fleet-wide schedule from a group-scoped account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such schedule, or it is outside the caller's scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "analysis"
        ],
        "summary": "Delete a schedule (operator+).",
        "operationId": "delete_analysis_schedule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Analysis schedule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Schedule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Operator",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such schedule, or it is outside the caller's scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-tokens": {
      "get": {
        "tags": [
          "api-tokens"
        ],
        "summary": "Every issued personal access token, as metadata.",
        "description": "Neither the raw token nor its hash is returned — a token's value exists only in the response\nthat created it. These credentials authenticate whichever surfaces each token names — `/mcp`,\nthis REST API, or both.",
        "operationId": "list_api_tokens",
        "responses": {
          "200": {
            "description": "Token metadata only — never the raw token or its hash",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiTokenInfo"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no token store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "api-tokens"
        ],
        "summary": "Mint a personal access token.",
        "description": "The raw token is in this response and nowhere else — only its hash is stored, so no later call\ncan produce it again.\n\nThe token acts as an **account** (`owner_user_id`, defaulting to the caller): disabling or\ndeleting that account stops the token, and its role is capped at the owner's current role on\nevery use. For anything unattended, own it with a service account rather than a person — see\n`POST /api/v1/users` — so the credential does not depend on who happened to create it.",
        "operationId": "create_api_token",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiTokenBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Token minted; `token` is the raw bearer and is returned only here",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedApiToken"
                }
              }
            }
          },
          "400": {
            "description": "Bad name, a scope naming no groups or a group that does not exist, a scope on a token whose owner is itself group-scoped, no surface named, an expiry already in the past, or an owner id that names no account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "An API token with that name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no token store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-tokens/{id}": {
      "delete": {
        "tags": [
          "api-tokens"
        ],
        "summary": "Revoke a personal access token, so it stops authenticating every surface immediately.",
        "description": "Idempotent: a missing or already-revoked id answers `204` too. Revocation is what an operator\nreaches for when a token may be compromised, so \"it was already gone\" is success, not `404`.",
        "operationId": "revoke_api_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "API token id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Token revoked; idempotent, so an already-revoked id also answers 204"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no token store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit": {
      "get": {
        "tags": [
          "audit"
        ],
        "operationId": "list_audit",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of audit rows, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`before` is not an RFC 3339 timestamp",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view-audit permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode keeps no audit log",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "tags": [
          "session"
        ],
        "summary": "Exchange a username and password for a bearer token.",
        "description": "Takes `Admin` with no permission guard in front of it — unlike every other handler — because\nthere is nothing to authenticate yet. A skeleton deployment answering 503 here is correct and\nnot a disclosure: \"there is no user store\" is exactly what a would-be logger-in needs to know.",
        "operationId": "login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "A bearer token and the role it carries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginOk"
                }
              }
            }
          },
          "401": {
            "description": "Incorrect username or password — one code for both, so the endpoint is not an account-enumeration oracle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts; `Retry-After` carries the wait in seconds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no user store, so there is nothing to log in to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/auth/logout": {
      "post": {
        "tags": [
          "session"
        ],
        "summary": "Revoke the caller's bearer token so it cannot be reused.",
        "description": "Idempotent and unguarded: an absent, expired or already-revoked token still answers 204. Making\nlogout require a valid session would mean the one action that fixes a suspect token is refused\nprecisely when the token has gone bad.",
        "operationId": "logout",
        "responses": {
          "204": {
            "description": "Token revoked; an absent, expired or already-revoked token answers 204 too"
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/auth/me": {
      "get": {
        "tags": [
          "session"
        ],
        "summary": "Who the bearer token belongs to. [`Caller`] does the work: it demands a real session (not open\nin public-dashboard mode, since an anonymous visitor has no identity to report).",
        "operationId": "auth_me",
        "responses": {
          "200": {
            "description": "The bearer holder's role and username",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthMe"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token — closed even on a public dashboard",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/oidc/authorize": {
      "get": {
        "tags": [
          "oidc"
        ],
        "summary": "Begin an OIDC login: the IdP authorization URL the browser should be sent to. The CSRF `state`,\n`nonce` and PKCE verifier are stashed server-side for the flight. Unauthenticated (pre-session).",
        "operationId": "oidc_authorize",
        "responses": {
          "200": {
            "description": "The IdP authorization URL the browser should be sent to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorizeUrl"
                }
              }
            }
          },
          "502": {
            "description": "Provider discovery or configuration failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "No OIDC provider store, or no provider enabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/auth/oidc/callback": {
      "post": {
        "tags": [
          "oidc"
        ],
        "summary": "Complete an OIDC login: exchange the code, validate the ID token, map IdP groups to a role,\nJIT-provision the account, and issue a Yagra session.",
        "operationId": "oidc_callback",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcCallbackBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "A Yagra session for the SSO account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OidcSession"
                }
              }
            }
          },
          "401": {
            "description": "The login could not be completed; which step failed stays server-side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "No OIDC provider store, no provider enabled, or skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/classification-rules": {
      "get": {
        "tags": [
          "classification"
        ],
        "operationId": "list_classification_rules",
        "responses": {
          "200": {
            "description": "Every rule, in evaluation order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ClassificationRule"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "classification"
        ],
        "operationId": "create_classification_rule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClassificationRuleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Rule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The rule matches nothing, the prefix is not a dotted OID, the regex does not compile, or the profile does not exist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/classification-rules/{id}": {
      "put": {
        "tags": [
          "classification"
        ],
        "operationId": "update_classification_rule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClassificationRuleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Rule updated"
          },
          "400": {
            "description": "The submitted rule is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "classification"
        ],
        "operationId": "delete_classification_rule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Rule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collection-templates": {
      "get": {
        "tags": [
          "collection"
        ],
        "operationId": "list_collection_templates",
        "responses": {
          "200": {
            "description": "Every collection template with its item count",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "collection"
        ],
        "operationId": "create_collection_template",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTemplate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Template created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The template name is blank",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "A template with that name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collection-templates/{id}": {
      "delete": {
        "tags": [
          "collection"
        ],
        "operationId": "delete_collection_template",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Collection template id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Template deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such template",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collection-templates/{id}/items": {
      "get": {
        "tags": [
          "collection"
        ],
        "operationId": "list_template_items",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Collection template id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The template's items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateItem"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "collection"
        ],
        "operationId": "create_template_item",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Collection template id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCollectionItem"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Item created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The metric name is not an identifier, the OID is not dotted-numeric, or collection/metric_kind is out of vocabulary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collection-templates/{id}/items/{item_id}": {
      "delete": {
        "tags": [
          "collection"
        ],
        "operationId": "delete_template_item",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Collection template id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "item_id",
            "in": "path",
            "description": "Item id within that template",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Item deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such item in that template",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/collection/{item_id}": {
      "delete": {
        "tags": [
          "collection"
        ],
        "operationId": "delete_collection_item",
        "parameters": [
          {
            "name": "item_id",
            "in": "path",
            "description": "Collection item id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Item deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such collection item",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/config": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Tells the WebUI whether reads are open and whether login is available, so it can decide up front\nwhether to gate behind a login screen. Intentionally unauthenticated — see the module doc.",
        "operationId": "get_config",
        "responses": {
          "200": {
            "description": "Client bootstrap config — no secrets. Unauthenticated by design",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientConfig"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      },
      "put": {
        "tags": [
          "health"
        ],
        "summary": "Update the global default polling interval. The scheduler re-reads it each round, so a change\napplies on the next poll round without a restart.",
        "operationId": "update_config",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfigBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "New default applied from the next poll round"
          },
          "400": {
            "description": "The interval is outside the configured bounds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has nowhere to persist the default",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/config/bundle": {
      "get": {
        "tags": [
          "config"
        ],
        "operationId": "export_bundle",
        "responses": {
          "200": {
            "description": "The deployment's monitoring configuration as a portable bundle. Carries no secrets — credentials, channel configs and ingest tokens stay in this deployment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfigBundle"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "A table holds more rows than one bundle carries; use a database dump for a deployment this size",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "config"
        ],
        "summary": "Apply a bundle. Existing rows with the same id are updated, new ones created; nothing is ever\ndeleted, and there is no replace mode.",
        "operationId": "import_bundle",
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "description": "Run the whole import and roll it back, returning the report it would have produced.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfigBundle"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Import report: per-table counts plus what was skipped or changed and why. With `dry_run` nothing was committed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportReport"
                }
              }
            }
          },
          "400": {
            "description": "Not a Yagra configuration bundle, or a schema version this build cannot read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "The uploaded bundle is larger than the accepted body size",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credentials": {
      "get": {
        "tags": [
          "credentials"
        ],
        "operationId": "list_credentials",
        "responses": {
          "200": {
            "description": "Credential metadata only — the secret is never returned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CredentialSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role does not hold ManageCredentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "credentials"
        ],
        "operationId": "create_credential",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCredential"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Credential sealed and stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "A missing field, or a secret that does not parse for its kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role does not hold ManageCredentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credentials/health": {
      "get": {
        "tags": [
          "credentials"
        ],
        "summary": "Report whether every stored credential can still be decrypted.",
        "description": "This is the check a restore cannot skip. A database can come back whole — right row counts,\nhealthy API — while the key-encryption key is a different one, in which case every credential is\npermanently unreadable and nothing says so until the next poll fails. `scripts/yagra-restore-verify.sh`\nasserts on this endpoint for exactly that reason, and it is worth looking at after any KEK\nrotation or restore.\n\nIt decrypts in memory and reports booleans; no secret value crosses this boundary.",
        "operationId": "credential_health",
        "responses": {
          "200": {
            "description": "Per-credential decryptability. `failures` is empty on a healthy deployment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialHealth"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageCredentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Credential storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/credentials/{id}": {
      "put": {
        "tags": [
          "credentials"
        ],
        "operationId": "update_credential",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Credential id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCredential"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Credential updated; an omitted secret is a rename, not a clear"
          },
          "400": {
            "description": "An empty name, a secret without its kind, or a secret that does not parse for its kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role does not hold ManageCredentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "credentials"
        ],
        "operationId": "delete_credential",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Credential id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Credential deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role does not hold ManageCredentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such credential",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard": {
      "get": {
        "tags": [
          "dashboard"
        ],
        "summary": "The caller's saved layout, or JSON `null` when they have never saved one — an explicit null\nrather than 404, so the client falls back to its default layout instead of showing an error.",
        "operationId": "get_dashboard",
        "responses": {
          "200": {
            "description": "The caller's opaque layout document, or JSON null when they have never saved one",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "No valid bearer token — the layout is keyed by account, so this stays closed in public-dashboard mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "dashboard"
        ],
        "summary": "Save (replace) the caller's layout. Mutating, so `audit_mw` records it automatically.",
        "operationId": "put_dashboard",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Layout saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardSaved"
                }
              }
            }
          },
          "400": {
            "description": "The layout is not a JSON object",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token — the layout is keyed by account, so this stays closed in public-dashboard mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The session's account no longer exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "The layout exceeds the document size cap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovered-endpoints": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Addresses seen on the network that Yagra does not monitor.",
        "description": "Built from the ARP / IPv6-neighbour caches of the nodes that *are* monitored, so an endpoint\nappears here only if some monitored router has spoken to it. Requires the ARP walk to be enabled\n(Settings ▸ System settings ▸ Discovery walks); with it off the list is empty, which is an answer\nrather than an outage.\n\n`summary.truncated_nodes > 0` means at least one router's cache exceeded its row budget and this\nlist is a **sample**, not a complete inventory of the segment.",
        "operationId": "list_discovered_endpoints",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "via_node",
            "in": "query",
            "description": "Only endpoints seen by this node.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "include_promoted",
            "in": "query",
            "description": "Include endpoints that have since become monitored nodes. Default `false`.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "before_last_seen",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of unmonitored endpoints, most recently seen first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoveredEndpointPage"
                }
              }
            }
          },
          "400": {
            "description": "before_last_seen and before_id must be given together, and before_last_seen must be RFC 3339",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovered-endpoints/{id}/import": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Promote a discovered endpoint to a monitored node.",
        "description": "Builds the same `NewNode` a scan import does and goes through the same writer, so classification\n(`sysDescr` → maker/model) happens on the node's first identity probe exactly as it does for any\nother node — there is no second creation path to keep in step.\n\n`409` means the address is already an inventory node. That is not a failure of the import so much\nas an answer: the endpoint stopped being unmonitored between the list being read and the button\nbeing pressed, and the row is reconciled on the way out so the list stops showing it.",
        "operationId": "import_discovered_endpoint",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Discovered-endpoint id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportEndpoint"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "The endpoint is now a monitored node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportResult"
                }
              }
            }
          },
          "400": {
            "description": "A binding id that is not a UUID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such discovered endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "That address is already a monitored node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/candidates": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Recent discovered (unclassified) devices across in-memory scans — the dashboard \"discovery\nqueue\".",
        "description": "`View`, unlike the rest of this module, because it reports what has been seen rather than\ncausing anything to happen. Empty in skeleton mode: with no discovery runner there are genuinely\nno candidates, which is an answer rather than an outage.",
        "operationId": "discovery_candidates",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent unclassified devices; empty in skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Candidate"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/import": {
      "post": {
        "tags": [
          "discovery"
        ],
        "operationId": "import_discovered",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportDiscovered"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Nodes created, in one transaction",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportResult"
                }
              }
            }
          },
          "400": {
            "description": "An unparseable address, an empty name, or a binding id that is not a UUID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/scan": {
      "post": {
        "tags": [
          "discovery"
        ],
        "operationId": "start_discovery_scan",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartScan"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Sweep accepted; poll its status by id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedScan"
                }
              }
            }
          },
          "400": {
            "description": "No targets or more than the cap, an unparseable address, or a named credential that is missing or unusable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/scan/{id}": {
      "get": {
        "tags": [
          "discovery"
        ],
        "operationId": "get_discovery_scan",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Scan id returned when the sweep was accepted",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Progress and the candidates found so far",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanStatus"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such scan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dns-monitors": {
      "post": {
        "tags": [
          "checks"
        ],
        "operationId": "create_dns_monitor",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDnsMonitor"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Monitor node created and bound to the built-in DNS profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The name is empty, the DNS check is not usable, or the pool name is not a legal subject token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-rules": {
      "get": {
        "tags": [
          "events"
        ],
        "operationId": "list_event_rules",
        "responses": {
          "200": {
            "description": "Every stored event rule",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StoredEventRule"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "events"
        ],
        "operationId": "create_event_rule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventRuleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Rule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "A pattern does not compile, or a field is outside its accepted range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-rules/test": {
      "post": {
        "tags": [
          "events"
        ],
        "summary": "Try a pattern against a sample message.",
        "description": "A read wearing POST — it compiles a regex and returns, changing nothing — so it is on\n`changes_monitoring_config`'s exception list and does not dirty the config generation.",
        "operationId": "test_event_rule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventRuleTest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Whether the sample matched; a pattern that does not compile is reported in-band",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuleTestResult"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-rules/{id}": {
      "put": {
        "tags": [
          "events"
        ],
        "operationId": "update_event_rule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventRuleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Rule updated"
          },
          "400": {
            "description": "A pattern does not compile, or a field is outside its accepted range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such event rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "events"
        ],
        "operationId": "delete_event_rule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Rule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such event rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-sources": {
      "get": {
        "tags": [
          "events"
        ],
        "operationId": "list_event_sources",
        "responses": {
          "200": {
            "description": "Every ingest source (never the token hash)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EventSourceView"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "events"
        ],
        "operationId": "create_event_source",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateEventSource"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Source created; the plaintext ingest token appears here only",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedSource"
                }
              }
            }
          },
          "400": {
            "description": "Name is empty or over 120 characters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-sources/{id}": {
      "put": {
        "tags": [
          "events"
        ],
        "operationId": "update_event_source",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event source id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateEventSource"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Source updated"
          },
          "400": {
            "description": "Name is empty or over 120 characters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such event source",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "events"
        ],
        "operationId": "delete_event_source",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event source id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Source deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such event source",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/event-sources/{id}/rotate-token": {
      "post": {
        "tags": [
          "events"
        ],
        "operationId": "rotate_event_source_token",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Event source id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A new ingest token; the plaintext is readable here only",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotatedToken"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such event source",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/events": {
      "get": {
        "tags": [
          "eventlog"
        ],
        "operationId": "list_events",
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start",
            "in": "query",
            "description": "Time-range lower bound (inclusive, RFC 3339). Distinct from `before` (the paging cursor).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "description": "Time-range upper bound (inclusive, RFC 3339).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "matched",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Free-text matched against source (node name / IP) or message. With `regex`, it is instead a\nregular expression matched against the message only.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "regex",
            "in": "query",
            "description": "Interpret `q` as a regular expression (message-only) rather than a plain term.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching events, newest first, from whichever store is the source of record",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EventRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`before` is not RFC 3339, a range bound is malformed, the kind is unknown, or the regex does not compile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side to resolve node names against",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/events/stats": {
      "get": {
        "tags": [
          "eventlog"
        ],
        "summary": "Fleet passive-event summary aggregates for the dashboard widgets.",
        "description": "Categorical (`group_by=kind|action|trap|source`) returns count-ordered buckets; `group_by=time`\nreturns a volume series. Routes to the same store the event log does, so a summary and the list\nit summarises can never disagree about which store answered.",
        "operationId": "events_stats",
        "parameters": [
          {
            "name": "start",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "node_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "matched",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "regex",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "group_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "bucket_secs",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "split",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A volume series for `group_by=time`, count-ordered buckets otherwise",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventStats"
                }
              }
            }
          },
          "400": {
            "description": "A range bound is malformed, the kind is unknown, the regex does not compile, or `group_by` is not one of kind|action|trap|source|time",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side to resolve node names against",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fleet/coverage": {
      "get": {
        "tags": [
          "fleet"
        ],
        "summary": "Which nodes have (not) reported ICMP within the freshness window — low coverage means the\nmonitoring itself is missing data. Admin-only data source (full inventory).",
        "operationId": "fleet_coverage",
        "responses": {
          "200": {
            "description": "Fresh vs total node counts plus the capped stale watchlist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetCoverage"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no inventory to measure coverage against",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fleet/group-summary": {
      "get": {
        "tags": [
          "fleet"
        ],
        "summary": "Per-group health rollup for the site-matrix / region-rollup / geo-map widgets.",
        "description": "View-gated and works without the admin store — the node→group map comes from the shared\n`NodeListing`. The client joins these counts to the bounded group tree for names and geo, and\nsums descendants for the region rollup.",
        "operationId": "fleet_group_summary",
        "responses": {
          "200": {
            "description": "Per-group direct-member state tallies, keyed by group id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetGroupSummary"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fleet/state-history": {
      "get": {
        "tags": [
          "fleet"
        ],
        "summary": "The fleet health timeline (stacked/line chart). Admin-only data source.",
        "operationId": "fleet_state_history",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One aligned series per state on a shared timestamp axis",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetStateHistory"
                }
              }
            }
          },
          "400": {
            "description": "`to` precedes `from`, or the window exceeds 90 days",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode keeps no state-history snapshots",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fleet/summary": {
      "get": {
        "tags": [
          "fleet"
        ],
        "summary": "Fleet-wide status summary, computed server-side from the live alert engine (S12).",
        "description": "View-gated and works without the admin store, so a public dashboard can render its\nstatus-summary / health-ring / nodes-down widgets.",
        "operationId": "fleet_summary",
        "responses": {
          "200": {
            "description": "Total node count plus a tally carrying all six states",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FleetSummary"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/conversations": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_conversations",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source→destination pairs ranked by traffic, AS names resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowConversation"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/protocols": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_protocols",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "IP protocols ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowProtoAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/series": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_series",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Traffic trend: bytes and packets per protocol per 5-minute bucket",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/top-as": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_top_as",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Autonomous systems ranked by traffic, names resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowAsAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/top-ports": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_top_ports",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Destination ports ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowPortAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/flow/top-talkers": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_flow_top_talkers",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Host addresses ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowTalker"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/forwarding/destinations": {
      "get": {
        "tags": [
          "forwarding"
        ],
        "operationId": "list_forward_destinations",
        "responses": {
          "200": {
            "description": "Every destination, without its stored secret",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ForwardDestination"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no destination store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "forwarding"
        ],
        "operationId": "create_forward_destination",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForwardDestinationBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Destination created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Edge validation rejected the destination (target, kind pairing, filter, certificate, credential, rate limit, or the destination cap)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "A destination with that name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no destination store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/forwarding/destinations/{id}": {
      "put": {
        "tags": [
          "forwarding"
        ],
        "operationId": "update_forward_destination",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Destination id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForwardDestinationBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Destination updated; an omitted secret keeps the stored one"
          },
          "400": {
            "description": "Edge validation rejected the destination (target, kind pairing, filter, certificate, credential, or rate limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such destination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "A destination with that name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no destination store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "forwarding"
        ],
        "operationId": "delete_forward_destination",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Destination id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Destination deleted, or was already gone"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no destination store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/forwarding/destinations/{id}/test": {
      "post": {
        "tags": [
          "forwarding"
        ],
        "summary": "Send one synthetic message to a destination and report what happened.",
        "description": "Deliberately independent of the running senders, so a still-disabled destination can be\nvalidated before it is switched on — and so the caller gets the transport error itself rather\nthan \"check the logs\".",
        "operationId": "test_forward_destination",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Destination id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The probe ran; `delivered` says whether it arrived",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestResult"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such destination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no destination store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/forwarding/status": {
      "get": {
        "tags": [
          "forwarding"
        ],
        "summary": "Live forwarding status: per-destination counters plus any online poller that cannot supply the\noriginal bytes, so a byte-exact destination silently degrading is visible in the UI.",
        "operationId": "forwarding_status",
        "responses": {
          "200": {
            "description": "Per-destination counters and the pollers that cannot feed them",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForwardingStatus"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no forwarder",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ingest/webhook/{source_id}": {
      "post": {
        "tags": [
          "events"
        ],
        "summary": "Machine-scoped webhook ingest.",
        "description": "Authenticated by the per-source bearer token rather than a session — see the module doc. The\nthree token outcomes are deliberately distinct: a wrong token is `401 bad_token`, an unknown or\ndisabled source is `404`, and a source over its rate is `429`. A sender needs to tell \"fix my\ntoken\" from \"that source is gone\" from \"slow down\".",
        "operationId": "ingest_webhook",
        "parameters": [
          {
            "name": "source_id",
            "in": "path",
            "description": "Webhook source id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "description": "Arbitrary sender payload; a JSON object's message/text/summary becomes the event text",
          "content": {
            "application/json": {
              "schema": {
                "type": "string"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Event accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IngestedEvent"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong per-source ingest token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No enabled webhook source with that id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "Body over the per-request ingest cap"
          },
          "429": {
            "description": "This source is over its ingest rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Event ingestion is not configured, or this core is not the HA leader",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/llm/config": {
      "get": {
        "tags": [
          "rca"
        ],
        "summary": "The active provider's configuration — never the credential.",
        "operationId": "get_llm_config",
        "responses": {
          "200": {
            "description": "The stored configuration (or null) and the provider choices",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LlmConfigResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no configuration store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "rca"
        ],
        "summary": "Create or replace the provider configuration.",
        "operationId": "put_llm_config",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LlmConfigInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Configuration saved; an omitted `api_key` keeps the stored one"
          },
          "400": {
            "description": "A field of the configuration is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no configuration store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/llm/test": {
      "post": {
        "tags": [
          "rca"
        ],
        "summary": "Send one minimal prompt to the configured provider.",
        "description": "Deliberately ignores `enabled`: validating a provider *before* switching it on is the whole point\nof the button (the same reasoning as the forwarding-destination test).",
        "operationId": "test_llm_provider",
        "responses": {
          "200": {
            "description": "The probe ran; `ok` says whether the provider answered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LlmTestResult"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no provider to test",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/maintenance-windows": {
      "get": {
        "tags": [
          "maintenance"
        ],
        "operationId": "list_maintenance_windows",
        "responses": {
          "200": {
            "description": "Every maintenance window",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StoredWindow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "maintenance"
        ],
        "operationId": "create_maintenance_window",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWindow"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Window created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name/scope_id, an unknown scope_level, or bounds that are not RFC 3339 or end at or before they start",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageMaintenance permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "A group_id scope naming a group that does not exist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/maintenance-windows/{id}": {
      "put": {
        "tags": [
          "maintenance"
        ],
        "operationId": "set_maintenance_window_enabled",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Maintenance window id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnabledBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Window enabled or disabled"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageMaintenance permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such maintenance window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "maintenance"
        ],
        "operationId": "delete_maintenance_window",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Maintenance window id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Window deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageMaintenance permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such maintenance window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/import": {
      "post": {
        "tags": [
          "meraki"
        ],
        "summary": "Import selected devices as nodes, atomically.",
        "description": "Already-imported serials are skipped rather than rejected, so re-running the wizard after a\npartial selection does the obvious thing instead of erroring on the ones already there.",
        "operationId": "import_meraki_devices",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiImportReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "How many devices became nodes; already-imported serials are skipped",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerakiImported"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs": {
      "get": {
        "tags": [
          "meraki"
        ],
        "operationId": "list_meraki_orgs",
        "responses": {
          "200": {
            "description": "Every onboarded organization; the credential reference is not included",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MerakiOrgView"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "meraki"
        ],
        "summary": "Onboard one or more organizations under a single read-only API key.",
        "description": "The key is validated by listing orgs, then sealed **once** as a shared credential — each org row\nholds a reference plus its own org id. Onboarding twenty orgs therefore stores one secret, not\ntwenty copies of the same one.\n\nA per-org create failure is logged and skipped rather than failing the batch: the count says how\nmany landed, and retrying is harmless.",
        "operationId": "create_meraki_orgs",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMerakiOrgsReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "How many organizations the batch created; a per-org failure is skipped, not fatal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerakiCreated"
                }
              }
            }
          },
          "400": {
            "description": "The key or org list is empty, or base_url is not an https allow-listed Meraki host",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "The Dashboard API rejected the key or was unreachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/discover": {
      "post": {
        "tags": [
          "meraki"
        ],
        "summary": "List the organizations an API key can access, so the operator can multi-select which to monitor.\nRead-only upstream (`GET /organizations`) and persists nothing.",
        "operationId": "meraki_discover",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiDiscoverReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The organizations the key can access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MerakiOrgOption"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The key is empty, or base_url is not an https allow-listed Meraki host",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "The Dashboard API call failed; the detail is logged, never returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/{id}": {
      "delete": {
        "tags": [
          "meraki"
        ],
        "summary": "Delete an organization: removes its device nodes, config, and folder tree.",
        "operationId": "delete_meraki_org",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Organization, its device nodes and its folder tree removed"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/{id}/cadence": {
      "put": {
        "tags": [
          "meraki"
        ],
        "summary": "Update an org's per-tier cadence, enabled tiers, and rate budget.",
        "operationId": "set_meraki_org_cadence",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiCadenceReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Cadence, enabled tiers and rate budget updated"
          },
          "400": {
            "description": "A cadence value is outside its band, target_rps is outside the cap, or a tier is unknown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/{id}/enabled": {
      "put": {
        "tags": [
          "meraki"
        ],
        "summary": "Enable/disable an org — pauses collection without losing its config or history.",
        "operationId": "set_meraki_org_enabled",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiEnabledReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Collection paused or resumed; config and history are kept"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/{id}/enumerate": {
      "post": {
        "tags": [
          "meraki"
        ],
        "summary": "Enumerate an org's networks and devices from the Dashboard API, for the import wizard.",
        "description": "Read-only upstream. It upserts the network scope (**preserving monitored flags** — re-enumerating\nmust not silently un-watch networks an operator chose) and returns the devices not already\nimported.",
        "operationId": "enumerate_meraki_org",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The org's networks and the devices not already imported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerakiEnumeration"
                }
              }
            }
          },
          "400": {
            "description": "The org's stored API key could not be resolved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "The Dashboard API call failed; the detail is logged, never returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/orgs/{id}/networks": {
      "get": {
        "tags": [
          "meraki"
        ],
        "summary": "The org's networks with their monitored (in-scope) flag.",
        "operationId": "list_meraki_networks",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The org's known networks and whether each is in scope",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MerakiNetworkView"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "meraki"
        ],
        "summary": "Set the monitored (watch/skip) flag for a set of the org's networks.",
        "operationId": "set_meraki_networks_monitored",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Organization row id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiMonitoredReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Network scope updated"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/meraki/polling": {
      "get": {
        "tags": [
          "meraki"
        ],
        "operationId": "get_meraki_polling",
        "responses": {
          "200": {
            "description": "Whether Meraki collection is running at all",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerakiPolling"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "meraki"
        ],
        "summary": "Set the global kill switch — the one control that instantly halts all Meraki collection without\nlosing any configuration, for when the Dashboard API budget needs to be given back at once.",
        "operationId": "set_meraki_polling",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerakiPollingReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Collection halted or resumed globally; no configuration is lost"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/metrics/interface-delta": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Interfaces whose total throughput moved the most vs `window` ago — spikes (`up`) or drops\n(`down`). `value` is the signed delta in bits/sec.",
        "operationId": "interface_delta",
        "parameters": [
          {
            "name": "direction",
            "in": "query",
            "description": "`up` (spikes) | `down` (drops).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "window",
            "in": "query",
            "description": "Comparison window in seconds (default 300 = now vs 5m ago).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Interfaces ranked by signed throughput delta (bits/sec); `partial` says the scope filter may have shortened the list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ranked_InterfaceTopEntry"
                }
              }
            }
          },
          "400": {
            "description": "`direction` is not 'up' or 'down'",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/metrics/interface-heatmap": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Busiest-links × time heatmap: picks the top interfaces by current throughput, then returns each\nlink's throughput (bits/sec) over time on a shared timestamp axis.",
        "operationId": "interface_heatmap",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "step",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A links × time throughput grid on one shared timestamp axis",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterfaceHeatmap"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/metrics/interface-top": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Fleet-wide busiest/erroring interfaces. Ranks `(node,ifindex)` by a query-time rate, then joins\nnode + interface names (and speed) from PostgreSQL.",
        "operationId": "interface_top",
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "description": "`throughput` | `in_bps` | `out_bps` | `errors` | `discards`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agg",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The busiest or most-erroring interfaces, ranked; `partial` says the scope filter may have shortened the list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ranked_InterfaceTopEntry"
                }
              }
            }
          },
          "400": {
            "description": "`metric` is not one of throughput|in_bps|out_bps|errors|discards, or `agg` is unsupported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/metrics/throughput-range": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Fleet aggregate ingress/egress (bits/sec) over time.",
        "operationId": "throughput_range",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "step",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fleet ingress and egress aligned on one timestamp axis",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThroughputRange"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/metrics/top": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Fleet-wide Top-N for a metric: the highest-value nodes right now (or by hourly peak). Powers\nthe dashboard \"Top RTT / CPU / memory / …\" widgets from one endpoint.",
        "operationId": "top_metrics",
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "description": "Metric to rank by (validated identifier, or a logical alias).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agg",
            "in": "query",
            "description": "`now` (default) ⇒ most recent value; `max_1h` ⇒ trailing-hour peak.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "How many nodes to return (default 5, clamped 1..=50).",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The highest-value nodes, ranked; `partial` says the scope filter may have shortened the list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ranked_TopEntry"
                }
              }
            }
          },
          "400": {
            "description": "`metric` is neither a logical alias nor an identifier, or `agg` is unsupported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/mib-catalog": {
      "get": {
        "tags": [
          "mib"
        ],
        "operationId": "list_mib_catalog",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum entries to return (1–2000, default 2000).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching catalog entries, or the whole catalog when no term is given, capped at `limit` (1–2000, default 2000)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MibEntry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "mib"
        ],
        "operationId": "create_mib_entry",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMibEntry"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Entry added to the catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The metric name is not an identifier, the OID is not dotted-numeric, or collection/metric_kind is outside its vocabulary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "An entry already claims that metric name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/mib-catalog/{id}": {
      "delete": {
        "tags": [
          "mib"
        ],
        "operationId": "delete_mib_entry",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Catalog entry id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Entry removed"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such entry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitoring-gaps": {
      "get": {
        "tags": [
          "pollers"
        ],
        "summary": "Recent core↔poller visibility outages (Phase 3, store-and-forward). Newest first, capped. A read\nerror degrades to an empty list rather than failing the Pollers page.",
        "operationId": "list_monitoring_gaps",
        "responses": {
          "200": {
            "description": "Recent core↔poller visibility outages, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MonitoringGapRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no durable poller store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/mutes": {
      "get": {
        "tags": [
          "maintenance"
        ],
        "operationId": "list_mutes",
        "responses": {
          "200": {
            "description": "Every mute",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StoredMute"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "maintenance"
        ],
        "operationId": "create_mute",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMute"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Mute created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "An unknown scope_kind, an invalid metric_name, or an `until` that is not RFC 3339 or is already in the past",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the AckAlerts permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "A group scope naming a group that does not exist",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/mutes/{id}": {
      "delete": {
        "tags": [
          "maintenance"
        ],
        "operationId": "delete_mute",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Mute id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Mute deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the AckAlerts permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such mute",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-groups": {
      "get": {
        "tags": [
          "groups"
        ],
        "operationId": "list_node_groups",
        "responses": {
          "200": {
            "description": "Every folder group in the inventory tree",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/GroupSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "groups"
        ],
        "operationId": "create_node_group",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Group created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name, unknown group type, or an invalid pool name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-groups/{id}": {
      "put": {
        "tags": [
          "groups"
        ],
        "operationId": "update_node_group",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Group updated"
          },
          "400": {
            "description": "Empty name, unknown group type, an invalid pool name, or a move that would nest the group inside its own subtree",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "groups"
        ],
        "operationId": "delete_node_group",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Group deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-groups/{id}/geo": {
      "put": {
        "tags": [
          "groups"
        ],
        "operationId": "set_node_group_geo",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupGeo"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Map pin set or cleared"
          },
          "400": {
            "description": "Only one of latitude/longitude given, or a coordinate out of range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-groups/{id}/placement": {
      "put": {
        "tags": [
          "groups"
        ],
        "operationId": "place_group",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupPlacement"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Group re-parented and re-ordered"
          },
          "400": {
            "description": "Both before and after given, or a move that would nest the group inside its own subtree",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-groups/{id}/pool": {
      "put": {
        "tags": [
          "groups"
        ],
        "summary": "Set just the folder's pool. Every node beneath it that has no pool of its own follows on the\nnext sweep (see `poolres`).",
        "operationId": "set_node_group_pool",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Group id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PoolAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Folder pool set or cleared"
          },
          "400": {
            "description": "Pool name too long or containing characters outside letters, digits, '_' and '-'",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such group",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/node-names": {
      "post": {
        "tags": [
          "nodes"
        ],
        "summary": "Resolve a batch of node ids to their display names. The shared `useEntityNames` resolver, and\nany table rendering a node reference by id, use this so names resolve across the **whole**\nfleet: the old path resolved against the first page of `list_nodes` (default 100), so a\nreference to the 101st node silently degraded to a raw UUID.",
        "operationId": "node_names_batch",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeNamesReq"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The resolved names; an id with no row is omitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NodeNameEntry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes": {
      "get": {
        "tags": [
          "nodes"
        ],
        "operationId": "list_nodes",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One keyset page of the inventory, or a single capped page in search mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodePage"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "nodes"
        ],
        "operationId": "create_node",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateNode"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Node created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name, an address that is not an IP, or an illegal pool name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/by-group": {
      "get": {
        "tags": [
          "nodes"
        ],
        "summary": "A group's direct members for the lazy inventory tree: the nodes whose `group_id` is exactly\n`group` (or the ungrouped bucket), in tree order, capped. Loaded on demand when a group is\nexpanded, so the initial page never pulls the whole fleet — it fetches the group skeleton plus\nper-group counts (`/fleet/group-summary`) and streams members per open group.",
        "operationId": "list_group_nodes",
        "parameters": [
          {
            "name": "group",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The group's direct members in tree order, flagged if capped",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupNodes"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/search": {
      "get": {
        "tags": [
          "nodes"
        ],
        "summary": "Server-side node search for the node-picker typeahead: case-insensitive substring over name or\naddress, capped, so a picker never loads the whole inventory into the browser (ui-conventions:\nsearch is server-side at fleet scale). Also backs the Nodes tree name filter and the\nTroubleshoot scope picker. Routes through the shared `NodeListing`, so it works in skeleton mode.",
        "operationId": "search_nodes",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching nodes, capped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NodeSearchResult"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}": {
      "get": {
        "tags": [
          "nodes"
        ],
        "operationId": "get_node",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's configuration, bindings and resolved kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeDetail"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node, or this deployment has no inventory",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "nodes"
        ],
        "operationId": "delete_node",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Node deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/assignment": {
      "get": {
        "tags": [
          "pollers"
        ],
        "summary": "Which pool a node effectively belongs to and which poller is currently polling it.",
        "operationId": "node_assignment",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's effective pool, where it came from, and its owning poller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeAssignment"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no inventory to resolve the node against",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/bindings": {
      "put": {
        "tags": [
          "nodes"
        ],
        "operationId": "set_node_bindings",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeBindings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Bindings updated"
          },
          "400": {
            "description": "Illegal pool name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/collection": {
      "get": {
        "tags": [
          "collection"
        ],
        "summary": "A node's collection items: its own overrides, or — with `?resolved=true` — the effective set\nafter the profile's defaults are overridden by them. The resolved view is what the poller sees.",
        "operationId": "list_node_collection",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "resolved",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's own stored items, or — with `?resolved=true` — the effective set the poller sees, which carries no item ids",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeCollection"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node (resolved view only)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "collection"
        ],
        "operationId": "create_node_collection",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCollectionItem"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Item created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The metric name is not an identifier, the OID is not dotted-numeric, or collection/metric_kind is out of vocabulary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/dns-chain": {
      "get": {
        "tags": [
          "checks"
        ],
        "operationId": "get_dns_chain",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's current resolution chain and how long it has held",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DnsChainCurrent"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No resolution has been recorded for the node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/dns-chain/history": {
      "get": {
        "tags": [
          "checks"
        ],
        "operationId": "list_dns_chain_history",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "before_at",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of chain changes, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DnsChainHistory"
                }
              }
            }
          },
          "400": {
            "description": "before_at and before_id must be given together, and before_at must be RFC 3339",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/dns-check": {
      "get": {
        "tags": [
          "checks"
        ],
        "operationId": "get_dns_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's DNS-check configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DnsCheckConfig"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The node carries no DNS check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "checks"
        ],
        "operationId": "set_dns_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DnsCheckConfig"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "DNS check stored, with the name normalized"
          },
          "400": {
            "description": "The DNS name, resolver address, port, depth or timeout is not usable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "The node is already a monitor of another kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "checks"
        ],
        "operationId": "delete_dns_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "DNS check removed; the node and its recorded chains are untouched"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The node carries no DNS check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/conversations": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_conversations",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Source→destination pairs ranked by traffic, AS names resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowConversation"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/protocols": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_protocols",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "IP protocols ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowProtoAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/series": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_series",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Traffic trend: bytes and packets per protocol per 5-minute bucket",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowPoint"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/top-as": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_top_as",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Autonomous systems ranked by traffic, names resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowAsAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/top-ports": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_top_ports",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Destination ports ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowPortAgg"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/flow/top-talkers": {
      "get": {
        "tags": [
          "flow"
        ],
        "operationId": "get_node_flow_top_talkers",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Exporter node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "proto",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "port",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "peer",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asn",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Host addresses ranked by traffic",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FlowTalker"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Flow monitoring is not enabled (no flow store configured)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/group": {
      "put": {
        "tags": [
          "nodes"
        ],
        "operationId": "set_node_group",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeGroupAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Node moved in the folder tree"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/interfaces": {
      "get": {
        "tags": [
          "collection"
        ],
        "summary": "Interfaces discovered on a node, with query-time utilization.",
        "description": "`View`, not `ManageConfig` — unlike the rest of this module. An interface list is device state\nan operator reads, not a setting they author. Skeleton mode answers an empty list rather than\n503: the interface inventory is PostgreSQL-only, so \"none known\" is the truthful answer.",
        "operationId": "list_node_interfaces",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Interfaces known for this node with query-time utilization; empty in skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/InterfaceRow"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/interfaces/{ifindex}/series": {
      "get": {
        "tags": [
          "metrics"
        ],
        "operationId": "get_interface_series",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ifindex",
            "in": "path",
            "description": "SNMP ifIndex of the interface",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "step",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "In/out throughput and error rates on one shared timestamp axis",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterfaceSeries"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/metrics": {
      "get": {
        "tags": [
          "metrics"
        ],
        "summary": "Every metric this node is configured to collect or has data for, with the status of each.",
        "description": "Answers what there is to look at for a node, including metrics that come from its checks rather\nthan from a collection set and so appear in no collection listing.",
        "operationId": "list_node_metrics",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "within_secs",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's metrics, name-ordered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NodeMetricEntry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/metrics/{metric}": {
      "get": {
        "tags": [
          "metrics"
        ],
        "operationId": "get_node_metric",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "metric",
            "in": "path",
            "description": "Metric name — a Prometheus identifier",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agg",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The latest sample for that series",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetricReading"
                }
              }
            }
          },
          "400": {
            "description": "The metric name is not an identifier, or `agg` is unsupported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The node is not collecting that series",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/metrics/{metric}/range": {
      "get": {
        "tags": [
          "metrics"
        ],
        "operationId": "get_node_metric_range",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "metric",
            "in": "path",
            "description": "Metric name — a Prometheus identifier",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "step",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          },
          {
            "name": "agg",
            "in": "query",
            "description": "`max` ⇒ node-level aggregate of a per-entity table gauge; absent ⇒ scalar node series.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate",
            "in": "query",
            "description": "`true` ⇒ per-second rate of a counter series instead of its stored values. Cannot be\ncombined with `agg`.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The window's points; empty when the slice has no samples",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetricRange"
                }
              }
            }
          },
          "400": {
            "description": "The metric name is not an identifier, `agg` is unsupported, or `rate` and `agg` were combined",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/neighbors": {
      "get": {
        "tags": [
          "neighbors"
        ],
        "summary": "The node's current CDP/LLDP neighbours.",
        "description": "`404` means no walk has recorded anything for this node yet — the node may not be an SNMP\ndevice, may not speak either protocol, or may simply not have been walked since collection was\nenabled. It is distinct from a recorded **empty** set, which is a real answer meaning the device\nreports no neighbours.",
        "operationId": "get_neighbors",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's current adjacency and how long it has held",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CurrentNeighbors"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No adjacency has been recorded for the node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/neighbors/history": {
      "get": {
        "tags": [
          "neighbors"
        ],
        "summary": "The node's adjacency change history, newest first.",
        "description": "A row is written only when the adjacency actually changed, so a quiet rack produces none. The\ncontent key deliberately excludes the agent's own churn (LLDP's `TimeMark` and remote index), so\na row here means a port genuinely started or stopped facing something, or the peer on it changed.",
        "operationId": "list_neighbor_history",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "before_at",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of adjacency changes, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NeighborHistory"
                }
              }
            }
          },
          "400": {
            "description": "before_at and before_id must be given together, and before_at must be RFC 3339",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/parent": {
      "put": {
        "tags": [
          "nodes"
        ],
        "operationId": "set_node_parent",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeParentAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Dependency edge set or cleared"
          },
          "400": {
            "description": "Self-dependency, a parent that does not exist, or an edge that would close a cycle",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/placement": {
      "put": {
        "tags": [
          "nodes"
        ],
        "operationId": "place_node",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodePlacement"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Node repositioned"
          },
          "400": {
            "description": "Both `before` and `after` were given",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/poll": {
      "post": {
        "tags": [
          "nodes"
        ],
        "summary": "`ManageConfig` — an operator action, like a discovery scan. Audited by the mutation middleware.\n`202` because the poll is dispatched, not finished, when this returns.",
        "operationId": "poll_node_now",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Jobs dispatched to the node's effective pool",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PollNowResult"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/pool": {
      "put": {
        "tags": [
          "nodes"
        ],
        "summary": "`PUT /api/v1/nodes/:node_id/pool` — set just the node's own pool.",
        "description": "Deliberately **not** folded into [`set_node_bindings`]: that handler overwrites\nprofile/credential/vendor/model unconditionally (only its `pool` is three-state-gated), so a\npool-only caller going through it would silently blank all four.",
        "operationId": "set_node_pool",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PoolAssignment"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Pool set, or cleared back to inherited"
          },
          "400": {
            "description": "Illegal pool name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/status": {
      "get": {
        "tags": [
          "nodes"
        ],
        "operationId": "get_node_status",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's display state and the alerts attributed to it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NodeStatus"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/suppression-opt-out": {
      "put": {
        "tags": [
          "nodes"
        ],
        "summary": "Exclude a node from derived alert suppression, or put it back.",
        "description": "An excluded node keeps its place in the connectivity graph — everything behind it still resolves\nthrough it — but is given no upstream of its own, so its alert is never rolled up under\nsomething else. Use it for the one box that must page whatever else is happening.\n\nThis only ever *removes* suppression, so it cannot cause an outage to go unreported. It has no\neffect while the deployment is on the hand-authored graph.",
        "operationId": "set_node_suppression_opt_out",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NodeSuppressionOptOut"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "The exclusion was set or cleared"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/nodes/{node_id}/url-check": {
      "get": {
        "tags": [
          "checks"
        ],
        "operationId": "get_url_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The node's URL-check configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UrlCheckConfig"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The node carries no URL check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "checks"
        ],
        "operationId": "set_url_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UrlCheckConfig"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "URL check stored"
          },
          "400": {
            "description": "The URL is malformed, not http(s), or points at a blocked address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "The node is already a monitor of another kind",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "checks"
        ],
        "operationId": "delete_url_check",
        "parameters": [
          {
            "name": "node_id",
            "in": "path",
            "description": "Node id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "URL check removed; the node itself is untouched"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "The node carries no URL check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notification-channels": {
      "get": {
        "tags": [
          "notifications"
        ],
        "operationId": "list_notification_channels",
        "responses": {
          "200": {
            "description": "Every channel, without its sealed connection config",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ChannelSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "notifications"
        ],
        "operationId": "create_notification_channel",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateChannel"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Channel created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name, or a connection config whose URL fails the SSRF / vendor-allowlist check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notification-channels/preview": {
      "post": {
        "tags": [
          "notifications"
        ],
        "summary": "Render a template against a representative alert, without saving anything.",
        "description": "A template is code that first runs during an outage, so being able to see its output while\nwriting it is part of the feature rather than a convenience. Takes no channel id, so a template\ncan be checked before the channel it belongs to exists.\n\nProblems come back **in the 200 response**, not as a 400: they are notes about the text being\ntyped, and a failed request would render as \"the preview is broken\" instead.",
        "operationId": "preview_notification_template",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "What this template would send; a template that cannot be used is reported in-band alongside the built-in text that would go instead",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreviewResult"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notification-channels/template-variables": {
      "get": {
        "tags": [
          "notifications"
        ],
        "summary": "Every variable a notification template can reference.",
        "description": "Served rather than documented so the editor's list and the renderer's context cannot disagree —\nthey are the same list.",
        "operationId": "list_template_variables",
        "responses": {
          "200": {
            "description": "The template variables, with what each one means and whether every alert carries it",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateVariable"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notification-channels/{id}": {
      "put": {
        "tags": [
          "notifications"
        ],
        "operationId": "set_notification_channel_enabled",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnabledBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Channel enabled or disabled"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such channel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "notifications"
        ],
        "operationId": "delete_notification_channel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Channel deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such channel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notification-channels/{id}/template": {
      "put": {
        "tags": [
          "notifications"
        ],
        "summary": "Replace a channel's notification template.",
        "description": "A template that does not compile is rejected here rather than at delivery time — the operator is\nstill looking at the field. The renderer additionally falls back to the built-in format if a\nstored template fails while an alert is being sent, so a broken template can never swallow a\nnotification.",
        "operationId": "set_notification_template",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Channel id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Template saved (or cleared, restoring the built-in wording)"
          },
          "400": {
            "description": "The template does not compile, or is longer than the accepted maximum",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such channel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "serve_document",
        "responses": {
          "200": {
            "description": "This document",
            "content": {
              "application/json": {}
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/api/v1/poller-health": {
      "get": {
        "tags": [
          "pollers"
        ],
        "summary": "Poll-loop self-monitoring: last sweep time, jobs dispatched last round, total results consumed.\nThe \"stat strip\" of the poller & collection-health widget.",
        "operationId": "poller_health",
        "responses": {
          "200": {
            "description": "Poll-loop counters since core started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SchedulerStatsSnapshot"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side to read the scheduler from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pollers": {
      "get": {
        "tags": [
          "pollers"
        ],
        "summary": "The registered poller fleet plus the per-pool summary.",
        "operationId": "list_pollers",
        "responses": {
          "200": {
            "description": "Every known poller (live ∪ durable inventory) and the per-pool summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PollersResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no poller inventory",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pollers/{id}": {
      "delete": {
        "tags": [
          "pollers"
        ],
        "summary": "Remove a decommissioned poller from the durable inventory.",
        "description": "A currently-online poller is refused: deleting it would achieve nothing, because it re-registers\non its next heartbeat. Better to say so than to appear to work.",
        "operationId": "delete_poller",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Poller id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Poller removed from the durable inventory"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such poller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "The poller is online and would re-register on its next heartbeat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no durable poller store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pollers/{id}/anchor": {
      "put": {
        "tags": [
          "pollers"
        ],
        "summary": "Name the node a poller attaches to, rooting the derived dependency graph.",
        "description": "Direction in the derived graph comes from distance to a poller, so core has to know where each\npoller sits. It works that out from the addresses the poller reports — but a poller running in a\ncontainer reports a container-network address that matches no monitored node, which is the\ncommon case rather than the unusual one. This is how an operator says where it really is.\n\nUntil every pool that has nodes has a placed poller, derived suppression cannot be enabled.",
        "operationId": "set_poller_anchor",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Poller id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PollerAnchorRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "The anchor was set or cleared"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageConfig permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such poller, or no such node",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no durable poller store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pollers/{id}/nodes": {
      "get": {
        "tags": [
          "pollers"
        ],
        "summary": "The nodes a poller currently holds, for the Pollers-page drill-down.",
        "description": "Served from the coordinator's published working set rather than a database query, so this and\nthe node detail's \"Polled by\" read the same data and can never disagree.",
        "operationId": "poller_nodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Poller id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The poller's published working set, capped to one page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PollerNodesResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no coordinator to read the working set from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pools": {
      "get": {
        "tags": [
          "nodes"
        ],
        "summary": "`GET /api/v1/pools` — the pools that exist, for the assignment picker. Names only, no telemetry.",
        "description": "Deliberately separate from `GET /pollers`, which scans the whole node table to build its\nper-pool counts; this is two indexed `DISTINCT`s and is loaded by an ordinary page.",
        "operationId": "list_pools",
        "responses": {
          "200": {
            "description": "The pools on offer, default first, each flagged with whether a live poller serves it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PoolOptions"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the View permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profiles": {
      "get": {
        "tags": [
          "profiles"
        ],
        "operationId": "list_profiles",
        "responses": {
          "200": {
            "description": "Every device profile",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProfileSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "profiles"
        ],
        "operationId": "create_profile",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Profile created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name, unknown category, or an out-of-bounds poll interval",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profiles/{id}": {
      "put": {
        "tags": [
          "profiles"
        ],
        "operationId": "update_profile",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Profile id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Profile updated"
          },
          "400": {
            "description": "Empty name, unknown category, or an out-of-bounds poll interval",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "profiles"
        ],
        "operationId": "delete_profile",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Profile id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Profile deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profiles/{id}/templates": {
      "get": {
        "tags": [
          "collection"
        ],
        "operationId": "list_profile_templates",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Device profile id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The templates attached to this profile",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "collection"
        ],
        "operationId": "set_profile_templates",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Device profile id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetProfileTemplates"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "The profile's attached templates now are exactly `template_ids`"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rca": {
      "post": {
        "tags": [
          "rca"
        ],
        "summary": "Generate (or serve from cache) an explanation of one incident.",
        "operationId": "create_rca",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RcaBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The explanation and the evidence it was grounded in",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RcaReport"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the AckAlerts permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No incident matches that node and check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "429": {
            "description": "Rate or concurrency cap reached; carries `Retry-After`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "The provider failed or the model refused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode, or no LLM provider configured / configured wrongly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/definitions": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "All report definitions. Empty in skeleton mode — \"no templates\" is the truth when there is no\ndatabase, and the builder renders its empty state rather than an error.",
        "operationId": "list_report_definitions",
        "responses": {
          "200": {
            "description": "Every report definition; empty in skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReportDefinition"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "reports"
        ],
        "operationId": "create_report_definition",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportDefinitionBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The created definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportDefinition"
                }
              }
            }
          },
          "400": {
            "description": "The name is blank, the spec is not an object, or it names a section kind this build cannot render",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "The spec exceeds the shared JSON-document cap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/definitions/{id}": {
      "put": {
        "tags": [
          "reports"
        ],
        "operationId": "update_report_definition",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report definition id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportDefinitionBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Definition updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok_"
                }
              }
            }
          },
          "400": {
            "description": "The name is blank, the spec is not an object, or it names a section kind this build cannot render",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "The spec exceeds the shared JSON-document cap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "reports"
        ],
        "summary": "Delete a definition. Schedules cascade; **saved runs are kept** with a null `definition_id` — a\ngenerated report is evidence of what the fleet looked like, and deleting the template it came\nfrom should not destroy that.",
        "operationId": "delete_report_definition",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report definition id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Definition deleted; its schedules cascade, its saved runs are kept"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/definitions/{id}/run": {
      "post": {
        "tags": [
          "reports"
        ],
        "summary": "Generate a report from a definition now. Returns the run row immediately; it progresses over SSE.",
        "operationId": "run_report_definition",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report definition id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The freshly created run, still generating",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportRun"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/runs": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "Saved runs, newest first. Empty in skeleton mode.",
        "operationId": "list_report_runs",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Saved runs, newest first; empty in skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReportRun"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/runs/{id}": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "One run with its rendered result (the viewer).",
        "operationId": "get_report_run",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report run id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The run with its rendered result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportRunDetail"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such run, or skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "reports"
        ],
        "operationId": "delete_report_run",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report run id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Run deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such run",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/runs/{id}/export": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "Download a saved run as HTML / CSV / PDF.",
        "description": "Returns a raw `Response` rather than `Json<T>` — the body is a file with its own content type\nand `Content-Disposition`, which is exactly the case `Json` cannot express.\n\nHTML and CSV are rendered from the stored result; PDF is produced on demand. The run must have\nsucceeded: an unfinished or failed run has no rendered result, and that is a `409` (come back\nlater) rather than a 404 (it does not exist).",
        "operationId": "export_report_run",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report run id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The rendered report as an attachment, per `format`",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              },
              "application/pdf": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`format` is not html|csv|pdf",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such run, or skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "The run has no rendered result yet (still running or failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "PDF rendering is not available on this server",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/schedules": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "All schedules. Empty in skeleton mode.",
        "operationId": "list_report_schedules",
        "responses": {
          "200": {
            "description": "Every schedule; empty in skeleton mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReportSchedule"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "reports"
        ],
        "operationId": "create_report_schedule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportScheduleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Schedule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "`frequency` is not daily|weekly|monthly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/schedules/{id}": {
      "put": {
        "tags": [
          "reports"
        ],
        "summary": "Update a schedule. Recomputes `next_run_at` from the new cadence, so an edit takes effect at the\nnext fire rather than at the old one.",
        "operationId": "update_report_schedule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report schedule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportScheduleBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Schedule updated and `next_run_at` recomputed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok_"
                }
              }
            }
          },
          "400": {
            "description": "`frequency` is not daily|weekly|monthly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such schedule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "reports"
        ],
        "operationId": "delete_report_schedule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Report schedule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Schedule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such schedule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/sections": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "The section catalog that drives the builder. Static, so it answers fully in skeleton mode.",
        "operationId": "list_report_sections",
        "responses": {
          "200": {
            "description": "Every section kind this build can render",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SectionDef"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/roles": {
      "get": {
        "tags": [
          "users"
        ],
        "summary": "The permission catalogue plus, for each role, what it grants.",
        "description": "Only `View`, unlike the rest of this module: it is the *shape* of the permission model, not\nanyone's account. Derived from `Permission::ALL` and `Role::ALL` rather than listed here, so a\nnew permission appears in the matrix without anyone remembering to add it.",
        "operationId": "list_roles",
        "responses": {
          "200": {
            "description": "The permission catalogue and what each role grants",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RolesMatrix"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/routing-rules": {
      "get": {
        "tags": [
          "notifications"
        ],
        "operationId": "list_routing_rules",
        "responses": {
          "200": {
            "description": "Every routing rule and the channels it fans out to",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RoutingRule"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "notifications"
        ],
        "operationId": "create_routing_rule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateRule"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Rule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty name, or a severity outside critical|warning|info|null",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/routing-rules/{id}": {
      "put": {
        "tags": [
          "notifications"
        ],
        "operationId": "set_routing_rule_enabled",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Routing rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnabledBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Rule enabled or disabled"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "notifications"
        ],
        "operationId": "delete_routing_rule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Routing rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Rule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/ldap": {
      "get": {
        "tags": [
          "ldap"
        ],
        "summary": "The stored directory configuration — never the bind password.",
        "operationId": "get_ldap_config",
        "responses": {
          "200": {
            "description": "The directory configuration, or null when none is saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LdapConfigResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the user-administration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no directory store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "ldap"
        ],
        "summary": "Save the directory configuration.",
        "operationId": "put_ldap_config",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LdapConfigInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Saved"
          },
          "400": {
            "description": "The configuration is not usable; the message names the field",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the user-administration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no directory store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/ldap/test": {
      "post": {
        "tags": [
          "ldap"
        ],
        "summary": "Exercise the **saved** configuration against the directory.",
        "operationId": "test_ldap_config",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LdapTestBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "How far the check got; a failed stage is reported here, not as an error status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LdapTestResult"
                }
              }
            }
          },
          "400": {
            "description": "No directory configuration has been saved yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the user-administration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no directory store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/neighbors": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "The deployment's adjacency-collection settings, with the accepted cadence range.",
        "operationId": "get_adjacency_settings",
        "responses": {
          "200": {
            "description": "Whether adjacency is collected, how often, and the accepted range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NeighborConfig"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Change whether and how often adjacency is collected.",
        "description": "Applies from the next scheduler sweep. Turning collection off stops issuing walks but keeps\neverything already recorded — the current set and the change history are unaffected.",
        "operationId": "update_neighbor_settings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NeighborConfig"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Settings updated; the change applies from the next scheduler sweep"
          },
          "400": {
            "description": "The cadence is outside the allowed range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/oidc": {
      "get": {
        "tags": [
          "oidc"
        ],
        "summary": "Configured providers — **metadata only**, never the client secret.",
        "operationId": "list_oidc_providers",
        "responses": {
          "200": {
            "description": "Every configured provider, without its client secret",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OidcProviderSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageUsers permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment does not persist SSO configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "oidc"
        ],
        "operationId": "create_oidc_provider",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcProviderInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Provider created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The provider definition is invalid, or the client secret is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageUsers permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment does not persist SSO configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/oidc/{id}": {
      "put": {
        "tags": [
          "oidc"
        ],
        "operationId": "update_oidc_provider",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Provider id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcProviderInput"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Provider updated; an omitted client secret keeps the stored one"
          },
          "400": {
            "description": "The provider definition is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageUsers permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such provider",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment does not persist SSO configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "oidc"
        ],
        "operationId": "delete_oidc_provider",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Provider id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Provider deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the ManageUsers permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such provider",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment does not persist SSO configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/retention": {
      "get": {
        "tags": [
          "settings"
        ],
        "operationId": "get_retention",
        "responses": {
          "200": {
            "description": "The deployment's retention policy: editable windows plus the full table, including rows set by a store's own start flag",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionPolicy"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Update the retention windows. Applies immediately: the PostgreSQL prune loops re-read the policy\non their next tick, and the flow store's table TTL is altered before this returns.",
        "operationId": "update_retention",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetentionValues"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Retention updated. Lowering a window deletes data older than it on the next prune"
          },
          "400": {
            "description": "A window is outside the allowed range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "502": {
            "description": "The flow store rejected the retention change; nothing was saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/tls": {
      "get": {
        "tags": [
          "tls"
        ],
        "summary": "The certificate the WebUI is serving. Never includes the private key.",
        "operationId": "get_web_tls",
        "responses": {
          "200": {
            "description": "The current certificate, or null if none has been established yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebTlsResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-configuration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no certificate store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "tls"
        ],
        "summary": "Import a certificate and its private key.",
        "operationId": "put_web_tls",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebTlsImport"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Imported and live; the body is the new certificate's details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebTlsResponse"
                }
              }
            }
          },
          "400": {
            "description": "The pair is not usable; the message says which of the checks it failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-configuration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no certificate store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/tls/regenerate": {
      "post": {
        "tags": [
          "tls"
        ],
        "summary": "Generate a new self-signed certificate, replacing whatever is being served.",
        "operationId": "regenerate_web_tls",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebTlsRegenerate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Generated and live; the body is the new certificate's details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebTlsResponse"
                }
              }
            }
          },
          "400": {
            "description": "A supplied name is not a usable hostname or IP address",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-configuration permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no certificate store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/topology": {
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Choose which dependency graph drives alert suppression.",
        "description": "`manual` uses each node's hand-authored parent. `shadow` changes nothing about alerting and only\nmakes the comparison at `GET /api/v1/topology/shadow` meaningful. `derived` hands suppression to\nthe graph derived from CDP/LLDP adjacency and shared subnets.\n\nMoving to `derived` is **refused** while any pool that has nodes has a poller whose location\ncould not be resolved: such a pool contributes no roots, so none of its nodes would ever be\nsuppressed — the change would look like it worked and quietly do nothing.",
        "operationId": "set_topology_mode",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopologyModeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "The mode was changed"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-config permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "`derived` was requested while a pool with nodes has an unplaced poller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/shared-dashboard": {
      "get": {
        "tags": [
          "dashboard"
        ],
        "summary": "The global Shared Dashboard layout, or JSON `null` when no admin has saved one. Open-read like\nthe other dashboard data, so it works in public-dashboard mode; the write side is not.",
        "operationId": "get_shared_dashboard",
        "responses": {
          "200": {
            "description": "The global opaque layout document, or JSON null when no admin has saved one",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "dashboard"
        ],
        "summary": "Save (replace) the global layout — **admin only**: it applies to every user.",
        "description": "Takes `RequireManageConfig` *and* [`Caller`]: the first decides whether the write is allowed, the\nsecond names who made it for the row's attribution. A `ManageConfig` holder always has `View`, so\nthe second guard never rejects a caller the first admitted.",
        "operationId": "put_shared_dashboard",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {}
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Layout saved for every user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardSaved"
                }
              }
            }
          },
          "400": {
            "description": "The layout is not a JSON object",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "413": {
            "description": "The layout exceeds the document size cap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stream/alerts": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Live alert stream (SSE, ADR-019): fires and resolutions as they happen. Each event's `data` is\nthe alert JSON with a `resolved` flag.",
        "operationId": "stream_alerts",
        "responses": {
          "200": {
            "description": "Server-sent event stream of fires and resolutions; a lagged subscriber gets a named `resync` event",
            "content": {
              "text/event-stream": {}
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stream/analysis": {
      "get": {
        "tags": [
          "analysis"
        ],
        "summary": "Live analysis-job status stream (SSE): each event is the job JSON with its current state and\nprogress. Mirrors the alert stream (lagged subscribers get a `resync` hint).",
        "description": "Returns a bare `Response` rather than `ApiResult`: an SSE body is not a `Json<T>`, and the\nguards still run as extractors, which is where the safety was.",
        "operationId": "stream_analysis",
        "responses": {
          "200": {
            "description": "Server-sent event stream of job state and progress; a lagged subscriber gets a named `resync` event",
            "content": {
              "text/event-stream": {}
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This deployment has no runner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stream/node-states": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Live node-state stream (SSE, S14): rolled-up display-state changes as they happen. The\ninventory and topology views seed from REST once, then patch individual nodes off this stream\ninstead of re-fetching the whole fleet every 15s. Works in skeleton mode — the alert engine is\nalways present.",
        "operationId": "stream_node_states",
        "responses": {
          "200": {
            "description": "Server-sent event stream of rolled-up node display-state changes",
            "content": {
              "text/event-stream": {}
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stream/report-runs": {
      "get": {
        "tags": [
          "reports"
        ],
        "summary": "Live report-run status stream: each event is the run JSON with its current state and progress.",
        "description": "A lagged subscriber gets a `resync` event rather than a dropped connection, so the client knows\nto refetch instead of silently showing a stale run forever.",
        "operationId": "stream_report_runs",
        "responses": {
          "200": {
            "description": "Server-sent event stream; each `data` is a run JSON, and a `resync` event means the subscriber lagged",
            "content": {
              "text/event-stream": {}
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks View",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode: no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system-health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Reachability of the backing services plus the indirect bus signal.",
        "description": "Takes `State` rather than the `Admin` extractor on purpose: in skeleton mode this answers a\n`\"degraded\"` body naming what is missing, not a 503. This is the page you open when something is\nalready broken.",
        "operationId": "system_health",
        "responses": {
          "200": {
            "description": "Per-dependency reachability; skeleton mode answers a `degraded` body rather than 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemHealth"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system/hosts": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Current host resources for core and every poller reporting telemetry.",
        "description": "Reads `st.admin` opportunistically rather than taking the `Admin` extractor: core is answering\nthe request, so it can always report *itself*. Skeleton mode returns just core rather than 503.",
        "operationId": "system_hosts",
        "responses": {
          "200": {
            "description": "Core plus every poller reporting host telemetry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemHostsResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system/hosts/{instance}/metrics/range": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Host CPU/load/mem/disk trends for one instance over `[from,to]` at `step`.",
        "operationId": "host_metric_range",
        "parameters": [
          {
            "name": "instance",
            "in": "path",
            "description": "`core`, or the id of a poller the live registry knows",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "step",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scalar host trends plus a per-mount filesystem trend",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HostMetricRange"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such instance — resolved against the known set before any selector is built",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system/support-bundle": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "A downloadable archive of this deployment's logs and status.",
        "description": "Written for a deployment behind an air gap: every entry is text, `MANIFEST.json` lists what is\ncarried **and what is deliberately not**, and a redaction scan over the assembled bytes aborts\nthe export rather than shipping a secret.",
        "operationId": "support_bundle",
        "parameters": [
          {
            "name": "since_hours",
            "in": "query",
            "description": "Hours of log history to carry. Clamped to `[1, 168]`; the appender's own retention is\nusually the tighter bound.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A gzipped tar of JSON and text files: build provenance, every system-health section, the environment allow-list, applied migrations, table sizes, active alerts, the audit tail, the Prometheus scrape, and core's own rotated log files. Carries no secrets — see MANIFEST.json's `omitted` and `redaction` sections",
            "content": {
              "application/gzip": {}
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks any of ManageConfig, ManageCredentials or ViewAudit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "500": {
            "description": "The redaction scan matched, so nothing was released. The rule and the file are named in the log, never the value",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/thresholds": {
      "get": {
        "tags": [
          "thresholds"
        ],
        "operationId": "list_thresholds",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A capped page of rules, with the unfiltered total",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThresholdPage"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin — the ruleset decides when the fleet pages someone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "thresholds"
        ],
        "operationId": "create_threshold",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateThreshold"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Rule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The metric is not an identifier, scope_level/direction is outside its vocabulary, or the metric is a raw counter (a monotonic value has no meaningful fixed bound)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/thresholds/{id}": {
      "delete": {
        "tags": [
          "thresholds"
        ],
        "operationId": "delete_threshold",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Threshold rule id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Rule deleted"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such rule",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topology": {
      "get": {
        "tags": [
          "topology"
        ],
        "summary": "The dependency graph: every node with its parent edge, current state, and any active root-cause\nattribution. Admin-only data source.",
        "description": "The default page is large — the graph views assemble the whole fleet, so fewer round-trips is\nbetter — but bounded, so no single response is a multi-MB blob.",
        "operationId": "get_topology",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One keyset page of the dependency graph; `next_cursor` is null on the last page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopologyPage"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no inventory to build the graph from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topology/link-overrides": {
      "get": {
        "tags": [
          "topology"
        ],
        "summary": "Operator decisions that override the derived connectivity graph.",
        "description": "A group-scoped caller sees only decisions whose **both** endpoints are visible to them, matching\nhow the links themselves are filtered.",
        "operationId": "get_link_overrides",
        "responses": {
          "200": {
            "description": "Every visible link override",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkOverrideList"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "topology"
        ],
        "summary": "Record a decision about a link, replacing any previous decision of the same kind for that pair.",
        "description": "The decision takes effect on the next derivation cycle. A pinned link is re-emitted by every run,\nso it never expires the way an unobserved derived link does.",
        "operationId": "create_link_override",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkOverrideRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The decision was recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The two endpoints are the same node, or `direction` disagrees with `action`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-config permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "One of the endpoints is not a node the caller can see",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topology/link-overrides/{id}": {
      "delete": {
        "tags": [
          "topology"
        ],
        "summary": "Remove an operator decision, letting the derivation's own answer stand again.",
        "operationId": "delete_link_override",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The override's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "The decision was removed"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the manage-config permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such override, or its endpoints are not visible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no write side",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topology/links": {
      "get": {
        "tags": [
          "topology"
        ],
        "summary": "The derived connectivity graph: every link between monitored nodes, with the evidence that\nproduced it.",
        "description": "Links are derived from CDP/LLDP adjacency and from nodes sharing an IP subnet; they are\nrecomputed periodically rather than stored by hand. A group-scoped caller sees only links whose\n**both** endpoints are visible to them.",
        "operationId": "get_topology_links",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "description": "Return links with an id greater than this (the previous page's `next_cursor`).",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum links to return.",
            "required": false,
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One keyset page of the connectivity graph; `next_cursor` is null on the last page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopologyLinkPage"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no inventory to build the graph from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topology/shadow": {
      "get": {
        "tags": [
          "topology"
        ],
        "summary": "What the derived dependency graph would do to alerting, compared with the hand-authored one.",
        "description": "This is the review surface for enabling derived suppression: `would_suppress` lists the active\nalerts that would stop being raised, and `unresolved_pools` lists the pollers that have no place\nin the graph yet. Both are computed on demand and neither affects alerting.",
        "operationId": "get_topology_shadow",
        "responses": {
          "200": {
            "description": "The comparison between the manual and derived dependency graphs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopologyShadow"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks the view permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Skeleton mode has no inventory to compare",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/url-monitors": {
      "post": {
        "tags": [
          "checks"
        ],
        "operationId": "create_url_monitor",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUrlMonitor"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Monitor node created and bound to the built-in URL profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "The name is empty, the URL is invalid or blocked, or the pool name is not a legal subject token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role lacks ManageConfig",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "Inventory storage is unavailable (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users": {
      "get": {
        "tags": [
          "users"
        ],
        "summary": "`GET /api/v1/users` — every local account (never a password hash).",
        "operationId": "list_users",
        "responses": {
          "200": {
            "description": "Every local account, without its password hash",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserSummary"
                  }
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "users"
        ],
        "summary": "`POST /api/v1/users` — create a local or service account.\nCreate an account.",
        "description": "A **service account** (`kind: \"service\"`) is a machine identity: no password, and no way to sign\nin through either the local form or SSO. It exists to own API tokens, so an unattended\nintegration keeps working when the person who set it up changes teams — and so that disabling it\nstops every credential it owns at once.",
        "operationId": "create_user",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateUser"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Account created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedId"
                }
              }
            }
          },
          "400": {
            "description": "Empty username, an unknown role, a password that is missing/too short for a local account or supplied for a service one, or `kind: oidc`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "The username is already taken",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/{id}": {
      "delete": {
        "tags": [
          "users"
        ],
        "summary": "`DELETE /api/v1/users/:id` — remove an account and cut every credential it still holds.",
        "operationId": "delete_user",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User account id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Account removed, its sessions revoked and its API tokens revoked"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Refused: this is the last admin account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/{id}/enabled": {
      "put": {
        "tags": [
          "users"
        ],
        "summary": "`PUT /api/v1/users/:id/enabled` — enable or disable an account.",
        "operationId": "set_user_status",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User account id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetStatus"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Status changed; disabling also revokes the account's sessions and API tokens"
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Refused: this would disable the last admin account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/{id}/password": {
      "put": {
        "tags": [
          "users"
        ],
        "summary": "`PUT /api/v1/users/:id/password` — reset an account's password.",
        "operationId": "set_user_password",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User account id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetPassword"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Password reset and the account's sessions revoked"
          },
          "400": {
            "description": "Password below the minimum length",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/{id}/role": {
      "put": {
        "tags": [
          "users"
        ],
        "summary": "`PUT /api/v1/users/:id/role` — change an account's role.",
        "operationId": "set_user_role",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User account id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetRole"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Role changed and the account's sessions revoked"
          },
          "400": {
            "description": "Role is not viewer, operator, or admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Refused: this would demote the last admin account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/{id}/scope": {
      "put": {
        "tags": [
          "users"
        ],
        "summary": "`PUT /api/v1/users/:id/scope` — set which node groups an account may see.\nLimit an account to a set of node groups, or restore fleet-wide visibility with `\"All\"`.",
        "description": "A scope narrows what the account can **see**: node lists, aggregates and rankings are filtered to\nthe allowed groups and everything beneath them, and a node outside it answers `404` — the same\nanswer an unknown id gets, so the scope cannot be used to probe for what exists. Endpoints whose\nanswer retains no per-node attribution (a rendered report, a pre-summed fleet timeline) refuse a\nscoped caller rather than quietly serving fleet-wide numbers.\n\nIt is not a substitute for a role: a scoped Operator can still acknowledge alerts and open\nmaintenance windows, within their groups. An **Admin cannot be scoped** — administration is\nfleet-wide, so promoting an account to Admin also clears whatever scope it held.",
        "operationId": "set_user_scope",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "User account id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetScope"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Scope changed and the account's sessions revoked"
          },
          "400": {
            "description": "The scope names no groups, or names something that is not an existing group id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "Role below Admin",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Refused: the account is an Admin, whose permissions are fleet-wide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          },
          "503": {
            "description": "This core has no write side (skeleton mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorBody"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/version": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "The running `yagra-core` crate version, which inherits the workspace version (the canonical\nsource of truth). The WebUI shows its own build version alongside this, so a core/web skew\nduring a rolling upgrade is visible at a glance.",
        "operationId": "version",
        "responses": {
          "200": {
            "description": "The running core's build version. Unauthenticated by design",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionInfo"
                }
              }
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/healthz": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "Liveness probe for the deploy/orchestrator — no auth, no store access. Both the leader and HA\nstandbys answer this so their containers stay healthy while a standby waits for leadership.",
        "operationId": "healthz",
        "responses": {
          "200": {
            "description": "This process is alive",
            "content": {
              "text/plain": {}
            }
          }
        },
        "security": [
          {}
        ]
      }
    },
    "/readyz": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "Readiness probe (ADR-016): `200` only when this core holds HA leadership — i.e. it is running the\ncoordinator + ingest and can serve live status. A standby returns `503` so a load balancer /\norchestrator routes traffic only to the active core. With HA off this core is always the leader,\nso it always returns `200`. No auth, no store access (mirrors `/healthz`).",
        "operationId": "readyz",
        "responses": {
          "200": {
            "description": "This core holds HA leadership and can serve live status"
          },
          "503": {
            "description": "This core is a standby — route traffic elsewhere"
          }
        },
        "security": [
          {}
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AckRequest": {
        "type": "object",
        "description": "Inbound ack reflection. An external incident tool mirrors ack state in by the dedup identity\n`(subject, check, severity)`; `acked:false` clears it. `AckAlerts`-gated; the mutating-request\nmiddleware records the audit entry.",
        "required": [
          "check",
          "severity"
        ],
        "properties": {
          "acked": {
            "type": "boolean",
            "description": "`true` = acked (upsert), `false` = cleared (delete). Defaults to `true`."
          },
          "at_unix_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "When the external tool recorded the ack (Unix ms, UTC); defaults to now."
          },
          "by": {
            "type": [
              "string",
              "null"
            ],
            "description": "External actor reference (id / handle) — never a secret."
          },
          "check": {
            "type": "string",
            "format": "uuid"
          },
          "node": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node the alert is about. Omit it and send `subject` instead for an alert about\nsomething other than a node (a poller pool). Exactly one of the two is required."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional free-text note from the external tool."
          },
          "severity": {
            "$ref": "#/components/schemas/Severity"
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Originating tool: `pagerduty` | `jsm` | `manual` | …"
          },
          "subject": {
            "type": [
              "string",
              "null"
            ],
            "description": "The alert's subject in its flat form — a node's UUID, or `pool:<name>`. This is the value\nthe alert's own `node` field carries, so an integration can echo back what it received."
          }
        }
      },
      "AckResult": {
        "type": "object",
        "description": "What an ack call reports back: the new state, and the stored view when acknowledging.",
        "required": [
          "acked"
        ],
        "properties": {
          "ack": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/AckView"
              }
            ]
          },
          "acked": {
            "type": "boolean"
          }
        }
      },
      "AckView": {
        "type": "object",
        "description": "The acknowledgement view attached to an alert / history row in API responses. Carries who\nacked it, when, from which external tool, and an optional note. Never carries a secret.",
        "required": [
          "at_unix_ms",
          "by",
          "source"
        ],
        "properties": {
          "at_unix_ms": {
            "type": "integer",
            "format": "int64",
            "description": "When the external tool recorded the ack (Unix ms, UTC)."
          },
          "by": {
            "type": "string",
            "description": "External actor reference (id / handle) — not a secret."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional free-text note from the external tool."
          },
          "source": {
            "type": "string",
            "description": "Originating tool: `pagerduty` | `jsm` | `manual` | …"
          }
        }
      },
      "ActiveAlertView": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Alert"
          },
          {
            "type": "object",
            "required": [
              "subject_kind"
            ],
            "properties": {
              "acked": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AckView"
                  }
                ]
              },
              "subject_kind": {
                "$ref": "#/components/schemas/SubjectKind",
                "description": "What this alert is about: a monitored node, or Yagra's own polling coverage for a pool."
              },
              "subject_name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The subject's name, for a subject identified by name rather than by id (a poller pool)."
              }
            }
          }
        ],
        "description": "An active alert plus its inbound (read-only) ack state.\n\n`subject_kind` and `subject_name` decompose the alert's `node` field, which carries either a\nnode's UUID or `pool:<name>`. The live alert stream emits the same three keys."
      },
      "Alert": {
        "type": "object",
        "description": "A single alert produced by the engine.",
        "required": [
          "node",
          "check",
          "severity",
          "state",
          "at_unix_ms",
          "flapping",
          "metric"
        ],
        "properties": {
          "at_unix_ms": {
            "type": "integer",
            "format": "int64",
            "description": "When it fired (Unix ms, UTC)."
          },
          "breach": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Breach",
                "description": "Numeric breach detail for a threshold alert; `None` for a liveness alert."
              }
            ]
          },
          "check": {
            "$ref": "#/components/schemas/CheckId",
            "description": "The check that produced it."
          },
          "flapping": {
            "type": "boolean",
            "description": "Whether the underlying check is currently flapping."
          },
          "metric": {
            "type": "string",
            "description": "Metric the check measured (e.g. `\"icmp_rtt_ms\"`; the liveness sentinel for up/down).\nCarried for the history log + notification payload so a human can read *what* fired —\nnot part of alert identity (dedup/grouping ignore it)."
          },
          "node": {
            "type": "string",
            "description": "What the alert is about: a node's UUID, or `pool:<name>` for a poller-pool alert."
          },
          "root_cause": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/NodeId",
                "description": "Root-cause node, if this alert was attributed upstream by dependency analysis."
              }
            ]
          },
          "severity": {
            "$ref": "#/components/schemas/Severity",
            "description": "Severity (derived from the committed state)."
          },
          "state": {
            "$ref": "#/components/schemas/NodeState",
            "description": "The committed state that triggered the alert."
          }
        }
      },
      "AlertFacts": {
        "type": "object",
        "description": "The alert being explained.",
        "required": [
          "severity",
          "state",
          "metric",
          "at_unix_ms",
          "flapping"
        ],
        "properties": {
          "asked_about": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the operator clicked a *symptom* and the context hopped to its cause. Naming the\nnode they clicked keeps the answer connected to what they were looking at."
          },
          "at_unix_ms": {
            "type": "integer",
            "format": "int64"
          },
          "breach": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BreachFacts",
                "description": "Numeric detail for a threshold alert; absent for liveness."
              }
            ]
          },
          "flapping": {
            "type": "boolean",
            "description": "Whether the engine is damping this check as flapping. Worth telling the model: a flapping\nlink and a hard failure have different causes and different next steps."
          },
          "metric": {
            "type": "string",
            "description": "What the check measured — `icmp_rtt_ms`, or the liveness sentinel."
          },
          "severity": {
            "type": "string"
          },
          "state": {
            "type": "string"
          }
        }
      },
      "AlertHistoryRow": {
        "type": "object",
        "description": "One alert-history row for the API.",
        "required": [
          "subject_kind",
          "check",
          "severity",
          "state",
          "at_unix_ms",
          "resolved",
          "recorded_at"
        ],
        "properties": {
          "at_unix_ms": {
            "type": "integer",
            "format": "int64"
          },
          "check": {
            "type": "string",
            "format": "uuid"
          },
          "direction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Direction",
                "description": "Which way the metric crossed its bound (threshold checks only)."
              }
            ]
          },
          "metric": {
            "type": [
              "string",
              "null"
            ],
            "description": "Metric the check measured (e.g. `icmp_rtt_ms`, or the liveness sentinel). `None` for\nrows recorded before this was captured (legacy) so the WebUI can show \"—\"."
          },
          "node": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node this transition was about; `null` when the subject is not a node — read\n`subject_kind` first. It is non-null exactly when `subject_kind` is `node`."
          },
          "observed_value": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Observed sample value that committed the transition (threshold checks only)."
          },
          "recorded_at": {
            "type": "string",
            "description": "Insertion time as an RFC 3339 timestamp. This is the **keyset cursor**: the WebUI passes\nthe last row's `recorded_at` as `before` to fetch the next (older) page (matches the audit\nlog's paging). Distinct from `at_unix_ms` (the event time), which can collide across rows."
          },
          "resolved": {
            "type": "boolean"
          },
          "severity": {
            "$ref": "#/components/schemas/Severity"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          },
          "subject_kind": {
            "$ref": "#/components/schemas/SubjectKind",
            "description": "What the transition was about."
          },
          "subject_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The subject's name, for a subject identified by name rather than by id (a poller pool)."
          },
          "threshold_value": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "The bound crossed for the committed severity (threshold checks only)."
          }
        }
      },
      "AlertHistoryView": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AlertHistoryRow"
          },
          {
            "type": "object",
            "properties": {
              "acked": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AckView"
                  }
                ]
              }
            }
          }
        ],
        "description": "An alert-history row plus its current inbound ack state (keyed by the dedup identity, so all\ntransitions of one incident share it)."
      },
      "AlertNodeCount": {
        "type": "object",
        "description": "One chronic-offender row.",
        "required": [
          "node_id",
          "name",
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "AlertTransition": {
        "type": "object",
        "description": "One recent state-change row (a fire = into an alert state; a resolve = recovery to ok).",
        "required": [
          "node_id",
          "name",
          "state",
          "severity",
          "resolved",
          "at_unix_ms"
        ],
        "properties": {
          "at_unix_ms": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "resolved": {
            "type": "boolean",
            "description": "true = recovery (→ ok); false = went into the alert state."
          },
          "severity": {
            "$ref": "#/components/schemas/Severity"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          }
        }
      },
      "AnalysisFinding": {
        "type": "object",
        "description": "One finding produced by an analysis (anomaly card / correlation pair / capacity / flap row).",
        "required": [
          "id",
          "score",
          "severity",
          "node_name",
          "metric",
          "kind",
          "when_label",
          "duration",
          "detail"
        ],
        "properties": {
          "detail": {},
          "duration": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string"
          },
          "metric": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "node_name": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "format": "double"
          },
          "severity": {
            "type": "string"
          },
          "when_label": {
            "type": "string"
          }
        }
      },
      "AnalysisJob": {
        "type": "object",
        "description": "A job row, as served to the API / SSE. Timestamps are epoch-millis so the WebUI formats\nrelative times without a date dependency.",
        "required": [
          "id",
          "tool",
          "scope_kind",
          "scope_label",
          "params",
          "state",
          "pct",
          "finding_count",
          "created_ms"
        ],
        "properties": {
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "finding_count": {
            "type": "integer",
            "format": "int32"
          },
          "finished_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "params": {},
          "pct": {
            "type": "integer",
            "format": "int32"
          },
          "phase": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string"
          },
          "scope_label": {
            "type": "string"
          },
          "started_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "state": {
            "type": "string"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ]
          },
          "tool": {
            "type": "string"
          }
        }
      },
      "AnalysisSchedule": {
        "type": "object",
        "description": "A schedule row, as served to the API.",
        "required": [
          "id",
          "tool",
          "scope_kind",
          "scope_label",
          "params",
          "frequency",
          "at_hour",
          "at_minute",
          "enabled",
          "next_run_ms"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          },
          "frequency": {
            "$ref": "#/components/schemas/Cadence"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_run_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "last_status": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/AnalysisScheduleStatus"
              }
            ]
          },
          "next_run_ms": {
            "type": "integer",
            "format": "int64"
          },
          "params": {
            "description": "The launch knobs, the same shape as `AnalysisJob.params`."
          },
          "scope_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string",
            "description": "`all` | `group` | `node`."
          },
          "scope_label": {
            "type": "string"
          },
          "tool": {
            "type": "string",
            "description": "Which diagnostic runs, as an `AnalysisTool` token."
          }
        }
      },
      "AnalysisScheduleBody": {
        "type": "object",
        "description": "Create/update body for an analysis schedule: the launch spec plus the cadence.",
        "required": [
          "tool",
          "scope_kind",
          "scope_label",
          "window_secs",
          "frequency",
          "at_hour",
          "at_minute"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "baseline_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "1 … 28. Read only for `monthly`."
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "0=Sun … 6=Sat. Read only for `weekly`."
          },
          "depth": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Defaults to enabled."
          },
          "family": {
            "type": [
              "string",
              "null"
            ]
          },
          "frequency": {
            "type": "string",
            "description": "`daily` | `weekly` | `monthly`."
          },
          "notify": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether a completed run may notify. Defaults to `false` — a schedule fires unattended, so\nsilence is the safer default; the manual launch path defaults it on because someone is\nwaiting for that run."
          },
          "scope_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string",
            "description": "`all` | `group` | `node`."
          },
          "scope_label": {
            "type": "string"
          },
          "sensitivity": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "tool": {
            "type": "string",
            "description": "Which diagnostic to run (an `AnalysisTool` token, e.g. `anomaly`)."
          },
          "window_secs": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "AnalysisScheduleRow": {
        "type": "object",
        "description": "A recurring Troubleshoot analysis.",
        "required": [
          "id",
          "tool",
          "scope_kind",
          "scope_label",
          "params",
          "frequency",
          "at_hour",
          "at_minute",
          "enabled"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "enabled": {
            "type": "boolean"
          },
          "frequency": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "params": {},
          "scope_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string"
          },
          "scope_label": {
            "type": "string"
          },
          "tool": {
            "type": "string"
          }
        }
      },
      "AnalysisScheduleStatus": {
        "type": "string",
        "description": "Outcome of a schedule's most recent firing attempt.",
        "enum": [
          "queued",
          "busy",
          "error",
          "unknown"
        ]
      },
      "ApiErrorBody": {
        "type": "object",
        "description": "The ADR-019 envelope every failure renders as. `pub(crate)` and schema-bearing so the OpenAPI\ndocument can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies\nundescribed — a client that has to guess the failure shape ends up parsing the success shape and\nreading `undefined`.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        }
      },
      "ApiTokenInfo": {
        "type": "object",
        "description": "One API token's metadata for the admin listing — **never** the raw token or its hash\n(security.md: a credential is never returned in an API response after issuance).",
        "required": [
          "id",
          "name",
          "role",
          "scope",
          "surfaces",
          "owner_active",
          "created_by",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the token stops authenticating, or `None` for no expiry."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "name": {
            "type": "string"
          },
          "owner": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account the token acts as. `None` means the owner was deleted before this column\nexisted, or could not be matched during the 0057 backfill — such a token no longer\nauthenticates and is shown so an admin can revoke it deliberately."
          },
          "owner_active": {
            "type": "boolean",
            "description": "Whether the owner account is currently able to authenticate (enabled). Surfaced so the\nlisting can explain a token that is live by its own dates yet refused."
          },
          "owner_last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The owner's last interactive sign-in, when the owner authenticates through an external IdP.\nThis is the only signal Yagra has that an SSO account is still live (see [`ApiTokenStore`]),\nso the listing shows it; `None` for local and service accounts, where it means nothing."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope"
          },
          "surfaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenSurface"
            },
            "description": "Which auth surfaces this token may be presented at. Never empty in practice — a token that\nnamed no surface could authenticate nowhere — but stored as a list so it can grow."
          }
        }
      },
      "AppSettingsRow": {
        "type": "object",
        "description": "The deployment-wide settings the bundle carries. The retention windows are deliberately absent\n(module docs).",
        "required": [
          "default_poll_interval_secs",
          "meraki_polling_enabled"
        ],
        "properties": {
          "default_poll_interval_secs": {
            "type": "integer",
            "format": "int32"
          },
          "meraki_polling_enabled": {
            "type": "boolean"
          }
        }
      },
      "AuditRow": {
        "type": "object",
        "description": "One audit row (API shape; `at` is RFC 3339 text at the edge).",
        "required": [
          "id",
          "at",
          "username",
          "action",
          "status"
        ],
        "properties": {
          "action": {
            "type": "string"
          },
          "at": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "integer",
            "format": "int32"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "AuthMe": {
        "type": "object",
        "description": "The caller's own identity.",
        "required": [
          "role",
          "username",
          "scope"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope",
            "description": "Which slice of the inventory this account sees: `\"All\"`, or the node groups it is limited\nto. The UI reads it to say so out loud — an operator looking at a filtered node list has no\nother way to tell a narrow scope from a small fleet."
          },
          "username": {
            "type": "string"
          }
        }
      },
      "AuthorizeUrl": {
        "type": "object",
        "description": "Where to send the browser to start the SSO handshake.",
        "required": [
          "authorize_url"
        ],
        "properties": {
          "authorize_url": {
            "type": "string"
          }
        }
      },
      "BodyMatch": {
        "type": "object",
        "description": "A keyword rule applied to a URL monitor's response body.\n\nWhen present, the monitor reports `http_body_match` (`1` satisfied / `0` not) in addition to\n`http_up`. How much of the body is read is [`UrlCheckConfig::body_max_bytes`].",
        "required": [
          "pattern"
        ],
        "properties": {
          "mode": {
            "$ref": "#/components/schemas/BodyMatchMode",
            "description": "Whether the keyword must be present or absent (default: present)."
          },
          "pattern": {
            "type": "string",
            "description": "The keyword to look for. Matched as plain, case-sensitive text — not a regular expression."
          }
        }
      },
      "BodyMatchMode": {
        "type": "string",
        "description": "Whether the keyword must be present or absent for the body to be considered healthy.",
        "enum": [
          "contains",
          "not_contains"
        ]
      },
      "Breach": {
        "type": "object",
        "description": "Numeric breach detail for a threshold alert (absent for a liveness up/down alert).\nCarried for the history log + notification payload — not part of alert identity.",
        "required": [
          "value",
          "direction"
        ],
        "properties": {
          "direction": {
            "$ref": "#/components/schemas/Direction",
            "description": "Which way the metric crossed its bound."
          },
          "threshold": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "The bound crossed for the committed severity, if the rule defines one at that level."
          },
          "value": {
            "type": "number",
            "format": "double",
            "description": "Observed sample value that committed the transition."
          }
        }
      },
      "BreachFacts": {
        "type": "object",
        "required": [
          "value",
          "direction"
        ],
        "properties": {
          "direction": {
            "$ref": "#/components/schemas/Direction"
          },
          "threshold": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "BundleNote": {
        "type": "object",
        "description": "One note, with the table it concerns and how many rows it covers.",
        "required": [
          "table",
          "code",
          "count"
        ],
        "properties": {
          "code": {
            "$ref": "#/components/schemas/NoteCode",
            "description": "What happened."
          },
          "count": {
            "type": "integer",
            "format": "int32",
            "description": "How many rows this note covers.",
            "minimum": 0
          },
          "field": {
            "type": [
              "string",
              "null"
            ],
            "description": "The column involved, when the note is about one (e.g. `credential_id`)."
          },
          "table": {
            "type": "string",
            "description": "The table the note is about."
          }
        }
      },
      "Cadence": {
        "type": "string",
        "description": "How often a schedule fires.",
        "enum": [
          "daily",
          "weekly",
          "monthly",
          "unknown"
        ]
      },
      "CalendarBucket": {
        "type": "object",
        "description": "One weekday×hour heatmap cell.",
        "required": [
          "dow",
          "hour",
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "dow": {
            "type": "integer",
            "format": "int32",
            "description": "0 = Sunday … 6 = Saturday (UTC)."
          },
          "hour": {
            "type": "integer",
            "format": "int32",
            "description": "Hour of day 0–23 (UTC)."
          }
        }
      },
      "Cancelled": {
        "type": "object",
        "description": "What cancelling a run reports.",
        "required": [
          "cancelled"
        ],
        "properties": {
          "cancelled": {
            "type": "boolean"
          }
        }
      },
      "Candidate": {
        "type": "object",
        "description": "One device a scan found, with a suggested profile for the operator to confirm on import.",
        "required": [
          "address",
          "reachable"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "matched_credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The stored credential that answered SNMP, by reference (never the value) — the UI\npreselects it on import so the working secret is bound automatically."
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "reachable": {
            "type": "boolean"
          },
          "suggested_profile_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Suggested device profile, resolved **server-side** via the classification rules (by\nsysObjectID prefix, else sysDescr regex, else \"Generic SNMP\" when SNMP answered). An id,\nnot a name, so the UI binds it robustly even if the profile was renamed."
          },
          "sysdescr": {
            "type": [
              "string",
              "null"
            ]
          },
          "sysname": {
            "type": [
              "string",
              "null"
            ]
          },
          "sysobjectid": {
            "type": [
              "string",
              "null"
            ],
            "description": "`sysObjectID` (dotted) if it answered SNMP — the authoritative device-type signal the\nclassifier prefers. Shown to the operator and useful for authoring rules."
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Maker / model best-effort parsed from sysDescr (editable on import) — pre-fills the\nnode's descriptive metadata so the imported node displays \"name (addr) (vendor) (model)\"."
          }
        }
      },
      "ChangeFacts": {
        "type": "object",
        "description": "One audited configuration change.",
        "required": [
          "at",
          "username",
          "action",
          "status"
        ],
        "properties": {
          "action": {
            "type": "string",
            "description": "`\"{METHOD} {path}\"`, as recorded by the audit middleware."
          },
          "at": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "format": "int32"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "ChannelConfig": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "url",
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "webhook"
                ]
              },
              "url": {
                "type": "string"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "host",
              "from",
              "to",
              "kind"
            ],
            "properties": {
              "from": {
                "type": "string"
              },
              "host": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "email"
                ]
              },
              "pass": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "port": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int32",
                "minimum": 0
              },
              "to": {
                "type": "string"
              },
              "user": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "PagerDuty Events API v2. `routing_key` is the integration key (a secret).\n`api_url` overrides the default US endpoint (EU: `https://events.eu.pagerduty.com/v2/enqueue`);\nallowed hosts are pinned at the API edge (`validate_channel_config`).",
            "required": [
              "routing_key",
              "kind"
            ],
            "properties": {
              "api_url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "kind": {
                "type": "string",
                "enum": [
                  "pagerduty"
                ]
              },
              "routing_key": {
                "type": "string"
              }
            }
          },
          {
            "type": "object",
            "description": "JSM Alerts / Opsgenie-compatible API. `api_url` is the integration base\n(e.g. `https://api.atlassian.com/jsm/ops/integration/v2`); `api_key` is the\nGenieKey (a secret).",
            "required": [
              "api_url",
              "api_key",
              "kind"
            ],
            "properties": {
              "api_key": {
                "type": "string"
              },
              "api_url": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "jsm"
                ]
              }
            }
          }
        ],
        "description": "The (secret) connection config for a channel — sealed at rest, never returned by the API."
      },
      "ChannelKind": {
        "type": "string",
        "description": "A delivery channel kind.",
        "enum": [
          "webhook",
          "email",
          "pagerduty",
          "jsm"
        ]
      },
      "ChannelSummary": {
        "type": "object",
        "description": "Channel metadata for the API — never the secret config.",
        "required": [
          "id",
          "name",
          "kind",
          "enabled"
        ],
        "properties": {
          "body_template": {
            "type": [
              "string",
              "null"
            ],
            "description": "Template for the notification body. Absent means Yagra's built-in format is used."
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/ChannelKind"
          },
          "name": {
            "type": "string"
          },
          "subject_template": {
            "type": [
              "string",
              "null"
            ],
            "description": "Template for the notification subject. Absent means Yagra's built-in wording is used."
          }
        }
      },
      "CheckId": {
        "type": "string",
        "format": "uuid",
        "description": "Stable identifier for a single check on a node (e.g. \"icmp liveness\", a specific\nthreshold). Part of the alert dedup key `(node, check, severity)`."
      },
      "ClassificationRule": {
        "type": "object",
        "description": "A persisted rule mapping a device signature to a profile. At least one of\n`sysobjectid_prefix` / `sysdescr_regex` is set (the DB enforces this with a CHECK).",
        "required": [
          "id",
          "priority",
          "profile_id",
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Disabled rules are skipped during classification."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable identity."
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "description": "See `vendor`."
          },
          "priority": {
            "type": "integer",
            "format": "int32",
            "description": "Evaluation order: ascending, lowest first. Most-specific rules get lower numbers."
          },
          "profile_id": {
            "$ref": "#/components/schemas/ProfileId",
            "description": "The profile to suggest when this rule matches."
          },
          "sysdescr_regex": {
            "type": [
              "string",
              "null"
            ],
            "description": "Match when the device's `sysDescr` matches this regular expression — a fallback for\ndevices whose `sysObjectID` isn't covered by a prefix rule."
          },
          "sysobjectid_prefix": {
            "type": [
              "string",
              "null"
            ],
            "description": "Match when the device's `sysObjectID` starts with this dotted-OID prefix\n(e.g. `1.3.6.1.4.1.9.` for Cisco). Authoritative — preferred over `sysDescr`."
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional vendor/model to pre-fill on the import row (overrides the `sysDescr`\nheuristic when set). Descriptive metadata only — never a TSDB label."
          }
        }
      },
      "ClassificationRuleBody": {
        "type": "object",
        "description": "Create/update body. At least one of `sysobjectid_prefix` / `sysdescr_regex` must be present.",
        "required": [
          "priority",
          "profile_id"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": "integer",
            "format": "int32"
          },
          "profile_id": {
            "type": "string"
          },
          "sysdescr_regex": {
            "type": [
              "string",
              "null"
            ]
          },
          "sysobjectid_prefix": {
            "type": [
              "string",
              "null"
            ]
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ClassificationRuleRow": {
        "type": "object",
        "description": "A discovery classification rule.",
        "required": [
          "id",
          "priority",
          "profile_id",
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": "integer",
            "format": "int32"
          },
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "sysdescr_regex": {
            "type": [
              "string",
              "null"
            ]
          },
          "sysobjectid_prefix": {
            "type": [
              "string",
              "null"
            ]
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ClientConfig": {
        "type": "object",
        "description": "Client bootstrap config — no secrets.",
        "required": [
          "public_dashboard",
          "auth_available",
          "sso_enabled",
          "rca_enabled",
          "flow_enabled",
          "default_poll_interval_secs"
        ],
        "properties": {
          "auth_available": {
            "type": "boolean",
            "description": "Whether interactive login exists at all (false in skeleton mode)."
          },
          "default_poll_interval_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "flow_enabled": {
            "type": "boolean",
            "description": "Whether this deployment has a traffic-flow store configured (ADR-031). When `false`, the\nflow analyses cannot be scheduled — `POST /api/v1/analysis/schedules` refuses them."
          },
          "public_dashboard": {
            "type": "boolean",
            "description": "Whether read endpoints are open to anonymous callers."
          },
          "rca_enabled": {
            "type": "boolean",
            "description": "Whether an LLM provider is configured *and* enabled."
          },
          "sso_enabled": {
            "type": "boolean"
          }
        }
      },
      "CollectionItem": {
        "type": "object",
        "description": "One thing to collect: a stable metric name, the OID to collect it from, how to collect\nit (scalar GET vs table walk), and whether it is a gauge or a raw counter.",
        "required": [
          "metric_name",
          "oid",
          "kind",
          "metric_kind"
        ],
        "properties": {
          "kind": {
            "$ref": "#/components/schemas/CollectionKind",
            "description": "Scalar GET vs table walk."
          },
          "metric_kind": {
            "$ref": "#/components/schemas/MetricKind",
            "description": "Gauge vs raw counter — rates/utilization are derived at query time (ADR-012),\nnever by the poller."
          },
          "metric_name": {
            "type": "string",
            "description": "Stable TSDB metric name (e.g. `if_hc_in_octets`). Bounded by convention to keep\nlabel cardinality controlled — never a free-text/device-supplied value (ADR-011)."
          },
          "oid": {
            "type": "string",
            "description": "Dotted OID: a scalar instance OID ([`CollectionKind::Scalar`]) or a table column\nbase ([`CollectionKind::Table`], the walk root)."
          }
        }
      },
      "CollectionKind": {
        "type": "string",
        "description": "How a [`CollectionItem`] is collected from the agent.",
        "enum": [
          "scalar",
          "table"
        ]
      },
      "CollectionTemplateItemRow": {
        "type": "object",
        "description": "One metric inside a collection template.",
        "required": [
          "id",
          "template_id",
          "metric_name",
          "oid",
          "collection",
          "metric_kind",
          "enabled"
        ],
        "properties": {
          "collection": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "metric_kind": {
            "type": "string"
          },
          "metric_name": {
            "type": "string"
          },
          "oid": {
            "type": "string"
          },
          "template_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "CollectionTemplateRow": {
        "type": "object",
        "description": "A reusable collection template.",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Condition": {
        "type": "object",
        "description": "One `field op value` test. `value` is always a string so the config has a single JSON shape;\n[`compile`] parses it according to the field's type.",
        "required": [
          "field",
          "op"
        ],
        "properties": {
          "field": {
            "$ref": "#/components/schemas/FilterField",
            "description": "The datum to inspect."
          },
          "op": {
            "$ref": "#/components/schemas/FilterOp",
            "description": "The comparison to apply."
          },
          "value": {
            "type": "string",
            "description": "The operand, parsed per field type at compile time."
          }
        }
      },
      "ConfigBody": {
        "type": "object",
        "required": [
          "default_poll_interval_secs"
        ],
        "properties": {
          "default_poll_interval_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "ConfigBundle": {
        "type": "object",
        "description": "A whole configuration bundle.",
        "required": [
          "format",
          "version",
          "exported_at",
          "yagra_version"
        ],
        "properties": {
          "analysis_schedules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnalysisScheduleRow"
            }
          },
          "app_settings": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/AppSettingsRow"
              }
            ]
          },
          "classification_rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClassificationRuleRow"
            }
          },
          "collection_template_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CollectionTemplateItemRow"
            }
          },
          "collection_templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CollectionTemplateRow"
            }
          },
          "dns_checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DnsCheckRow"
            }
          },
          "event_rules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventRuleRow"
            }
          },
          "event_sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventSourceRow"
            }
          },
          "exported_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the export ran."
          },
          "format": {
            "type": "string",
            "description": "Always `yagra.config-bundle`. An importer refuses anything else rather than guessing."
          },
          "forward_destinations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ForwardDestinationRow"
            }
          },
          "node_groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeGroupRow"
            }
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeRow"
            }
          },
          "notes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BundleNote"
            },
            "description": "What the export left out or changed. Informational; ignored on import."
          },
          "profile_collection_templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProfileTemplateLink"
            }
          },
          "profiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProfileRow"
            }
          },
          "report_definitions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportDefinitionRow"
            }
          },
          "report_schedules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportScheduleRow"
            }
          },
          "secrets": {
            "$ref": "#/components/schemas/SecretsMode",
            "description": "How secrets are represented. Always `references` — a bundle never carries one."
          },
          "thresholds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThresholdRow"
            }
          },
          "url_checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UrlCheckRow"
            }
          },
          "version": {
            "type": "integer",
            "format": "int32",
            "description": "Bundle schema version.",
            "minimum": 0
          },
          "yagra_version": {
            "type": "string",
            "description": "The Yagra version that produced it."
          }
        }
      },
      "CreateAnalysisJob": {
        "type": "object",
        "description": "Request body to launch an analysis (launch drawer / report config bar).",
        "required": [
          "tool",
          "scope_kind",
          "scope_label",
          "window_secs"
        ],
        "properties": {
          "baseline_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "depth": {
            "type": [
              "string",
              "null"
            ]
          },
          "family": {
            "type": [
              "string",
              "null"
            ]
          },
          "notify": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "scope_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string"
          },
          "scope_label": {
            "type": "string"
          },
          "sensitivity": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "tool": {
            "type": "string"
          },
          "window_secs": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "CreateApiTokenBody": {
        "type": "object",
        "description": "Request body for `POST /api/v1/api-tokens`.",
        "required": [
          "name",
          "role"
        ],
        "properties": {
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the token stops working. Omit for no expiry — appropriate for a service account driving\nan integration, and deliberately still allowed."
          },
          "name": {
            "type": "string",
            "description": "Human label (unique, ≤128 chars)."
          },
          "owner_user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The account the token acts as. Omit to own it yourself; name a service account for anything\nunattended, so the credential outlives whoever set it up."
          },
          "role": {
            "$ref": "#/components/schemas/Role",
            "description": "The role the token grants (`viewer` is the right default for a read-only client). Capped at\nthe owner's role on every use, so this is a ceiling rather than a promise."
          },
          "scope": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Scope",
                "description": "Visibility scope; defaults to `All` when omitted. A group scope limits the token to those\nnode groups and everything beneath them. It must name groups that exist, and the owner must\nitself be unscoped — a token owned by a group-scoped account inherits that account's scope,\nso giving it a different one is refused rather than silently ignored."
              }
            ]
          },
          "surfaces": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/TokenSurface"
            },
            "description": "Which surfaces the token may authenticate. Defaults to `[\"mcp\"]` when omitted, matching what\nevery token issued before this field existed can do."
          }
        }
      },
      "CreateChannel": {
        "type": "object",
        "description": "Create-channel body: a name plus the (secret-bearing) connection config, tagged by `kind`.",
        "required": [
          "name",
          "config"
        ],
        "properties": {
          "config": {
            "$ref": "#/components/schemas/ChannelConfig"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateCollectionItem": {
        "type": "object",
        "description": "Create body for a collection item — the same shape whether it lands on a node or a template.",
        "required": [
          "metric_name",
          "oid",
          "collection",
          "metric_kind"
        ],
        "properties": {
          "collection": {
            "type": "string"
          },
          "enabled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "metric_kind": {
            "type": "string"
          },
          "metric_name": {
            "type": "string"
          },
          "oid": {
            "type": "string"
          }
        }
      },
      "CreateCredential": {
        "type": "object",
        "description": "Create body. `secret` is sealed before storage and never logged.",
        "required": [
          "name",
          "kind",
          "secret"
        ],
        "properties": {
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "secret": {
            "type": "string"
          }
        }
      },
      "CreateDnsMonitor": {
        "type": "object",
        "description": "The check config is spelled out rather than `#[serde(flatten)]`ed (as [`CreateUrlMonitor`]\ndoes) because both the node and the check have a `name`: flattening would bind them to the same\nJSON key and silently force the display label to equal the resolved name.",
        "required": [
          "name",
          "dns_name"
        ],
        "properties": {
          "dns_name": {
            "type": "string",
            "description": "The DNS name to resolve."
          },
          "max_depth": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "name": {
            "type": "string",
            "description": "Display name for the node."
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "record_type": {
            "$ref": "#/components/schemas/DnsRecordType"
          },
          "resolver": {
            "type": [
              "string",
              "null"
            ]
          },
          "resolver_port": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "timeout_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "CreateEventSource": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "CreateMerakiOrgsReq": {
        "type": "object",
        "required": [
          "api_key",
          "org_ids"
        ],
        "properties": {
          "api_key": {
            "type": "string"
          },
          "base_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "org_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CreateMibEntry": {
        "type": "object",
        "description": "Create-entry body for the catalog.",
        "required": [
          "metric_name",
          "oid",
          "collection",
          "metric_kind"
        ],
        "properties": {
          "collection": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "metric_kind": {
            "type": "string"
          },
          "metric_name": {
            "type": "string"
          },
          "oid": {
            "type": "string"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateMute": {
        "type": "object",
        "description": "Create-mute body. `scope_kind` is `node` (silence one node, optionally one `metric_name`) or\n`group` (silence every node under a folder group, recursive — `metric_name` is ignored);\n`scope_id` is the node/group UUID. `until` is RFC 3339.",
        "required": [
          "scope_kind",
          "scope_id",
          "until"
        ],
        "properties": {
          "metric_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope_id": {
            "type": "string",
            "format": "uuid"
          },
          "scope_kind": {
            "type": "string"
          },
          "until": {
            "type": "string"
          }
        }
      },
      "CreateNode": {
        "type": "object",
        "description": "Create-node request body. `profile_id`/`credential_id`/`parent_id` are optional.",
        "required": [
          "name",
          "address"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateRule": {
        "type": "object",
        "description": "Create-rule body: a name, an optional severity filter (absent = any), and target channels.",
        "required": [
          "name",
          "channel_ids"
        ],
        "properties": {
          "channel_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "name": {
            "type": "string"
          },
          "severity": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateTemplate": {
        "type": "object",
        "description": "Create-template body.",
        "required": [
          "name"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          }
        }
      },
      "CreateThreshold": {
        "type": "object",
        "description": "Create-threshold request body.",
        "required": [
          "scope_level",
          "scope_id",
          "metric",
          "direction"
        ],
        "properties": {
          "critical": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "direction": {
            "type": "string"
          },
          "dwell_samples": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "metric": {
            "type": "string"
          },
          "scope_id": {
            "type": "string"
          },
          "scope_level": {
            "type": "string"
          },
          "warning": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          }
        }
      },
      "CreateUrlMonitor": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UrlCheckConfig"
          },
          {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "parent_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "pool": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        ],
        "description": "`name`/`parent_id`/`pool` plus a flattened [`UrlCheckConfig`] (only `url` is required;\neverything else defaults)."
      },
      "CreateUser": {
        "type": "object",
        "description": "Create-user request body. The password is hashed before storage and never logged.",
        "required": [
          "username",
          "role"
        ],
        "properties": {
          "kind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/UserKind",
                "description": "What kind of account this is. Defaults to `local`, so a client written before service\naccounts existed keeps creating exactly what it did before.\n\n`oidc` is not accepted: those accounts are provisioned by signing in through the IdP, never\nby hand — creating one here would produce an account whose subject matches nobody."
              }
            ]
          },
          "password": {
            "type": [
              "string",
              "null"
            ],
            "description": "Required for a `local` account, and rejected for a `service` one — a machine account has no\npassword by design, so accepting a discarded one would advertise a login that does not exist."
          },
          "role": {
            "type": "string"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "CreateWindow": {
        "type": "object",
        "description": "Create-window body. Times are RFC 3339; the scope mirrors thresholds (ADR-013) plus\n`group_id` (a folder-group UUID, resolved recursively — the All Nodes right-click scope).",
        "required": [
          "name",
          "scope_level",
          "scope_id",
          "starts_at",
          "ends_at"
        ],
        "properties": {
          "ends_at": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "scope_id": {
            "type": "string"
          },
          "scope_level": {
            "type": "string"
          },
          "starts_at": {
            "type": "string"
          }
        }
      },
      "CreatedApiToken": {
        "type": "object",
        "description": "The one and only response carrying a usable token.\n\nA named type rather than an inline `json!` because of what the `token` field is: the client has\nto store it now, since only its hash is kept and no later call can produce it again. Giving it a\ntype makes that field visible in one place if this response ever grows a second consumer.",
        "required": [
          "id",
          "name",
          "role",
          "surfaces",
          "token"
        ],
        "properties": {
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "surfaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenSurface"
            }
          },
          "token": {
            "type": "string",
            "description": "The raw bearer token, returned **once**. Never stored, never logged."
          }
        }
      },
      "CreatedId": {
        "type": "object",
        "description": "The id of a freshly created resource — the whole body of a `201`.\n\nDeliberately one shape for every creator. The `json!({\"id\": …})` literal it replaces was written\nout per handler, which is how `{\"id\": …}` and `{\"node_id\": …}` both ended up in this API for the\nsame idea; a client then needs to know which creator it called to read the id back.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "CreatedSource": {
        "type": "object",
        "description": "A newly created source, with its ingest token.\n\n**The plaintext token appears here and nowhere else** — only its hash is stored, so this response\nand `rotate-token` are the only two places it can ever be read.",
        "required": [
          "id",
          "token"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "token": {
            "type": "string"
          }
        }
      },
      "CredentialHealth": {
        "type": "object",
        "description": "Whether the stored credentials can actually be decrypted with the KEK this process loaded.",
        "required": [
          "total",
          "decryptable",
          "failures"
        ],
        "properties": {
          "decryptable": {
            "type": "integer",
            "format": "int32",
            "description": "How many of them the current key opened successfully.",
            "minimum": 0
          },
          "failures": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UndecryptableCredential"
            },
            "description": "The ones that failed, if any. A non-empty list means polling with those credentials will\nfail until the correct key file is restored."
          },
          "total": {
            "type": "integer",
            "format": "int32",
            "description": "How many credentials are stored.",
            "minimum": 0
          }
        }
      },
      "CredentialId": {
        "type": "string",
        "format": "uuid",
        "description": "Stable identifier for a stored monitoring credential (SNMP community / v3 / token)."
      },
      "CredentialSummary": {
        "type": "object",
        "description": "Credential metadata returned by the API — never includes the secret value.",
        "required": [
          "id",
          "name",
          "kind",
          "used_by"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "used_by": {
            "type": "integer",
            "format": "int64",
            "description": "How many nodes reference this credential — answers \"is it safe to delete?\". Counted at\nlist time from `nodes.credential_id`; `0` means the credential is unused."
          }
        }
      },
      "CurrentNeighbors": {
        "type": "object",
        "description": "A node's current adjacency and how long it has held.",
        "required": [
          "neighbors",
          "first_seen",
          "last_seen"
        ],
        "properties": {
          "first_seen": {
            "type": "string",
            "description": "When this exact set was first seen (RFC 3339)."
          },
          "last_seen": {
            "type": "string",
            "description": "When it was last confirmed unchanged (RFC 3339)."
          },
          "neighbors": {
            "$ref": "#/components/schemas/NeighborSet",
            "description": "The adjacencies the node last reported."
          }
        }
      },
      "DashboardSaved": {
        "type": "object",
        "description": "A save's acknowledgement. The layout is not echoed back — the client already has it.",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          }
        }
      },
      "DependencyHealth": {
        "type": "object",
        "description": "Reachability of one backing dependency. Carries only a boolean and a human label — no connection\nstrings, no secrets.",
        "required": [
          "reachable",
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string"
          },
          "reachable": {
            "type": "boolean"
          }
        }
      },
      "Dependents": {
        "type": "object",
        "description": "Alerts attributed upstream to this incident.",
        "required": [
          "named",
          "total"
        ],
        "properties": {
          "named": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The named dependents, capped — see `total` for how many there actually are."
          },
          "total": {
            "type": "integer",
            "description": "How many there are in total — kept separately so truncation is visible rather than silent.",
            "minimum": 0
          }
        }
      },
      "DestKind": {
        "type": "string",
        "description": "How a destination is spoken to.",
        "enum": [
          "syslog_udp",
          "syslog_tcp",
          "syslog_tls",
          "snmp_trap_udp",
          "flow_udp",
          "bigquery"
        ]
      },
      "DestStatus": {
        "type": "object",
        "description": "A destination's runtime status, as the API serializes it.",
        "required": [
          "id",
          "name",
          "sent",
          "filtered",
          "dropped",
          "errors",
          "rendered",
          "queue_depth",
          "circuit_open"
        ],
        "properties": {
          "circuit_open": {
            "type": "boolean",
            "description": "Whether the circuit breaker is currently open (sends are being dropped fast)."
          },
          "dropped": {
            "type": "integer",
            "format": "int64",
            "description": "Messages dropped without being sent (full queue, rate cap, or open circuit).",
            "minimum": 0
          },
          "errors": {
            "type": "integer",
            "format": "int64",
            "description": "Failed sends.",
            "minimum": 0
          },
          "filtered": {
            "type": "integer",
            "format": "int64",
            "description": "Messages the filter rejected.",
            "minimum": 0
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Destination id."
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Last error text, truncated."
          },
          "last_success_unix_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Last successful send, Unix ms; `None` if there has not been one."
          },
          "name": {
            "type": "string",
            "description": "Destination name."
          },
          "queue_depth": {
            "type": "integer",
            "format": "int64",
            "description": "Messages currently queued for this destination.",
            "minimum": 0
          },
          "rendered": {
            "type": "integer",
            "format": "int64",
            "description": "Messages sent re-rendered because no raw payload was available, despite `verbatim`.",
            "minimum": 0
          },
          "sent": {
            "type": "integer",
            "format": "int64",
            "description": "Messages handed to the collector.",
            "minimum": 0
          }
        }
      },
      "Direction": {
        "type": "string",
        "description": "Which way a metric breaches its bound.",
        "enum": [
          "above",
          "below"
        ]
      },
      "DiscoveredEndpointCursor": {
        "type": "object",
        "description": "Keyset cursor for the next page.",
        "required": [
          "last_seen",
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_seen": {
            "type": "string"
          }
        }
      },
      "DiscoveredEndpointPage": {
        "type": "object",
        "description": "One page of discovered endpoints, most recently seen first.",
        "required": [
          "endpoints",
          "summary"
        ],
        "properties": {
          "endpoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiscoveredEndpointRow"
            }
          },
          "next": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DiscoveredEndpointCursor",
                "description": "Pass back as `before_last_seen`+`before_id`; `null` ⇒ this was the last page."
              }
            ]
          },
          "summary": {
            "$ref": "#/components/schemas/DiscoveredEndpointSummary"
          }
        }
      },
      "DiscoveredEndpointRow": {
        "type": "object",
        "description": "One address the fleet has resolved on the wire but does not monitor.",
        "required": [
          "id",
          "ip",
          "first_seen",
          "last_seen"
        ],
        "properties": {
          "first_seen": {
            "type": "string",
            "description": "When it was first seen anywhere in the fleet (RFC 3339)."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "ip": {
            "type": "string",
            "description": "The endpoint's address."
          },
          "last_seen": {
            "type": "string",
            "description": "When it was last confirmed still present (RFC 3339)."
          },
          "mac": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its hardware address, lowercase colon-separated hex; `null` for an incomplete ARP entry."
          },
          "promoted_node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node this address became, once it is monitored; `null` while it is still unmonitored."
          },
          "via_ifindex": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The SNMP ifIndex it was resolved on — the port it is behind.",
            "minimum": 0
          },
          "via_node": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Which monitored node resolved it; `null` once that node has been deleted."
          }
        }
      },
      "DiscoveredEndpointSummary": {
        "type": "object",
        "description": "How much of the fleet's ARP data this list was built from.",
        "required": [
          "observed_total",
          "nodes_reporting",
          "truncated_nodes"
        ],
        "properties": {
          "nodes_reporting": {
            "type": "integer",
            "format": "int64",
            "description": "How many nodes have reported an ARP/ND cache at all."
          },
          "observed_total": {
            "type": "integer",
            "format": "int64",
            "description": "Total endpoints observed across the fleet, before dedup and before the unmonitored filter."
          },
          "truncated_nodes": {
            "type": "integer",
            "format": "int64",
            "description": "How many of those hit a cap, making their contribution a sample rather than a total."
          }
        }
      },
      "DiskUsage": {
        "type": "object",
        "description": "Usage of one watched filesystem (or a store-size proxy, e.g. the PostgreSQL database size which\ncore cannot `statvfs`). `size_bytes == 0` means \"total capacity unknown\" — the value is a bare\ngrowing size (used only), not a fraction of a disk.",
        "required": [
          "mount",
          "used_bytes",
          "size_bytes"
        ],
        "properties": {
          "mount": {
            "type": "string",
            "description": "Friendly mount label (e.g. `root`, `metrics`, `database`) — a stable, low-cardinality name,\nnever a raw device path, so it is safe as a TSDB label."
          },
          "size_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Total filesystem capacity in bytes; `0` when unknown (capacity not measurable).",
            "minimum": 0
          },
          "used_bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes in use on the filesystem (or the store's size when `size_bytes == 0`).",
            "minimum": 0
          }
        }
      },
      "DnsAnswer": {
        "type": "object",
        "description": "One answer record plus its TTL.\n\nThe TTL is **display-only**: it counts down between polls, so including it in the content key\nwould make every single poll register as a change.",
        "required": [
          "record",
          "ttl"
        ],
        "properties": {
          "record": {
            "$ref": "#/components/schemas/DnsRecord",
            "description": "The record itself."
          },
          "ttl": {
            "type": "integer",
            "format": "int32",
            "description": "Time-to-live as reported by the resolver, in seconds.",
            "minimum": 0
          }
        }
      },
      "DnsChain": {
        "type": "object",
        "description": "One observed resolution chain — the artifact of a DNS check.\n\nProduced by the transport, carried on `PollResult.dns_chain`, persisted to PostgreSQL. **Never\na TSDB label** (ADR-011); it is the same tier as the interface inventory and `sys_descr`.",
        "required": [
          "query",
          "record_type",
          "resolver",
          "hops",
          "resolve_ms"
        ],
        "properties": {
          "failure": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DnsFailure",
                "description": "`None` ⇒ resolved. A failed chain may still carry hops (e.g. one CNAME, then NXDOMAIN)."
              }
            ]
          },
          "hops": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DnsHop"
            },
            "description": "The hops in walk order. Order is significant and is never sorted."
          },
          "query": {
            "type": "string",
            "description": "The name originally asked for (normalized)."
          },
          "record_type": {
            "$ref": "#/components/schemas/DnsRecordType",
            "description": "The record type asked for."
          },
          "resolve_ms": {
            "type": "number",
            "format": "double",
            "description": "Total wall-clock milliseconds for the walk. **Not** part of the content key."
          },
          "resolver": {
            "type": "string",
            "description": "Where we asked, rendered for display (e.g. `10.0.0.53:53` or `system`). Provenance, **not**\ncontent: swapping resolvers while the answer stays the same is not a change."
          }
        }
      },
      "DnsChainChange": {
        "type": "object",
        "description": "One append-on-change history row.",
        "required": [
          "id",
          "at",
          "chain",
          "resolved"
        ],
        "properties": {
          "at": {
            "type": "string"
          },
          "chain": {
            "$ref": "#/components/schemas/DnsChain"
          },
          "failure_kind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DnsFailureKind"
              }
            ]
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "prev_chain_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "resolved": {
            "type": "boolean"
          }
        }
      },
      "DnsChainCurrent": {
        "type": "object",
        "description": "The node's current resolution chain, plus how long it has held.",
        "required": [
          "chain",
          "resolved",
          "first_seen",
          "last_seen"
        ],
        "properties": {
          "chain": {
            "$ref": "#/components/schemas/DnsChain"
          },
          "failure_kind": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DnsFailureKind"
              }
            ]
          },
          "first_seen": {
            "type": "string"
          },
          "last_seen": {
            "type": "string"
          },
          "resolved": {
            "type": "boolean"
          }
        }
      },
      "DnsChainHistory": {
        "type": "object",
        "description": "One page of chain changes, newest first.",
        "required": [
          "changes"
        ],
        "properties": {
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DnsChainChange"
            }
          },
          "next": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DnsHistoryCursor",
                "description": "Pass back as `before_at`+`before_id` for the next page; `null` ⇒ this was the last one."
              }
            ]
          }
        }
      },
      "DnsCheckConfig": {
        "type": "object",
        "description": "A node's DNS-monitoring configuration (1:1 with the node).",
        "required": [
          "name"
        ],
        "properties": {
          "max_depth": {
            "type": "integer",
            "format": "int32",
            "description": "Maximum CNAME hops before giving up (default 8).",
            "minimum": 0
          },
          "name": {
            "type": "string",
            "description": "The name to resolve, e.g. `horryworks.net`. Stored normalized (lowercase, no trailing dot)."
          },
          "record_type": {
            "$ref": "#/components/schemas/DnsRecordType",
            "description": "Which record type the chain must reach (default `A`)."
          },
          "resolver": {
            "type": [
              "string",
              "null"
            ],
            "description": "Recursive resolver to query. `None` ⇒ the poller container's system resolver."
          },
          "resolver_port": {
            "type": "integer",
            "format": "int32",
            "description": "Resolver port (default 53).",
            "minimum": 0
          },
          "timeout_ms": {
            "type": "integer",
            "format": "int32",
            "description": "**Total** budget for the whole chain walk, in milliseconds (default 3000).",
            "minimum": 0
          }
        }
      },
      "DnsCheckRow": {
        "type": "object",
        "description": "A DNS monitor's configuration (1:1 with its node).",
        "required": [
          "node_id",
          "name",
          "record_type",
          "resolver_port",
          "max_depth",
          "timeout_ms"
        ],
        "properties": {
          "max_depth": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "record_type": {
            "type": "string"
          },
          "resolver_ip": {
            "type": [
              "string",
              "null"
            ]
          },
          "resolver_port": {
            "type": "integer",
            "format": "int32"
          },
          "timeout_ms": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DnsFailure": {
        "oneOf": [
          {
            "type": "object",
            "description": "Authoritative \"no such name\" (RCODE 3).",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "nx_domain"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "NOERROR, but no record of the requested type and no CNAME to follow.",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "no_data"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "The resolver failed to answer the question (RCODE 2).",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "serv_fail"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "The resolver refused to answer (RCODE 5).",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "refused"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "Any other response code, kept numeric so a new RCODE is never lost.",
            "required": [
              "rcode",
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "other_rcode"
                ]
              },
              "rcode": {
                "type": "integer",
                "format": "int32",
                "description": "The raw DNS response code.",
                "minimum": 0
              }
            }
          },
          {
            "type": "object",
            "description": "The resolver did not answer within the check's budget.",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "timeout"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "A CNAME pointed at a name already visited in this chain.",
            "required": [
              "at",
              "kind"
            ],
            "properties": {
              "at": {
                "type": "string",
                "description": "The name the loop closed on."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "loop_detected"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "The chain was longer than the configured `max_depth`.",
            "required": [
              "max_depth",
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "depth_exceeded"
                ]
              },
              "max_depth": {
                "type": "integer",
                "format": "int32",
                "description": "The limit that was hit.",
                "minimum": 0
              }
            }
          },
          {
            "type": "object",
            "description": "The response could not be decoded or did not match the question asked.",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "malformed"
                ]
              }
            }
          }
        ],
        "description": "Why a resolution did not reach a terminal record set."
      },
      "DnsFailureKind": {
        "type": "string",
        "description": "Why a resolution failed, without the detail that distinguishes one instance from another — the\n`failure_kind` column, and what the API serves for grouping.",
        "enum": [
          "nx_domain",
          "no_data",
          "serv_fail",
          "refused",
          "other_rcode",
          "timeout",
          "loop_detected",
          "depth_exceeded",
          "malformed"
        ]
      },
      "DnsHistoryCursor": {
        "type": "object",
        "description": "Keyset cursor for the next page (ADR-019 — never OFFSET).",
        "required": [
          "at",
          "id"
        ],
        "properties": {
          "at": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "DnsHop": {
        "type": "object",
        "description": "One hop of a resolution chain: the name asked about and the answers that came back for it.",
        "required": [
          "name",
          "answers"
        ],
        "properties": {
          "answers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DnsAnswer"
            },
            "description": "The answers whose owner is `name`, canonicalized (sorted, deduped, capped)."
          },
          "name": {
            "type": "string",
            "description": "The name queried at this hop (normalized)."
          }
        }
      },
      "DnsRecord": {
        "oneOf": [
          {
            "type": "object",
            "description": "A CNAME alias target (normalized: lowercase, no trailing dot).",
            "required": [
              "target",
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "cname"
                ]
              },
              "target": {
                "type": "string",
                "description": "The name this hop is an alias for."
              }
            }
          },
          {
            "type": "object",
            "description": "An IPv4 address record.",
            "required": [
              "addr",
              "kind"
            ],
            "properties": {
              "addr": {
                "type": "string",
                "description": "The resolved IPv4 address."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "a"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "An IPv6 address record.",
            "required": [
              "addr",
              "kind"
            ],
            "properties": {
              "addr": {
                "type": "string",
                "description": "The resolved IPv6 address."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "aaaa"
                ]
              }
            }
          }
        ],
        "description": "One record in an answer set.\n\nTyped rather than a rendered `String` so ordering is **numeric**: `Ipv4Addr`'s `Ord` compares\noctets, so `9.9.9.9` sorts before `10.1.2.3`. Text ordering gets that backwards, which would\nmake the canonical form depend on how the resolver happened to rotate a round-robin RRset."
      },
      "DnsRecordType": {
        "type": "string",
        "description": "Which record type a DNS check resolves to. Stored as an UPPERCASE token (the `record_type`\ncolumn).\n\n`Cname` is a legitimate terminal type: it answers \"what is this name an alias for?\" without\nchasing on to an address.",
        "enum": [
          "A",
          "AAAA",
          "CNAME"
        ]
      },
      "EnabledBody": {
        "type": "object",
        "description": "The body of an enable/disable toggle — `{\"enabled\": true}`.\n\nShared rather than per-domain because it already was: the maintenance module reached across for\n`super::EnabledBody` while it was declared inside the notifications block, which is the same\ncross-domain reach that keeps turning up as a migration tripwire.",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "ErrorDetail": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine-readable code. Clients branch on this, never on the message."
          },
          "message": {
            "type": "string",
            "description": "Operator-facing sentence. Safe to display; never carries an internal error's own text."
          }
        }
      },
      "EventAction": {
        "type": "string",
        "description": "What the pipeline did with an event. When several rules match one event, the row records the\nstrongest outcome.",
        "enum": [
          "none",
          "info",
          "suppressed",
          "cleared",
          "refreshed",
          "fired"
        ]
      },
      "EventKind": {
        "type": "string",
        "description": "What kind of passive event a poller (or core, for webhooks) received.",
        "enum": [
          "syslog",
          "trap",
          "webhook"
        ]
      },
      "EventMatchKind": {
        "type": "string",
        "description": "How a rule's pattern is matched against the event text.",
        "enum": [
          "substring",
          "regex",
          "unknown"
        ]
      },
      "EventRow": {
        "type": "object",
        "description": "One received event, as served by `GET /api/v1/events`.",
        "required": [
          "id",
          "kind",
          "at_unix_ms",
          "recorded_at",
          "message",
          "action"
        ],
        "properties": {
          "action": {
            "$ref": "#/components/schemas/EventAction"
          },
          "app_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "at_unix_ms": {
            "type": "integer",
            "format": "int64"
          },
          "facility": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "hostname": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/EventKind"
          },
          "matched_rule_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "message": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "recorded_at": {
            "type": "string",
            "format": "date-time"
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "source_ip": {
            "type": [
              "string",
              "null"
            ]
          },
          "syslog_severity": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "trap_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Well-known MIB name for `trap_oid` (e.g. `linkDown`), derived at read time; `None`\nfor syslog/webhook events or an OID outside the curated set."
          },
          "trap_oid": {
            "type": [
              "string",
              "null"
            ]
          },
          "varbinds": {}
        }
      },
      "EventRuleBody": {
        "type": "object",
        "required": [
          "name",
          "match_kind",
          "pattern",
          "severity"
        ],
        "properties": {
          "clear_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "match_kind": {
            "type": "string"
          },
          "min_count": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pattern": {
            "type": "string"
          },
          "severity": {
            "type": "string"
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "source_kind": {
            "type": [
              "string",
              "null"
            ]
          },
          "ttl_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "window_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          }
        }
      },
      "EventRuleRow": {
        "type": "object",
        "description": "A passive-event match rule.",
        "required": [
          "id",
          "name",
          "enabled",
          "match_kind",
          "pattern",
          "severity",
          "ttl_secs",
          "min_count",
          "window_secs"
        ],
        "properties": {
          "clear_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "match_kind": {
            "type": "string"
          },
          "min_count": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pattern": {
            "type": "string"
          },
          "severity": {
            "type": "string"
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "source_kind": {
            "type": [
              "string",
              "null"
            ]
          },
          "ttl_secs": {
            "type": "integer",
            "format": "int32"
          },
          "window_secs": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "EventRuleTest": {
        "type": "object",
        "description": "Body for the interactive rule tester.",
        "required": [
          "match_kind",
          "pattern",
          "sample"
        ],
        "properties": {
          "clear_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "match_kind": {
            "type": "string"
          },
          "pattern": {
            "type": "string"
          },
          "sample": {
            "type": "string"
          }
        }
      },
      "EventSourceRow": {
        "type": "object",
        "description": "A passive-event ingest source.",
        "required": [
          "id",
          "name",
          "kind",
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "EventSourceView": {
        "type": "object",
        "description": "A webhook ingest source, as served by the API (never includes the token hash).",
        "required": [
          "id",
          "name",
          "kind",
          "enabled",
          "created_at"
        ],
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "$ref": "#/components/schemas/EventKind"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "EventStatBucket": {
        "type": "object",
        "description": "One categorical `/events/stats` bucket: a stable `key` (for the React key + fallback display), an\noptional display `label` resolved server-side (e.g. a trap's MIB name), an optional `node_id`\n(set for source grouping when the source maps to an inventory node, so the UI resolves its name\n— no raw UUID rule), and the row count.",
        "required": [
          "key",
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "key": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "EventStats": {
        "oneOf": [
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventTimeBucket"
            },
            "description": "`group_by=time`: the volume series."
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventStatBucket"
            },
            "description": "Every other `group_by`: count-ordered categorical buckets."
          }
        ],
        "description": "The two row shapes `/events/stats` answers with, as one type.\n\n`#[serde(untagged)]`, so the bytes are exactly the bare array either arm used to serialize on its\nown — the union exists because a `Response` names no shape at all in the generated contract, and\na client that has to guess between two arrays guesses wrong on one of them."
      },
      "EventTimeBucket": {
        "type": "object",
        "description": "One time bucket for the `/events/stats?group_by=time` volume series: a bucket-start timestamp\n(Unix ms), the total count, and — when `split=kind` — the per-kind breakdown.",
        "required": [
          "ts_unix_ms",
          "count"
        ],
        "properties": {
          "by_kind": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "integer",
              "format": "int64"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "count": {
            "type": "integer",
            "format": "int64"
          },
          "ts_unix_ms": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ExpectedStatus": {
        "oneOf": [
          {
            "type": "object",
            "description": "Any 2xx (the default).",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "two_xx"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "An explicit set of acceptable codes.",
            "required": [
              "codes",
              "kind"
            ],
            "properties": {
              "codes": {
                "type": "array",
                "items": {
                  "type": "integer",
                  "format": "int32",
                  "minimum": 0
                }
              },
              "kind": {
                "type": "string",
                "enum": [
                  "exact"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "An inclusive range `[lo, hi]`.",
            "required": [
              "lo",
              "hi",
              "kind"
            ],
            "properties": {
              "hi": {
                "type": "integer",
                "format": "int32",
                "minimum": 0
              },
              "kind": {
                "type": "string",
                "enum": [
                  "range"
                ]
              },
              "lo": {
                "type": "integer",
                "format": "int32",
                "minimum": 0
              }
            }
          }
        ],
        "description": "Which HTTP status codes count as \"up\". Serialized as a tagged object (the `expected_status`\nJSONB column), e.g. `{\"kind\":\"two_xx\"}` / `{\"kind\":\"exact\",\"codes\":[200,204]}`."
      },
      "FilterExpr": {
        "type": "object",
        "description": "A destination's filter as stored and edited. `{}` deserializes to \"match everything\".",
        "properties": {
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Condition"
            },
            "description": "The conditions; empty means match everything."
          },
          "mode": {
            "$ref": "#/components/schemas/FilterMode",
            "description": "How [`Self::conditions`] combine."
          }
        }
      },
      "FilterField": {
        "type": "string",
        "description": "Which datum a condition inspects.",
        "enum": [
          "source_ip",
          "pool",
          "kind",
          "facility",
          "severity",
          "hostname",
          "app_name",
          "message",
          "trap_oid",
          "varbind",
          "src_addr",
          "dst_addr",
          "proto",
          "src_port",
          "dst_port",
          "src_as",
          "dst_as"
        ]
      },
      "FilterMode": {
        "type": "string",
        "description": "How the conditions combine.",
        "enum": [
          "all",
          "any"
        ]
      },
      "FilterOp": {
        "type": "string",
        "description": "What a condition does with the datum.",
        "enum": [
          "eq",
          "ne",
          "contains",
          "not_contains",
          "prefix",
          "regex",
          "not_regex",
          "in_list",
          "in_cidr",
          "not_in_cidr",
          "lte",
          "gte"
        ]
      },
      "FleetCoverage": {
        "type": "object",
        "description": "Fleet data-coverage summary: fresh vs total nodes + the stale watchlist.",
        "required": [
          "total",
          "fresh",
          "coverage_pct",
          "stale"
        ],
        "properties": {
          "coverage_pct": {
            "type": "integer",
            "format": "int64",
            "description": "Percent of nodes reporting fresh data (100 when the inventory is empty)."
          },
          "fresh": {
            "type": "integer",
            "minimum": 0
          },
          "stale": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StaleNode"
            },
            "description": "The stale nodes by name, capped at [`STALE_WATCHLIST_MAX`]; `total - fresh` is the real\ncount, so a truncated list is still legible against the totals above it."
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "FleetGroupSummary": {
        "type": "object",
        "description": "The per-group rollup response: `group_id → direct-member state counts`.",
        "required": [
          "groups"
        ],
        "properties": {
          "groups": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/GroupStateCounts"
            },
            "propertyNames": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "FleetStateHistory": {
        "type": "object",
        "description": "Node-state counts over time, pivoted into per-state series on a shared timestamp axis.",
        "required": [
          "timestamps",
          "series"
        ],
        "properties": {
          "series": {
            "type": "object",
            "description": "One aligned series per state. Keyed off [`NodeState::ALL`], so every state is present with\nzeroes even if it never occurred in the window — the chart's series set must not change\nshape depending on what happened to the fleet.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "integer",
                "format": "int64"
              }
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "timestamps": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            }
          }
        }
      },
      "FleetSummary": {
        "type": "object",
        "description": "Total node count plus a per-state tally.\n\nThe `states` keys are **always all six** and always sum to `total`, so a client can index them\nblind. Shared with the MCP `get_fleet_summary` tool, which used to build its own version that\nomitted zeroes.",
        "required": [
          "total",
          "states"
        ],
        "properties": {
          "states": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "format": "int64"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "FlowAsAgg": {
        "type": "object",
        "description": "An autonomous-system aggregate. `asn = 0` means unknown (the UI labels it accordingly). `name`\nis resolved from the IP→ASN table at the API layer (the store leaves it `None`).",
        "required": [
          "asn",
          "bytes",
          "packets",
          "flows"
        ],
        "properties": {
          "asn": {
            "type": "integer",
            "format": "int32",
            "description": "Autonomous-system number (0 = unknown).",
            "minimum": 0
          },
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "flows": {
            "type": "integer",
            "format": "int64",
            "description": "Distinct flows.",
            "minimum": 0
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "AS organization name, if resolvable."
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          }
        }
      },
      "FlowConversation": {
        "type": "object",
        "description": "A conversation: a src→dst pair with summed traffic. `src_asn`/`dst_asn` are the stored\nper-flow AS numbers (0 = unknown); the `*_as_name` fields are resolved from the IP→ASN table\nat the API layer (the store leaves them `None`), mirroring [`FlowAsAgg`].",
        "required": [
          "src",
          "dst",
          "src_asn",
          "dst_asn",
          "bytes",
          "packets",
          "flows"
        ],
        "properties": {
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "dst": {
            "type": "string",
            "description": "Destination address."
          },
          "dst_as_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Destination AS organization name, if resolvable (filled at the API layer)."
          },
          "dst_asn": {
            "type": "integer",
            "format": "int32",
            "description": "Destination autonomous-system number (0 = unknown).",
            "minimum": 0
          },
          "flows": {
            "type": "integer",
            "format": "int64",
            "description": "Distinct flows.",
            "minimum": 0
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          },
          "src": {
            "type": "string",
            "description": "Source address."
          },
          "src_as_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source AS organization name, if resolvable (filled at the API layer)."
          },
          "src_asn": {
            "type": "integer",
            "format": "int32",
            "description": "Source autonomous-system number (0 = unknown).",
            "minimum": 0
          }
        }
      },
      "FlowPoint": {
        "type": "object",
        "description": "A trend point: bytes/packets for one protocol at one 5-minute bucket.",
        "required": [
          "ts_unix_ms",
          "proto",
          "bytes",
          "packets"
        ],
        "properties": {
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          },
          "proto": {
            "type": "integer",
            "format": "int32",
            "description": "IP protocol number.",
            "minimum": 0
          },
          "ts_unix_ms": {
            "type": "integer",
            "format": "int64",
            "description": "Bucket start, Unix ms."
          }
        }
      },
      "FlowPortAgg": {
        "type": "object",
        "description": "A destination-port aggregate.",
        "required": [
          "port",
          "bytes",
          "packets",
          "flows"
        ],
        "properties": {
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "flows": {
            "type": "integer",
            "format": "int64",
            "description": "Distinct flows.",
            "minimum": 0
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          },
          "port": {
            "type": "integer",
            "format": "int32",
            "description": "Destination port.",
            "minimum": 0
          }
        }
      },
      "FlowProtoAgg": {
        "type": "object",
        "description": "A protocol aggregate.",
        "required": [
          "proto",
          "bytes",
          "packets",
          "flows"
        ],
        "properties": {
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "flows": {
            "type": "integer",
            "format": "int64",
            "description": "Distinct flows.",
            "minimum": 0
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          },
          "proto": {
            "type": "integer",
            "format": "int32",
            "description": "IP protocol number.",
            "minimum": 0
          }
        }
      },
      "FlowTalker": {
        "type": "object",
        "description": "A top-talker: one host address with summed traffic.",
        "required": [
          "addr",
          "bytes",
          "packets",
          "flows"
        ],
        "properties": {
          "addr": {
            "type": "string",
            "description": "Host address (v4 or v6, normalized from ClickHouse's v4-mapped form)."
          },
          "bytes": {
            "type": "integer",
            "format": "int64",
            "description": "Bytes.",
            "minimum": 0
          },
          "flows": {
            "type": "integer",
            "format": "int64",
            "description": "Distinct flows.",
            "minimum": 0
          },
          "packets": {
            "type": "integer",
            "format": "int64",
            "description": "Packets.",
            "minimum": 0
          }
        }
      },
      "ForwardDestination": {
        "type": "object",
        "description": "A destination as the API exposes it — no secrets, ever.",
        "required": [
          "id",
          "name",
          "enabled",
          "source_kind",
          "dest_kind",
          "target",
          "verbatim",
          "filter",
          "has_secret"
        ],
        "properties": {
          "ca_cert": {
            "type": [
              "string",
              "null"
            ],
            "description": "Extra PEM certificate(s) trusted for a TLS destination, on top of the system roots. Not a\nsecret — a CA certificate is public — so it round-trips through the API like any other field."
          },
          "dest_kind": {
            "$ref": "#/components/schemas/DestKind",
            "description": "How the collector is spoken to."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the forwarder currently sends to it."
          },
          "filter": {
            "$ref": "#/components/schemas/FilterExpr",
            "description": "The filter; `{}` forwards the whole stream."
          },
          "has_secret": {
            "type": "boolean",
            "description": "Whether a sealed secret is stored (so the UI can show \"configured\" without revealing it)."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable id."
          },
          "name": {
            "type": "string",
            "description": "Human label (unique)."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Restrict to one poller pool; `None` = every pool."
          },
          "rate_limit_per_sec": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Optional messages/second ceiling.",
            "minimum": 0
          },
          "source_kind": {
            "$ref": "#/components/schemas/SourceKind",
            "description": "Which received stream is teed."
          },
          "target": {
            "type": "string",
            "description": "`host:port` of the collector."
          },
          "verbatim": {
            "type": "boolean",
            "description": "`true` = relay original bytes, `false` = rebuild from parsed fields."
          }
        }
      },
      "ForwardDestinationBody": {
        "type": "object",
        "description": "Request body for creating/updating a forwarding destination.",
        "required": [
          "name",
          "source_kind",
          "dest_kind",
          "target"
        ],
        "properties": {
          "ca_cert": {
            "type": [
              "string",
              "null"
            ],
            "description": "PEM certificate(s) to trust for a TLS destination, in addition to the system roots. Not a\nsecret, so unlike `community` it round-trips and an empty value clears it."
          },
          "community": {
            "type": [
              "string",
              "null"
            ],
            "description": "SNMP community for re-encoded traps (`snmp_trap_udp` only). Sealed at rest; on update,\nomitting it keeps the stored value."
          },
          "dest_kind": {
            "$ref": "#/components/schemas/DestKind",
            "description": "How to speak to the collector."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the forwarder should send to it. Defaults to enabled."
          },
          "filter": {
            "$ref": "#/components/schemas/FilterExpr",
            "description": "The filter; omitted = forward the whole stream."
          },
          "name": {
            "type": "string",
            "description": "Human label (unique, 1–120 chars)."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Restrict to one poller pool; omitted/null = every pool."
          },
          "rate_limit_per_sec": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Optional messages/second ceiling.",
            "minimum": 0
          },
          "service_account_json": {
            "type": [
              "string",
              "null"
            ],
            "description": "Google service-account key JSON for a `bigquery` destination. Sealed at rest; on update,\nomitting it keeps the stored key. Omitting it on create selects Workload Identity (the\nGCE/GKE metadata server), which stores no secret at all."
          },
          "source_kind": {
            "$ref": "#/components/schemas/SourceKind",
            "description": "Which received stream to tee."
          },
          "target": {
            "type": "string",
            "description": "`host:port` of the collector."
          },
          "verbatim": {
            "type": "boolean",
            "description": "Relay the original bytes (default) rather than re-rendering from the parsed fields."
          }
        }
      },
      "ForwardDestinationRow": {
        "type": "object",
        "description": "A forwarding destination. Its optional sealed secret is not carried; a destination that had one\narrives disabled.",
        "required": [
          "id",
          "name",
          "enabled",
          "source_kind",
          "dest_kind",
          "target",
          "verbatim",
          "filter"
        ],
        "properties": {
          "ca_cert": {
            "type": [
              "string",
              "null"
            ]
          },
          "dest_kind": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "filter": {},
          "had_secret": {
            "type": "boolean",
            "description": "Whether the source deployment had a sealed secret on this destination. Carries no secret —\nit is what tells the importer to arrive disabled and what tells the operator to re-enter it."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "rate_limit_per_sec": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "source_kind": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "verbatim": {
            "type": "boolean"
          }
        }
      },
      "ForwardingStatus": {
        "type": "object",
        "description": "The `GET /api/v1/forwarding/status` body.",
        "required": [
          "destinations",
          "pollers_without_raw_capture",
          "pollers_without_flow_relay",
          "sending"
        ],
        "properties": {
          "destinations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DestStatus"
            },
            "description": "Runtime counters, one entry per running destination."
          },
          "pollers_without_flow_relay": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Online pollers that relay no flow datagrams at all, so a flow destination fed only by these\nreceives nothing."
          },
          "pollers_without_raw_capture": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Online pollers that cannot attach the original bytes, so their traffic degrades to rendered."
          },
          "sending": {
            "type": "boolean",
            "description": "False on an HA standby, whose dispatcher is not running (destination CRUD still works)."
          }
        }
      },
      "GeoSource": {
        "type": "string",
        "description": "Where a group's effective map position came from.",
        "enum": [
          "own",
          "inherited",
          "unset"
        ]
      },
      "GroupBody": {
        "type": "object",
        "description": "Create/update body for a group. `group_type` is a validated [`GroupType`] key.",
        "required": [
          "name",
          "group_type"
        ],
        "properties": {
          "group_type": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poll-pool this folder assigns to its nodes (ADR-009/020). Same three-state contract as a\nnode's: **absent** leaves it unchanged, `\"\"` clears it (inherit from the nearest ancestor,\nelse the default pool), otherwise it moves the folder's nodes to that pool."
          }
        }
      },
      "GroupGeo": {
        "type": "object",
        "description": "A folder's map pin. Both fields or neither — see [`set_node_group_geo`].",
        "properties": {
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          }
        }
      },
      "GroupNodes": {
        "type": "object",
        "description": "One group's direct members. Not keyset-paged — a folder is loaded whole when it is expanded —\nso it reports truncation instead of offering a cursor.",
        "required": [
          "nodes",
          "truncated"
        ],
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeSummary"
            }
          },
          "truncated": {
            "type": "boolean"
          }
        }
      },
      "GroupPlacement": {
        "type": "object",
        "description": "Drag-reorder a group: re-parent it under `parent_id` (`null` ⇒ top level) and position it\nrelative to a sibling. `before`/`after` name the sibling; both omitted ⇒ append.",
        "properties": {
          "after": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "before": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "GroupStateCounts": {
        "type": "object",
        "description": "Per-group direct-member state tally. All six keys are always present (a missing state is `0`)\nand they sum to the group's direct-member count.",
        "required": [
          "ok",
          "warning",
          "critical",
          "unknown",
          "unreachable",
          "maintenance"
        ],
        "properties": {
          "critical": {
            "type": "integer",
            "format": "int64"
          },
          "maintenance": {
            "type": "integer",
            "format": "int64"
          },
          "ok": {
            "type": "integer",
            "format": "int64"
          },
          "unknown": {
            "type": "integer",
            "format": "int64"
          },
          "unreachable": {
            "type": "integer",
            "format": "int64"
          },
          "warning": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "GroupSummary": {
        "type": "object",
        "description": "One group row returned by the API. `group_type` is the snake_case key.",
        "required": [
          "id",
          "name",
          "group_type",
          "sort_order",
          "geo_source"
        ],
        "properties": {
          "effective_latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Where this group sits on the map after inheritance: its own coordinates, else the nearest\nancestor's, else null. Computed on every read; never stored.\n\n**These do not add a pin.** A group is drawn on the map only when `geo_source` is `own`;\nfor every other group this says which pin its nodes are counted at (`geo_group`)."
          },
          "effective_longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "geo_group": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The group that supplied the effective position: this group when `geo_source` is `own`, the\nancestor it inherited from when `inherited`, null when `unset`. This is the pin the group's\nnodes belong to, so a client never has to walk the folder tree itself."
          },
          "geo_source": {
            "$ref": "#/components/schemas/GeoSource",
            "description": "Whether the effective position is the group's own, inherited from an ancestor, or absent."
          },
          "group_type": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "The group's own geo coordinates, as stored (both set ⇒ drawn as a pin). A descendant\nfolder normally leaves these null and inherits — see the `effective_*` pair below."
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poll-pool this folder assigns to its nodes (ADR-009/020, migration 0054). `null` ⇒ inherit\nfrom the nearest ancestor that sets one, else the default pool. A node's own `pool` still\nwins — see [`crate::poolres`]."
          },
          "sort_order": {
            "type": "number",
            "format": "double",
            "description": "Manual order within the parent scope (the UI sorts siblings by this, then by name)."
          }
        }
      },
      "HostDiskRange": {
        "type": "object",
        "description": "A per-mount filesystem trend. The frontend derives % from the pair, or shows a bare-bytes trend\nwhen `size_bytes` is all zero (the `database` size proxy has no capacity).",
        "required": [
          "mount",
          "used_bytes",
          "size_bytes"
        ],
        "properties": {
          "mount": {
            "type": "string"
          },
          "size_bytes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "used_bytes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          }
        }
      },
      "HostInfo": {
        "type": "object",
        "description": "One self-monitored host: current resource values for the core process's host (`role=\"core\"`) or\na poller's (`role=\"poller\"`).",
        "required": [
          "instance",
          "role",
          "online",
          "disks"
        ],
        "properties": {
          "cpu_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Current CPU utilization % (0–100); `null` when no sample yet."
          },
          "disk_used_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Highest watched-filesystem used %, for at-a-glance columns; `null` when none has a capacity."
          },
          "disks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DiskUsage"
            },
            "description": "Current per-watched-filesystem usage."
          },
          "instance": {
            "type": "string",
            "description": "`core` or the poller id."
          },
          "load1": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Current 1-minute load average; `null` when no sample / unavailable on the platform."
          },
          "mem_total_bytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Total physical memory, bytes; `null` when no sample.",
            "minimum": 0
          },
          "mem_used_bytes": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Memory in use, bytes; `null` when no sample.",
            "minimum": 0
          },
          "mem_used_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Memory-used %, derived; `null` when total is unknown."
          },
          "online": {
            "type": "boolean",
            "description": "Whether the source is currently reporting (core is always online; a poller within its\nheartbeat window)."
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pool the poller serves; `null` for core."
          },
          "role": {
            "type": "string",
            "description": "`\"core\"` or `\"poller\"`."
          }
        }
      },
      "HostMetricRange": {
        "type": "object",
        "description": "The scalar host trends plus a per-mount filesystem trend, all over one window — one round trip\nper instance/range change.",
        "required": [
          "instance",
          "cpu_pct",
          "load1",
          "load5",
          "load15",
          "mem_used_bytes",
          "mem_total_bytes",
          "disks"
        ],
        "properties": {
          "cpu_pct": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "disks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HostDiskRange"
            }
          },
          "instance": {
            "type": "string"
          },
          "load1": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "load15": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "load5": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "mem_total_bytes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          },
          "mem_used_bytes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          }
        }
      },
      "HttpMethod": {
        "type": "string",
        "description": "HTTP request method for a URL check. Stored as an UPPERCASE token (the `method` column).",
        "enum": [
          "GET",
          "HEAD",
          "POST"
        ]
      },
      "ImportDiscovered": {
        "type": "object",
        "description": "Import body: the selected devices to create as nodes.",
        "required": [
          "nodes"
        ],
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportNode"
            }
          }
        }
      },
      "ImportEndpoint": {
        "type": "object",
        "description": "What to call the endpoint, and what to bind it to, when promoting it to a node.",
        "properties": {
          "credential_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Node name. Defaults to the address when omitted or blank."
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ImportNode": {
        "type": "object",
        "description": "One discovered device the operator chose to add.",
        "required": [
          "address",
          "name"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "credential_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Maker/model pre-filled from discovery's sysDescr classification (editable before import)."
          }
        }
      },
      "ImportReport": {
        "type": "object",
        "description": "The outcome of an import.",
        "required": [
          "dry_run",
          "tables",
          "notes"
        ],
        "properties": {
          "dry_run": {
            "type": "boolean",
            "description": "True when nothing was committed: the whole import ran and was rolled back."
          },
          "notes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BundleNote"
            },
            "description": "What was skipped or changed, and why."
          },
          "tables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TableResult"
            },
            "description": "Per-table counts, in dependency order."
          }
        }
      },
      "ImportResult": {
        "type": "object",
        "description": "How many nodes an import created.",
        "required": [
          "created"
        ],
        "properties": {
          "created": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "IncidentContext": {
        "type": "object",
        "description": "Exactly what the model was shown about the incident, so an answer can be checked rather than\ntrusted (ADR-029). Stored beside the answer; also what makes a bad answer reviewable later.",
        "required": [
          "generated_at_s",
          "window_secs",
          "root_node_id",
          "node",
          "alert",
          "dependents",
          "upstream",
          "timeline",
          "recent_changes"
        ],
        "properties": {
          "alert": {
            "$ref": "#/components/schemas/AlertFacts",
            "description": "The alert on that node."
          },
          "dependents": {
            "$ref": "#/components/schemas/Dependents",
            "description": "Alerts rolled up under this one."
          },
          "generated_at_s": {
            "type": "integer",
            "format": "int64",
            "description": "When the context was assembled (Unix seconds), so the prompt can express ages rather than\nabsolute times the model has no clock for."
          },
          "node": {
            "$ref": "#/components/schemas/NodeFacts",
            "description": "The node being explained — the root cause, after any roll-up hop."
          },
          "recent_changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChangeFacts"
            },
            "description": "Recent audited configuration changes touching this node."
          },
          "root_node_id": {
            "type": "string",
            "format": "uuid",
            "description": "Id of the node being explained. Differs from the one the operator clicked whenever the\nroll-up hop fired, and it is what a generated report is filed under — a report explains the\ncause, so it belongs to the cause."
          },
          "timeline": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IncidentSignal"
            },
            "description": "Cross-signal timeline for the window, oldest first."
          },
          "upstream": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeFacts"
            },
            "description": "Inventory ancestors, nearest first. Present even when healthy: \"the parent is fine\" is\nevidence that the failure is local to this node."
          },
          "window_secs": {
            "type": "integer",
            "format": "int64",
            "description": "How far back the timeline reaches."
          }
        }
      },
      "IncidentSignal": {
        "type": "object",
        "description": "One dated signal on an incident timeline (`incident_correlate`).\n\n`Serialize` because an RCA report stores the timeline it was grounded in alongside the answer:\nthe UI shows the two together so a reader can check the explanation against its evidence rather\nthan taking it on faith (ADR-029).",
        "required": [
          "at_s",
          "severity",
          "kind",
          "label"
        ],
        "properties": {
          "at_s": {
            "type": "integer",
            "format": "int64"
          },
          "kind": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "severity": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "IngestedEvent": {
        "type": "object",
        "description": "The accepted event's id.",
        "required": [
          "event_id"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "InterfaceHeatmap": {
        "type": "object",
        "description": "A links × time grid. `values[i][j]` is link `i`'s throughput at `timestamps[j]`, so every row\nis the same length and the client can shade cells without bounds checks.",
        "required": [
          "links",
          "timestamps",
          "values",
          "partial"
        ],
        "properties": {
          "links": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "partial": {
            "type": "boolean",
            "description": "`true` when the link set covers only the groups the calling account may see and links it is\nentitled to may be missing. Always `false` for an account with unrestricted visibility."
          },
          "timestamps": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            }
          },
          "values": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "number",
                "format": "double"
              }
            }
          }
        }
      },
      "InterfaceRow": {
        "type": "object",
        "description": "One interface row for the node-detail Interfaces tab: stored metadata joined with query-time\n`rate()`/`latest()` metrics. Utilization is derived here and never stored (ADR-012).",
        "required": [
          "ifindex",
          "stale"
        ],
        "properties": {
          "if_alias": {
            "type": [
              "string",
              "null"
            ]
          },
          "if_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "if_speed_bps": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "ifindex": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "in_bps": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "in_util_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "last_seen_unix": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "oper_status": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "out_bps": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "out_util_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "stale": {
            "type": "boolean"
          }
        }
      },
      "InterfaceSeries": {
        "type": "object",
        "description": "Per-interface time-series for the node-detail Interfaces pane: In/Out throughput (bits/sec,\nfrom `rate()` of the octet counters) and In/Out errors (per second).\n\nAll four share one `timestamps` axis — the union of returned points, with `null` in the gaps —\nso the chart gets aligned series rather than four independently-indexed ones. Derived at query\ntime (ADR-012); empty when there is no history.",
        "required": [
          "timestamps",
          "in_bps",
          "out_bps",
          "in_errors",
          "out_errors"
        ],
        "properties": {
          "in_bps": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "in_errors": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "out_bps": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "out_errors": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "timestamps": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            }
          }
        }
      },
      "InterfaceTopEntry": {
        "type": "object",
        "description": "One ranked interface in a fleet interface Top-N.",
        "required": [
          "node_id",
          "node_name",
          "ifindex",
          "value"
        ],
        "properties": {
          "if_alias": {
            "type": [
              "string",
              "null"
            ]
          },
          "if_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "if_speed_bps": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Configured speed (bits/sec) for util%; `null` if unknown."
          },
          "ifindex": {
            "type": "integer",
            "format": "int32"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "node_name": {
            "type": "string"
          },
          "value": {
            "type": "number",
            "format": "double",
            "description": "bits/sec for throughput metrics, errors|discards per second otherwise."
          }
        }
      },
      "JsonExtract": {
        "type": "object",
        "description": "One number to lift out of a JSON response body and record as a metric.",
        "required": [
          "metric",
          "path"
        ],
        "properties": {
          "metric": {
            "type": "string",
            "description": "The metric name to record the value under, e.g. `queue_depth`. Must match\n`[A-Za-z_:][A-Za-z0-9_:]*` and must not be one of the names the monitor already emits."
          },
          "path": {
            "type": "string",
            "description": "Dot-separated path to the value, e.g. `data.queue.depth` or `items.0.value`. Array elements\nare indexed by number; `items[0].value` is accepted and means the same thing.\n\nNot a JSONPath expression: the path names exactly one location, so the rule always produces\neither one number or nothing."
          }
        }
      },
      "Language": {
        "type": "string",
        "description": "What language the answer should be written in.\n\nThe prompt is always English — instructions in one language keep the model's behaviour stable —\nbut the *answer* follows the reader. An operator reading a Japanese UI should not get an English\nexplanation of their own network.",
        "enum": [
          "en",
          "ja"
        ]
      },
      "LdapConfigInput": {
        "type": "object",
        "description": "The save payload from the Settings page.",
        "required": [
          "host",
          "bind_dn",
          "user_base_dn"
        ],
        "properties": {
          "bind_dn": {
            "type": "string"
          },
          "bind_password": {
            "type": [
              "string",
              "null"
            ],
            "description": "Write-only credential. Two-valued, **not** three: `None` keeps what is stored, a non-blank\nvalue replaces it. An empty string is a validation error rather than \"clear\", because a bind\nwith a DN and no password is an unauthenticated bind that a permissive directory answers\n`success` — so \"no password\" is not a configuration, it is a silent downgrade to anonymous."
          },
          "ca_cert": {
            "type": [
              "string",
              "null"
            ]
          },
          "default_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "group_base_dn": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_filter": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_name_attribute": {
            "type": "string"
          },
          "host": {
            "type": "string"
          },
          "member_of_attribute": {
            "type": "string"
          },
          "port": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "role_map": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "security": {
            "$ref": "#/components/schemas/LdapSecurity"
          },
          "uid_attribute": {
            "type": "string"
          },
          "user_base_dn": {
            "type": "string"
          },
          "user_filter": {
            "type": "string"
          },
          "username_attribute": {
            "type": "string"
          }
        }
      },
      "LdapConfigResponse": {
        "type": "object",
        "description": "The directory configuration, or `null` when none has been saved.",
        "properties": {
          "config": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LdapConfigView",
                "description": "`null` rather than a 404: \"not configured\" is the normal state of a fresh installation, and\nthe settings form wants to render its empty self rather than an error."
              }
            ]
          }
        }
      },
      "LdapConfigView": {
        "type": "object",
        "description": "The configuration as the Settings page shows it — **never** the bind password.",
        "required": [
          "host",
          "port",
          "security",
          "bind_dn",
          "has_bind_password",
          "user_base_dn",
          "user_filter",
          "username_attribute",
          "uid_attribute",
          "member_of_attribute",
          "group_name_attribute",
          "role_map",
          "enabled",
          "updated_at"
        ],
        "properties": {
          "bind_dn": {
            "type": "string"
          },
          "ca_cert": {
            "type": [
              "string",
              "null"
            ],
            "description": "The operator-supplied CA certificate, in PEM. A certificate is public, so unlike the bind\npassword it round-trips through the form rather than being write-only."
          },
          "default_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "group_base_dn": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_filter": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_name_attribute": {
            "type": "string"
          },
          "has_bind_password": {
            "type": "boolean",
            "description": "True once a bind password has been stored, so the form can say \"set\" without revealing it."
          },
          "host": {
            "type": "string"
          },
          "member_of_attribute": {
            "type": "string"
          },
          "port": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "role_map": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "security": {
            "$ref": "#/components/schemas/LdapSecurity"
          },
          "uid_attribute": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "user_base_dn": {
            "type": "string"
          },
          "user_filter": {
            "type": "string"
          },
          "username_attribute": {
            "type": "string"
          }
        }
      },
      "LdapSecurity": {
        "type": "string",
        "description": "How the connection is protected. **Two variants, both TLS** — there is deliberately no plaintext\noption, so `ldap://` cannot be configured into existence and the bind password cannot cross the\nwire in the clear. Adding one later would be a certificate-verification-disable flag by another\nname and needs the same argument (ADR-041 decision 2).",
        "enum": [
          "ldaps",
          "starttls"
        ]
      },
      "LdapTestBody": {
        "type": "object",
        "description": "Which account, if any, the test should look up.",
        "properties": {
          "username": {
            "type": [
              "string",
              "null"
            ],
            "description": "A username to resolve. Optional: with none, the check still proves the connection, the TLS\ntrust and the service account's bind. With one, it also reports the DN, the groups and the\nrole that user would receive — **without** binding as them, so it can neither be used as a\ncredential-testing proxy into the directory nor push anybody towards their domain's lockout\nthreshold."
          }
        }
      },
      "LdapTestResult": {
        "type": "object",
        "description": "The Test button's result.\n\nStaged rather than a single boolean on purpose. This probe cannot prove that *logging in* works,\nbecause it deliberately never binds as the user (see [`probe`]) — so an `ok: true` alone would\nbe read as \"login works\" when the directory may still refuse simple binds, or the account may be\ndisabled. Naming the stages says exactly how far it got.",
        "required": [
          "ok",
          "stages",
          "groups",
          "groups_truncated",
          "note"
        ],
        "properties": {
          "groups": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "groups_truncated": {
            "type": "boolean"
          },
          "note": {
            "type": "string",
            "description": "What this probe did not test, so a green result is not over-read."
          },
          "ok": {
            "type": "boolean",
            "description": "Every stage passed."
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "The role this user would receive. **`None` means they would be denied** — the commonest\nmisconfiguration, and one the login form reports as an indistinguishable wrong password."
          },
          "stages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LdapTestStage"
            }
          },
          "subject_present": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the entry carried the configured id attribute — the flag, not the value. Its absence\nis the failure this field exists to surface, and the value itself is of no use here."
          },
          "user_dn": {
            "type": [
              "string",
              "null"
            ]
          },
          "username_resolved": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LdapTestStage": {
        "type": "object",
        "description": "One step of the Test button's report.",
        "required": [
          "name",
          "ok"
        ],
        "properties": {
          "detail": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it failed, or what it found. Truncated — this is remote-influenced text."
          },
          "name": {
            "type": "string",
            "description": "`connect` | `bind_service` | `search_user` | `resolve_groups`."
          },
          "ok": {
            "type": "boolean"
          }
        }
      },
      "LinkDirection": {
        "type": "string",
        "description": "Which end of a link is upstream.",
        "enum": [
          "a_parent",
          "b_parent"
        ]
      },
      "LinkOverrideAction": {
        "type": "string",
        "description": "What an operator has decided about a link, overriding whatever the derivation produces.",
        "enum": [
          "pin",
          "hide",
          "direction"
        ]
      },
      "LinkOverrideList": {
        "type": "object",
        "description": "Every operator decision visible to the caller.",
        "required": [
          "overrides"
        ],
        "properties": {
          "overrides": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkOverrideRow"
            }
          }
        }
      },
      "LinkOverrideRequest": {
        "type": "object",
        "description": "A decision to record about one link.",
        "required": [
          "a_node",
          "b_node",
          "action"
        ],
        "properties": {
          "a_node": {
            "type": "string",
            "format": "uuid",
            "description": "One endpoint. Order is not significant — the pair is canonicalized before storing, and a\n`direction` is re-expressed to match."
          },
          "action": {
            "$ref": "#/components/schemas/LinkOverrideAction",
            "description": "`pin`, `hide` or `direction`."
          },
          "b_node": {
            "type": "string",
            "format": "uuid",
            "description": "The other endpoint."
          },
          "direction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LinkDirection",
                "description": "Which endpoint is upstream. Required when `action` is `direction`, rejected otherwise."
              }
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text note for whoever reads this decision later."
          }
        }
      },
      "LinkOverrideRow": {
        "type": "object",
        "description": "One operator decision about one link.",
        "required": [
          "id",
          "a_node",
          "b_node",
          "action",
          "created_at"
        ],
        "properties": {
          "a_node": {
            "type": "string",
            "format": "uuid",
            "description": "The lower-ordered endpoint. Endpoints are stored in a canonical order, so this is not\nnecessarily the one that was submitted first."
          },
          "action": {
            "$ref": "#/components/schemas/LinkOverrideAction"
          },
          "b_node": {
            "type": "string",
            "format": "uuid",
            "description": "The higher-ordered endpoint."
          },
          "created_at": {
            "type": "string",
            "description": "When it was recorded (RFC 3339)."
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who recorded the decision."
          },
          "direction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LinkDirection",
                "description": "Which endpoint is upstream. Present only when `action` is `direction`."
              }
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LinkSource": {
        "type": "string",
        "description": "What kind of evidence produced a link, ordered strongest first.",
        "enum": [
          "manual",
          "lldp",
          "cdp",
          "ospf",
          "route",
          "bgp",
          "l3_subnet"
        ]
      },
      "LlmConfigInput": {
        "type": "object",
        "description": "The `PUT /api/v1/llm/config` body.",
        "required": [
          "provider",
          "model"
        ],
        "properties": {
          "api_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Write-only credential. Three-valued on purpose:\n* `None` — keep whatever is stored (so editing the model does not require re-entering a key);\n* `Some(\"\")` — clear it, which is how an operator moves Vertex onto Workload Identity;\n* `Some(key)` — replace it."
          },
          "enabled": {
            "type": "boolean"
          },
          "location": {
            "type": "string"
          },
          "max_output_tokens": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "minimum": 0
          },
          "model": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          }
        }
      },
      "LlmConfigResponse": {
        "type": "object",
        "description": "The `GET /api/v1/llm/config` body.",
        "required": [
          "providers"
        ],
        "properties": {
          "config": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LlmConfigView",
                "description": "`null` until a provider has been configured — the normal state of a fresh installation."
              }
            ]
          },
          "providers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProviderChoice"
            },
            "description": "Every provider the operator may choose, with its placeholders and its egress warning."
          }
        }
      },
      "LlmConfigView": {
        "type": "object",
        "description": "What `GET /api/v1/llm/config` returns. No secret, by construction.",
        "required": [
          "provider",
          "model",
          "project",
          "location",
          "enabled",
          "max_output_tokens",
          "has_api_key",
          "leaves_operator_boundary",
          "updated_at"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "has_api_key": {
            "type": "boolean",
            "description": "True once a credential has been stored, so the form can show \"set\" without revealing it."
          },
          "leaves_operator_boundary": {
            "type": "boolean",
            "description": "Whether this provider sends incident context outside the operator's own cloud. Computed\nserver-side so the warning the UI shows cannot drift from what the backend actually does."
          },
          "location": {
            "type": "string"
          },
          "max_output_tokens": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "model": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "LlmTestResult": {
        "type": "object",
        "description": "The provider-test outcome. `ok: false` is a *successful* request reporting a failed probe — the\nprovider configuration is the caller's, and the typed error is what tells them which part of it\nis wrong, so this is not a 5xx.",
        "required": [
          "ok"
        ],
        "properties": {
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "latency_ms": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "ok": {
            "type": "boolean"
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LoginBody": {
        "type": "object",
        "description": "Login request body. Never logged, never echoed.",
        "required": [
          "username",
          "password"
        ],
        "properties": {
          "password": {
            "type": "string"
          },
          "username": {
            "type": "string"
          }
        }
      },
      "LoginOk": {
        "type": "object",
        "description": "A freshly issued session.",
        "required": [
          "token",
          "role"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role",
            "description": "The role it carries, so the UI can render the right navigation immediately."
          },
          "token": {
            "type": "string",
            "description": "The bearer token for subsequent requests."
          }
        }
      },
      "MerakiCadenceReq": {
        "type": "object",
        "required": [
          "availability_secs",
          "uplink_secs",
          "traffic_secs",
          "inventory_secs",
          "enabled_tiers",
          "target_rps"
        ],
        "properties": {
          "availability_secs": {
            "type": "integer",
            "format": "int32"
          },
          "enabled_tiers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "inventory_secs": {
            "type": "integer",
            "format": "int32"
          },
          "target_rps": {
            "type": "number",
            "format": "double"
          },
          "traffic_secs": {
            "type": "integer",
            "format": "int32"
          },
          "uplink_secs": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "MerakiCandidate": {
        "type": "object",
        "required": [
          "serial",
          "name",
          "product_type",
          "network_id",
          "network_name"
        ],
        "properties": {
          "lan_ip": {
            "type": [
              "string",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "network_id": {
            "type": "string"
          },
          "network_name": {
            "type": "string"
          },
          "product_type": {
            "type": "string"
          },
          "serial": {
            "type": "string"
          }
        }
      },
      "MerakiCreated": {
        "type": "object",
        "description": "How many organizations an onboarding batch created.",
        "required": [
          "created"
        ],
        "properties": {
          "created": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "MerakiDeviceConfig": {
        "type": "object",
        "description": "A node's Meraki-device binding (1:1 with the node). No secrets: the org API key is held by the\n`meraki_orgs` row's credential and inlined by core at dispatch time (ADR-018/020).",
        "required": [
          "org_uuid",
          "org_id",
          "serial",
          "network_id",
          "product_type"
        ],
        "properties": {
          "model": {
            "type": [
              "string",
              "null"
            ],
            "description": "Device model (e.g. \"MX67\") — display only."
          },
          "network_id": {
            "type": "string",
            "description": "The Meraki networkId the device belongs to."
          },
          "org_id": {
            "type": "string",
            "description": "The Meraki organizationId (the API path segment) — denormalised for display."
          },
          "org_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Internal handle of the owning `meraki_orgs` row."
          },
          "product_type": {
            "type": "string",
            "description": "Meraki productType (appliance/switch/wireless/…)."
          },
          "serial": {
            "type": "string",
            "description": "The device serial — the join key returned by the org-bulk endpoints."
          }
        }
      },
      "MerakiDiscoverReq": {
        "type": "object",
        "required": [
          "api_key"
        ],
        "properties": {
          "api_key": {
            "type": "string"
          },
          "base_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "MerakiEnabledReq": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "MerakiEnumeration": {
        "type": "object",
        "description": "What the import wizard reads in one call: the org's network scope, and the devices not yet\nimported.",
        "required": [
          "networks",
          "devices"
        ],
        "properties": {
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerakiCandidate"
            }
          },
          "networks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerakiNetworkView"
            }
          }
        }
      },
      "MerakiImportDeviceReq": {
        "type": "object",
        "required": [
          "serial",
          "product_type",
          "network_id"
        ],
        "properties": {
          "lan_ip": {
            "type": [
              "string",
              "null"
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "network_id": {
            "type": "string"
          },
          "network_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_type": {
            "type": "string"
          },
          "serial": {
            "type": "string"
          }
        }
      },
      "MerakiImportReq": {
        "type": "object",
        "required": [
          "org_uuid",
          "devices"
        ],
        "properties": {
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MerakiImportDeviceReq"
            }
          },
          "monitored_network_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "org_uuid": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "MerakiImported": {
        "type": "object",
        "description": "How many devices an import created.",
        "required": [
          "imported"
        ],
        "properties": {
          "imported": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "MerakiMonitoredReq": {
        "type": "object",
        "required": [
          "network_ids",
          "monitored"
        ],
        "properties": {
          "monitored": {
            "type": "boolean"
          },
          "network_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "MerakiNetworkView": {
        "type": "object",
        "required": [
          "network_id",
          "name",
          "monitored"
        ],
        "properties": {
          "monitored": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "network_id": {
            "type": "string"
          }
        }
      },
      "MerakiOrgOption": {
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "MerakiOrgView": {
        "type": "object",
        "required": [
          "id",
          "org_id",
          "name",
          "base_url",
          "enabled",
          "availability_secs",
          "uplink_secs",
          "traffic_secs",
          "inventory_secs",
          "enabled_tiers",
          "target_rps"
        ],
        "properties": {
          "availability_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "base_url": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "enabled_tiers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "inventory_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "org_id": {
            "type": "string"
          },
          "target_rps": {
            "type": "number",
            "format": "double"
          },
          "traffic_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "uplink_secs": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "MerakiPolling": {
        "type": "object",
        "description": "The global Meraki polling kill switch.",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "MerakiPollingReq": {
        "type": "object",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "MetricDimension": {
        "type": "string",
        "description": "The dimension a metric's series carry, which decides how it can be read.",
        "enum": [
          "none",
          "interface",
          "entity"
        ]
      },
      "MetricKind": {
        "type": "string",
        "description": "What a metric's values represent over time.",
        "enum": [
          "gauge",
          "counter"
        ]
      },
      "MetricPoint": {
        "type": "object",
        "description": "One point of a time series: Unix-seconds timestamp and value.",
        "required": [
          "t",
          "v"
        ],
        "properties": {
          "t": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp in seconds."
          },
          "v": {
            "type": "number",
            "format": "double",
            "description": "Sample value."
          }
        }
      },
      "MetricRange": {
        "type": "object",
        "description": "A time-series window for one node metric.",
        "required": [
          "node_id",
          "metric",
          "points"
        ],
        "properties": {
          "metric": {
            "type": "string"
          },
          "node_id": {
            "$ref": "#/components/schemas/NodeId"
          },
          "points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MetricPoint"
            }
          }
        }
      },
      "MetricReading": {
        "type": "object",
        "description": "Latest reading for one node metric.",
        "required": [
          "node_id",
          "metric",
          "value"
        ],
        "properties": {
          "metric": {
            "type": "string"
          },
          "node_id": {
            "$ref": "#/components/schemas/NodeId"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "MetricStatus": {
        "type": "string",
        "description": "Whether a metric is configured for collection, has data, or both.",
        "enum": [
          "ok",
          "no_data",
          "unconfigured"
        ]
      },
      "MibEntry": {
        "type": "object",
        "description": "One catalog entry returned by the API.",
        "required": [
          "id",
          "metric_name",
          "oid",
          "collection",
          "metric_kind"
        ],
        "properties": {
          "collection": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "metric_kind": {
            "type": "string"
          },
          "metric_name": {
            "type": "string"
          },
          "oid": {
            "type": "string"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "MonitoringGapRow": {
        "type": "object",
        "description": "One `monitoring_gaps` row (API shape). A gap is one core↔poller **visibility outage**: core\nstopped hearing from the poller (partition or the poller went down) and later saw it again. If the\npoller was alive but partitioned, its store-and-forward buffer backfills the metrics for the\nwindow on reconnect (Phase 3); alerts are *not* backfilled (they resume from \"now\").",
        "required": [
          "id",
          "poller_id",
          "pool",
          "started_at",
          "ended_at",
          "duration_secs",
          "recorded_at",
          "listeners"
        ],
        "properties": {
          "duration_secs": {
            "type": "integer",
            "format": "int64",
            "description": "Gap length in seconds (UI convenience)."
          },
          "ended_at": {
            "type": "string",
            "description": "End of the gap window (RFC 3339 — core heard from it again)."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Row id."
          },
          "listeners": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Passive listeners the poller had bound when the gap began (e.g. `syslog:514`, `trap:162`).\n\nEmpty ⇒ the poller had none, so the gap cost no passive data. Non-empty ⇒ whatever those\nlisteners would have received in the window is **gone**: syslog, traps and flow exports are\nfire-and-forget, so unlike active polling there is no buffer to backfill from. (SNMP informs\nare the exception — the sender retries until acknowledged.)"
          },
          "poller_id": {
            "type": "string",
            "description": "The poller whose visibility lapsed."
          },
          "pool": {
            "type": "string",
            "description": "Pool it serves."
          },
          "recorded_at": {
            "type": "string",
            "description": "When core recorded the gap (RFC 3339)."
          },
          "started_at": {
            "type": "string",
            "description": "Start of the gap window (RFC 3339 — core's last contact before the outage)."
          }
        }
      },
      "MuteScope": {
        "type": "string",
        "description": "Whether a mute targets a single node or a whole folder group (recursive).",
        "enum": [
          "node",
          "group"
        ]
      },
      "Neighbor": {
        "type": "object",
        "description": "One observed adjacency.\n\nThe first three string fields are the **identity**; everything below them is payload. Payload\nchanges still append a history row (a peer that was reimaged is a real change on that port), but\nthey never split one link into two records.",
        "required": [
          "proto",
          "local_port",
          "remote_chassis",
          "remote_port"
        ],
        "properties": {
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NeighborCapability"
            },
            "description": "What the peer says it is, normalized across both protocols."
          },
          "local_ifindex": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The local `ifIndex`, when the protocol genuinely supplies one. CDP indexes its cache by\n`ifIndex` so this is exact; LLDP's `lldpLocPortNum` is an arbitrary local index that only\n*often* equals `ifIndex`, so LLDP records leave this `None` rather than guess.",
            "minimum": 0
          },
          "local_port": {
            "type": "string",
            "description": "The local port, as the device names it: LLDP renders `lldpLocPortId` by its subtype, CDP\nuses `cdpInterfaceName`. Falls back to `port <n>` / `ifindex <n>` when the naming table has\nno row, so the record still has an identity rather than being dropped."
          },
          "proto": {
            "$ref": "#/components/schemas/NeighborProto",
            "description": "Which protocol reported this."
          },
          "remote_chassis": {
            "type": "string",
            "description": "The peer's chassis id, rendered by subtype: LLDP `lldpRemChassisId`, CDP `cdpCacheDeviceId`."
          },
          "remote_mgmt_addr": {
            "type": [
              "string",
              "null"
            ],
            "description": "The peer's management address, from `cdpCacheAddress` for CDP and from `lldpRemManAddrTable`\nfor LLDP. `None` when the peer advertised none."
          },
          "remote_platform": {
            "type": [
              "string",
              "null"
            ],
            "description": "`cdpCachePlatform` — the peer's hardware/software platform string (CDP only)."
          },
          "remote_port": {
            "type": "string",
            "description": "The peer's port id, rendered by subtype: LLDP `lldpRemPortId`, CDP `cdpCacheDevicePort`."
          },
          "remote_port_desc": {
            "type": [
              "string",
              "null"
            ],
            "description": "`lldpRemPortDesc` — the peer's own description of its port."
          },
          "remote_sys_desc": {
            "type": [
              "string",
              "null"
            ],
            "description": "`lldpRemSysDesc`."
          },
          "remote_sys_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "`lldpRemSysName`. CDP has no separate system name (its device id serves both)."
          }
        }
      },
      "NeighborCapability": {
        "type": "string",
        "description": "What the peer says it is, as one vocabulary shared by both protocols.\n\nLLDP reports this as a `BITS` value over `lldpRemSysCapEnabled` and CDP as a four-byte mask over\n`cdpCacheCapabilities`; the two bit layouts have nothing in common. Normalizing them here is\nwhat lets the UI render one column — the alternative is a per-protocol legend, which is the\n\"same fact in two shapes\" the extensibility rules exist to prevent.",
        "enum": [
          "router",
          "bridge",
          "switch",
          "wlan_ap",
          "phone",
          "host",
          "repeater",
          "cable_device",
          "igmp",
          "other"
        ]
      },
      "NeighborChange": {
        "type": "object",
        "description": "One append-on-change history row.",
        "required": [
          "id",
          "at",
          "neighbors"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "When the change was recorded (RFC 3339)."
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "neighbors": {
            "$ref": "#/components/schemas/NeighborSet",
            "description": "The adjacency as of this change."
          },
          "prev_neighbor_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "The content key this replaced; `null` marks the first observation ever recorded for the node."
          }
        }
      },
      "NeighborConfig": {
        "type": "object",
        "description": "How this deployment discovers connectivity: CDP/LLDP neighbours and interface addresses.",
        "required": [
          "enabled",
          "interval_secs"
        ],
        "properties": {
          "arp_enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether ARP / IPv6-neighbour walks are issued at all. Omitted on update leaves it unchanged.\n\nOff unless an operator turns it on: this walk reads a table sized by the network rather than\nby the device, and it is the only discovery walk here that costs a busy switch measurable\nwork. What it buys is the only answer nothing else can give — which hosts are on your\nsegments that Yagra is not monitoring."
          },
          "arp_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "How often each SNMP node's ARP / IPv6-neighbour tables are walked, in seconds. Omitted on\nupdate leaves it unchanged.",
            "minimum": 0
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether CDP/LLDP neighbour walks are issued at all."
          },
          "interval_secs": {
            "type": "integer",
            "format": "int32",
            "description": "How often each SNMP node's neighbour tables are walked, in seconds.",
            "minimum": 0
          },
          "l3_enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether interface-address walks are issued at all. Omitted on update leaves it unchanged."
          },
          "l3_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "How often each SNMP node's interface-address tables are walked, in seconds. Omitted on\nupdate leaves it unchanged.",
            "minimum": 0
          },
          "max_interval_secs": {
            "type": "integer",
            "format": "int32",
            "description": "Largest cadence this deployment accepts, in seconds.",
            "minimum": 0
          },
          "min_interval_secs": {
            "type": "integer",
            "format": "int32",
            "description": "Smallest cadence this deployment accepts, in seconds.",
            "minimum": 0
          },
          "routing_enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether routing-adjacency collection is issued at all. Omitted on update leaves it unchanged.\n\nOn unless an operator turns it off. This is what finds the links that share no subnet — a\npoint-to-point `/32`, an unnumbered OSPF link, an eBGP session across a segment — which the\nshared-subnet rule structurally cannot see. The tables it reads are sized by the device's own\npeering mesh, and the routing table itself is never walked: it is probed one destination at a\ntime."
          },
          "routing_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "How often each SNMP node's routing adjacency is collected, in seconds. Omitted on update\nleaves it unchanged.",
            "minimum": 0
          }
        }
      },
      "NeighborHistory": {
        "type": "object",
        "description": "One page of adjacency changes, newest first.",
        "required": [
          "changes"
        ],
        "properties": {
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NeighborChange"
            }
          },
          "next": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/NeighborHistoryCursor",
                "description": "Pass back as `before_at`+`before_id` for the next page; `null` ⇒ this was the last one."
              }
            ]
          }
        }
      },
      "NeighborHistoryCursor": {
        "type": "object",
        "description": "Keyset cursor for the next page (ADR-019 — never OFFSET).",
        "required": [
          "at",
          "id"
        ],
        "properties": {
          "at": {
            "type": "string"
          },
          "id": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "NeighborProto": {
        "type": "string",
        "description": "Which discovery protocol reported an adjacency.\n\nKept on every record rather than normalized away: a switch running both protocols reports the\nsame physical link twice with *different* identities (LLDP names the peer by chassis MAC, CDP by\nhostname), so collapsing them would mean guessing that two differently-identified rows are one\nlink. Showing both, labelled, is the honest answer.",
        "enum": [
          "lldp",
          "cdp"
        ]
      },
      "NeighborSet": {
        "type": "object",
        "description": "Every neighbour a node reports on one observation, as a set.\n\nThe unit of storage is the whole set per node, not one row per adjacency, because a partial walk\nmust never read as \"every neighbour disappeared\". The poller reports the set it could observe,\ncore replaces it atomically, and a failed walk sends no set at all — so nothing is written. A\nper-adjacency table would need an explicit \"this is complete\" flag to get the same guarantee.",
        "properties": {
          "neighbors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Neighbor"
            },
            "description": "The adjacencies, canonically ordered."
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether [`MAX_NEIGHBORS_PER_NODE`] was hit and rows were dropped. Reported rather than\nsilently swallowed — a truncated view that looks complete is worse than no view."
          }
        }
      },
      "NodeAssignment": {
        "type": "object",
        "description": "`GET /api/v1/nodes/:id/assignment` — the node's effective pool, where that pool came from, and\nwhich poller currently holds it.",
        "required": [
          "pool",
          "pool_source",
          "polled_by"
        ],
        "properties": {
          "polled_by": {
            "$ref": "#/components/schemas/PolledBy"
          },
          "pool": {
            "type": "string",
            "description": "Effective pool: the node's own, else the nearest ancestor folder's, else the default."
          },
          "pool_source": {
            "$ref": "#/components/schemas/PoolSource"
          },
          "pool_source_group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The folder that supplied the pool, when `pool_source` is `group`."
          }
        }
      },
      "NodeBindings": {
        "type": "object",
        "description": "Set/clear a node's profile + bound credential and its descriptive maker/model, and optionally\nmove it to a different poll-pool. The node-edit UI loads the current values and resends them, so\nan unchanged field is preserved.",
        "properties": {
          "credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poll-pool assignment (ADR-009). **Absent** = leave the pool unchanged; `\"\"` (or whitespace)\n= clear it to the `default` pool; otherwise move the node to that pool (validated as a\nNATS-subject-safe token). See [`validate_pool_update`]."
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NodeCollection": {
        "oneOf": [
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredCollectionItem"
            },
            "description": "Default: the node's own overrides, each with its id and scope."
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CollectionItem"
            },
            "description": "`?resolved=true`: the effective set after profile defaults, as the poller sees it."
          }
        ],
        "description": "The two shapes `GET /nodes/:id/collection` answers with, as one type.\n\n`#[serde(untagged)]`, so the bytes are the same bare array either arm always sent — the union\nexists because the response shape depends on a *query parameter*, which OpenAPI cannot express,\nand an undescribed body pushed the difference onto the client to guess. The stored view carries\nitem ids and scope; the resolved view is the poller's effective set and has neither."
      },
      "NodeDetail": {
        "type": "object",
        "description": "One node's configuration detail, including its bindings (profile/credential/parent) so the\nnode-detail page can show and edit them. Live mode only (PostgreSQL inventory).",
        "required": [
          "id",
          "name",
          "address",
          "kind"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "dns_check": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/DnsCheckConfig",
                "description": "DNS-monitor config when this node carries a `dns_checks` row; `null` otherwise."
              }
            ]
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The group this node belongs to; `null` ⇒ ungrouped."
          },
          "id": {
            "$ref": "#/components/schemas/NodeId"
          },
          "kind": {
            "$ref": "#/components/schemas/NodeKind",
            "description": "**What this node is** — the kind the scheduler actually polls it as, resolved by the one\nprecedence in [`NodeKind::resolve`].\n\nThe three configs below are the raw rows, and a node is not guaranteed to carry only one:\nthe API edge refuses a second, but rows predating that guard exist. Reading the configs and\nconcluding a kind from whichever is non-null is how the node page came to show a URL-monitor\nhealth card for a node the poller was treating as a Meraki device. Branch on this instead."
          },
          "meraki_device": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerakiDeviceConfig",
                "description": "Cisco Meraki binding when this node carries a `meraki_devices` row; `null` otherwise."
              }
            ]
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The node's **own** poll-pool (ADR-009/020); `null` ⇒ it inherits from its folder, else the\ndefault pool. Deliberately the raw stored value, not the effective one, so the edit form can\ntell an explicit assignment from an inherited one — the *effective* pool (and which poller\ncurrently holds the node) comes from `GET /nodes/:id/assignment`."
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "url_check": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/UrlCheckConfig",
                "description": "URL-monitor config when this node carries a `url_checks` row; `null` otherwise."
              }
            ]
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Descriptive maker/model, editable from the node detail."
          }
        }
      },
      "NodeFacts": {
        "type": "object",
        "description": "The subset of a node the model may see. Notably not the credential binding.",
        "required": [
          "name",
          "address",
          "tags"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poller pool — usually the site, which is often the diagnosis (\"everything in branch-osaka\")."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "array",
              "items": false,
              "prefixItems": [
                {
                  "type": "string"
                },
                {
                  "type": "string"
                }
              ]
            },
            "description": "Operator-set grouping attributes, capped and sorted for a deterministic prompt."
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NodeGroupAssignment": {
        "type": "object",
        "description": "Move a node into a group (or `null` to ungroup). Used by the inventory tree (drag/move).",
        "properties": {
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "NodeGroupRow": {
        "type": "object",
        "description": "A folder in the inventory tree.",
        "required": [
          "id",
          "name",
          "group_type",
          "sort_order"
        ],
        "properties": {
          "group_type": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "sort_order": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "NodeId": {
        "type": "string",
        "format": "uuid",
        "description": "Stable identifier for a monitored node.\n\nA UUID, not a name or address — both of which can change over a node's life."
      },
      "NodeKind": {
        "type": "string",
        "description": "A node's monitoring kind: the thing that decides which poll jobs it produces.\n\nVariants are declared in **precedence order**, which is the order [`NodeKind::resolve`] applies.\nA node should carry at most one single-purpose row — the API edge refuses the second — but a row\ncan predate that guard, so resolution has to be deterministic rather than depend on which lookup\nhappened to run first.\n\nBefore this type the same question was answered in three places that could disagree: the\nscheduler's Meraki short-circuit, the scheduler's URL-beats-DNS resolution, and the node-detail\nAPI — which applied no precedence at all and handed the UI every config it found, so a node the\nscheduler polled as Meraki could render a URL-monitor health card next to it.",
        "enum": [
          "meraki",
          "url",
          "dns",
          "device"
        ]
      },
      "NodeMetricEntry": {
        "type": "object",
        "description": "One metric on one node: what it is, whether it has data, and how it must be read.",
        "required": [
          "metric",
          "metric_kind",
          "dimension",
          "status",
          "series_count"
        ],
        "properties": {
          "dimension": {
            "$ref": "#/components/schemas/MetricDimension"
          },
          "metric": {
            "type": "string",
            "description": "The TSDB metric name."
          },
          "metric_kind": {
            "$ref": "#/components/schemas/MetricKind",
            "description": "Gauge vs raw counter. A counter's stored value is an odometer reading, so chart it with\n`rate=true` rather than plotting it directly."
          },
          "series_count": {
            "type": "integer",
            "format": "int32",
            "description": "How many series share this name on this node — the fan-out behind one entry.",
            "minimum": 0
          },
          "status": {
            "$ref": "#/components/schemas/MetricStatus"
          }
        }
      },
      "NodeNameEntry": {
        "type": "object",
        "description": "One resolved node id → display name (unresolved ids are omitted; the caller keeps the raw id).",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "NodeNamesReq": {
        "type": "object",
        "description": "Request body for `POST /api/v1/node-names`: the node ids whose display names to resolve.",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "NodePage": {
        "type": "object",
        "description": "One keyset page of the inventory.",
        "required": [
          "nodes"
        ],
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as `cursor` for the next page; `null` ⇒ this was the last one. Always `null` in\nsearch mode, which returns a single capped page by design."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NodeSummary"
            }
          }
        }
      },
      "NodeParentAssignment": {
        "type": "object",
        "description": "Set (or clear) a node's **dependency parent** (upstream). `parent_id: null` removes the\ndependency. This is the alert-suppression edge (parent down ⇒ suppress children, ADR-015) —\ndistinct from `PUT /nodes/:id/group`, which moves the node in the inventory folder tree.",
        "properties": {
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "NodePlacement": {
        "type": "object",
        "description": "Drag-reorder a node within (or into) a group, positioning it relative to a sibling node.\n`group_id` is the destination group (`null` ⇒ ungrouped); `before`/`after` name the sibling to\nland next to (both omitted ⇒ append to the end). At most one of before/after may be set.",
        "properties": {
          "after": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "before": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "NodeRow": {
        "type": "object",
        "description": "A monitored node. `credential_id` is a reference only — see the module docs.",
        "required": [
          "id",
          "name",
          "address",
          "sort_order",
          "tags"
        ],
        "properties": {
          "address": {
            "type": "string",
            "description": "IPv4 or IPv6, as text."
          },
          "credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "profile_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "sort_order": {
            "type": "number",
            "format": "double"
          },
          "tags": {},
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "NodeSearchResult": {
        "type": "object",
        "description": "One node-picker result: id + display name + address. Deliberately excludes credentials and\nbindings (security.md — the picker only needs to show and select a node).",
        "required": [
          "id",
          "name",
          "address"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "NodeState": {
        "type": "string",
        "description": "The current state of a monitored node or check.",
        "enum": [
          "ok",
          "warning",
          "critical",
          "unknown",
          "unreachable",
          "maintenance"
        ]
      },
      "NodeStatus": {
        "type": "object",
        "description": "One node's live status: its display state plus the alerts currently attributed to it, so node\ndetail can show *why* it is down without re-deriving from the list.",
        "required": [
          "node_id",
          "state",
          "alerts"
        ],
        "properties": {
          "alerts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Alert"
            }
          },
          "node_id": {
            "$ref": "#/components/schemas/NodeId"
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          }
        }
      },
      "NodeSummary": {
        "type": "object",
        "description": "One inventory row (mirrors the WebUI `NodeSummary`).",
        "required": [
          "id",
          "name",
          "address",
          "state",
          "sort_order",
          "kind"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The group this node belongs to (for the inventory tree); `null` ⇒ ungrouped."
          },
          "id": {
            "$ref": "#/components/schemas/NodeId"
          },
          "kind": {
            "$ref": "#/components/schemas/NodeKind",
            "description": "**What this node is**, and therefore how it is polled — the value that distinguishes a URL\nor DNS monitor from an ordinary ICMP/SNMP device in the inventory.\n\nResolved by `NodeKind::resolve`, the same function `GET /nodes/{id}` and the scheduler ask,\nso a list row can never disagree with the detail page it opens."
          },
          "model": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The node's **own** poll-pool; `null` ⇒ inherited from its folder, else the default pool.\nThe tree's pool picker edits exactly this value, so it is what marks the active choice —\nthe *effective* pool (and the poller holding the node) comes from `/nodes/:id/assignment`."
          },
          "sort_order": {
            "type": "number",
            "format": "double",
            "description": "Manual order within the group (the tree sorts members by this, then by name)."
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Descriptive maker/model for the \"name (addr) (vendor) (model)\" display."
          }
        }
      },
      "NodeSuppressionOptOut": {
        "type": "object",
        "description": "Whether this node is excluded from derived alert suppression.",
        "required": [
          "opt_out"
        ],
        "properties": {
          "opt_out": {
            "type": "boolean",
            "description": "`true` ⇒ this node's alerts always stand on their own, whatever the derived graph says."
          }
        }
      },
      "NoteCode": {
        "type": "string",
        "description": "Something the export or the import did that the operator would not otherwise see.\n\nA silent drop is the failure mode that matters here: a bundle that quietly left out half the\nrules imports without error and the operator finds out during an incident.",
        "enum": [
          "skipped_builtin",
          "skipped_missing_reference",
          "reference_dropped",
          "secret_dropped_imported_disabled",
          "webhook_token_reset",
          "schedule_next_run_recomputed"
        ]
      },
      "NotifyEvent": {
        "type": "string",
        "description": "Which point in an alert's life produced this notification.\n\nTemplates branch on it — a resolve usually wants different wording from a fire — so it is a\nvariable rather than three separate template fields.",
        "enum": [
          "fire",
          "resolve",
          "suppress"
        ]
      },
      "OidcCallbackBody": {
        "type": "object",
        "description": "OIDC callback body: the `code` + `state` the WebUI forwards from the IdP redirect.",
        "required": [
          "code",
          "state"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "state": {
            "type": "string"
          }
        }
      },
      "OidcProviderInput": {
        "type": "object",
        "description": "Create/update payload from the admin UI. `client_secret` is write-only: `None` on update keeps\nthe stored value (so editing other fields doesn't require re-entering the secret).",
        "required": [
          "name",
          "issuer",
          "client_id",
          "redirect_uri"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": [
              "string",
              "null"
            ]
          },
          "default_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "groups_claim": {
            "type": "string"
          },
          "issuer": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/OidcProviderKind",
            "description": "Which IdP product this is. Omitted ⇒ `generic`."
          },
          "name": {
            "type": "string"
          },
          "redirect_uri": {
            "type": "string"
          },
          "role_map": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "scopes": {
            "type": "string"
          }
        }
      },
      "OidcProviderKind": {
        "type": "string",
        "description": "Which IdP product a provider was configured for.\n\nDescriptive only: the login handshake is driven by `issuer`, `scopes` and `groups_claim`, and\nbehaves identically whichever product is named here. `generic` means the provider was defined\nfield by field rather than from a product's shape.",
        "enum": [
          "entra",
          "okta",
          "google",
          "generic"
        ]
      },
      "OidcProviderSummary": {
        "type": "object",
        "description": "Provider metadata for the admin API — **never** includes the client_secret.",
        "required": [
          "id",
          "name",
          "kind",
          "issuer",
          "client_id",
          "redirect_uri",
          "scopes",
          "groups_claim",
          "role_map",
          "enabled",
          "has_secret"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "default_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "groups_claim": {
            "type": "string"
          },
          "has_secret": {
            "type": "boolean",
            "description": "True once a client_secret has been stored (so the UI can show \"set\" without revealing it)."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "issuer": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/OidcProviderKind",
            "description": "Which IdP product this provider was configured for."
          },
          "name": {
            "type": "string"
          },
          "redirect_uri": {
            "type": "string"
          },
          "role_map": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "propertyNames": {
              "type": "string"
            }
          },
          "scopes": {
            "type": "string"
          }
        }
      },
      "OidcSession": {
        "type": "object",
        "description": "A session minted by a completed SSO login — the same shape local login returns, deliberately, so\nthe WebUI stores a token the same way whichever path produced it.",
        "required": [
          "token",
          "role"
        ],
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "token": {
            "type": "string"
          }
        }
      },
      "Ok_": {
        "type": "object",
        "description": "`{\"ok\": true}` — the body of a successful mutation that has nothing else to say.",
        "required": [
          "ok"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          }
        }
      },
      "PermissionInfo": {
        "type": "object",
        "description": "One permission in the role/privilege matrix.",
        "required": [
          "key",
          "label",
          "description"
        ],
        "properties": {
          "description": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        }
      },
      "PollNowResult": {
        "type": "object",
        "description": "What an out-of-schedule poll dispatched.",
        "required": [
          "dispatched",
          "node_id",
          "pool"
        ],
        "properties": {
          "dispatched": {
            "type": "integer",
            "description": "How many poll jobs went to the bus. Results arrive asynchronously on the normal result\npath, so this confirms dispatch, not completion.",
            "minimum": 0
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "pool": {
            "type": "string",
            "description": "The pool the jobs were published to — the node's *effective* pool, which may be inherited\nfrom its folder rather than set on the node."
          }
        }
      },
      "PolledBy": {
        "type": "object",
        "description": "Which poller currently polls a node — the node detail's \"Polled by\" fact.",
        "required": [
          "state"
        ],
        "properties": {
          "poller_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The owning poller; set only in the `assigned` state."
          },
          "state": {
            "type": "string",
            "description": "One of `assigned`, `legacy_fanout`, `pending`, `meraki`, `unknown`."
          }
        }
      },
      "PollerAnchorRequest": {
        "type": "object",
        "description": "Where a poller attaches to the monitored network.",
        "properties": {
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node the poller sits behind. `null` clears the anchor, returning the poller to being\nplaced by its own reported addresses."
          }
        }
      },
      "PollerInfo": {
        "type": "object",
        "description": "One poller in the `GET /api/v1/pollers` response — a merge of the live registry (current\nstatus/telemetry) and the durable inventory (so an offline poller still lists). No secrets.",
        "required": [
          "id",
          "pool",
          "status",
          "working_set_nodes",
          "working_set_specs",
          "results_total",
          "mgmt_addrs"
        ],
        "properties": {
          "anchor_node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node this poller attaches to, naming where it sits in the derived dependency graph.\n`null` ⇒ core places it from `mgmt_addrs` instead."
          },
          "cpu_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Current host CPU utilization % (0–100) from its latest heartbeat; `null` when the poller is\noffline or on an N-1 build without host telemetry."
          },
          "disk_used_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Highest watched-filesystem used % (0–100); `null` when unavailable."
          },
          "first_seen": {
            "type": [
              "string",
              "null"
            ],
            "description": "First durably-recorded contact (RFC 3339); `null` if not yet persisted."
          },
          "id": {
            "type": "string",
            "description": "Sanitized poller id (stable across restarts)."
          },
          "last_seen": {
            "type": [
              "string",
              "null"
            ],
            "description": "Last durably-recorded contact (RFC 3339); `null` for a live poller not yet persisted (it\nregisters within the 60s inventory-upsert throttle window)."
          },
          "mem_used_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Current host memory-used % (0–100); `null` when unavailable."
          },
          "mgmt_addrs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Interface addresses the poller reported for itself. Empty for an older poller build, and\nempty for a containerized poller whose only address is a container-network one."
          },
          "pool": {
            "type": "string",
            "description": "Pool it serves (live view wins; else the durable row)."
          },
          "results_total": {
            "type": "integer",
            "format": "int64",
            "description": "Poll results core has consumed from it since core started.",
            "minimum": 0
          },
          "status": {
            "type": "string",
            "description": "`\"online\"` when it is beating within the offline window, else `\"offline\"`."
          },
          "version": {
            "type": [
              "string",
              "null"
            ],
            "description": "Build version from its latest heartbeat (or the durable row when it is offline)."
          },
          "working_set_nodes": {
            "type": "integer",
            "format": "int32",
            "description": "Working-set node count it last reported (0 when offline / never reported).",
            "minimum": 0
          },
          "working_set_specs": {
            "type": "integer",
            "format": "int32",
            "description": "Working-set spec count it last reported.",
            "minimum": 0
          }
        }
      },
      "PollerNodeRef": {
        "type": "object",
        "description": "One node in the poller drill-down.",
        "required": [
          "id",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "PollerNodesResponse": {
        "type": "object",
        "description": "`GET /api/v1/pollers/:id/nodes` body.",
        "required": [
          "poller_id",
          "state",
          "total",
          "truncated",
          "nodes"
        ],
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PollerNodeRef"
            }
          },
          "poller_id": {
            "type": "string"
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "The pool it serves; `null` unless it is live."
          },
          "state": {
            "type": "string",
            "description": "`assigned` (live, working set known), `offline` (unknown or not beating), or `unknown`\n(this core is an HA standby and runs no coordinator)."
          },
          "total": {
            "type": "integer",
            "description": "Nodes in its working set, before the page cap.",
            "minimum": 0
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether `nodes` is a capped page of `total`."
          }
        }
      },
      "PollersResponse": {
        "type": "object",
        "description": "The `GET /api/v1/pollers` body: the fleet of pollers + the per-pool summary.",
        "required": [
          "pollers",
          "pools"
        ],
        "properties": {
          "pollers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PollerInfo"
            }
          },
          "pools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PoolSummary"
            }
          }
        }
      },
      "PoolAssignment": {
        "type": "object",
        "description": "Move a node (or a folder) to a poll-pool, or clear it back to inherited. Absent or `\"\"` ⇒ NULL\n(inherit from the folder, else the default pool).",
        "properties": {
          "pool": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PoolOption": {
        "type": "object",
        "description": "One pool offered by the pool picker.",
        "required": [
          "name",
          "live"
        ],
        "properties": {
          "live": {
            "type": "boolean",
            "description": "Whether a live poller currently serves it. A pool with none takes the legacy per-job path\nonto a subject nothing subscribes to, so its jobs are silently discarded — the picker has to\nsay so rather than present it as an equivalent choice."
          },
          "name": {
            "type": "string",
            "description": "Pool name."
          }
        }
      },
      "PoolOptions": {
        "type": "object",
        "description": "The pools that exist, for the assignment picker.",
        "required": [
          "pools"
        ],
        "properties": {
          "pools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PoolOption"
            }
          }
        }
      },
      "PoolSource": {
        "type": "string",
        "description": "Where a node's effective pool came from, so the UI can say \"inherited from the Tokyo folder\"\nrather than just showing a name.",
        "enum": [
          "node",
          "group",
          "default"
        ]
      },
      "PoolSummary": {
        "type": "object",
        "description": "One pool in the `GET /api/v1/pollers` response — node count vs. live pollers, its dispatch mode,\nand a warning when it has nodes but no live poller (they would go unmonitored).",
        "required": [
          "pool",
          "nodes",
          "live_pollers",
          "mode"
        ],
        "properties": {
          "live_pollers": {
            "type": "integer",
            "description": "Live (online) pollers serving this pool.",
            "minimum": 0
          },
          "mode": {
            "type": "string",
            "description": "`\"working_set\"` when a live poller serves it, else `\"legacy\"` (per-job fallback)."
          },
          "nodes": {
            "type": "integer",
            "description": "Non-Meraki nodes assigned to this pool.",
            "minimum": 0
          },
          "pool": {
            "type": "string",
            "description": "Pool name (`default` for unassigned nodes)."
          },
          "warning": {
            "type": [
              "string",
              "null"
            ],
            "description": "`\"nodes_without_live_poller\"` when the pool has nodes but no live poller, else `null`."
          }
        }
      },
      "PreviewProblem": {
        "type": "object",
        "description": "One field that could not be used.",
        "required": [
          "field",
          "reason",
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "`subject` or `body`."
          },
          "message": {
            "type": "string",
            "description": "The engine's message, including the offending line where it knows it."
          },
          "reason": {
            "type": "string",
            "description": "`compile`, `render`, `too_large`, or `not_json`."
          }
        }
      },
      "PreviewRequest": {
        "type": "object",
        "description": "A template to render against a representative alert.",
        "required": [
          "kind"
        ],
        "properties": {
          "body": {
            "type": [
              "string",
              "null"
            ]
          },
          "event": {
            "$ref": "#/components/schemas/NotifyEvent",
            "description": "Which point in an alert's life to render: `fire`, `resolve`, or `suppress`."
          },
          "kind": {
            "$ref": "#/components/schemas/ChannelKind",
            "description": "The channel kind the template is for. Decides whether the body has to be valid JSON."
          },
          "subject": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PreviewResult": {
        "type": "object",
        "description": "What the template produces, or what stopped it.",
        "required": [
          "subject",
          "body",
          "problems"
        ],
        "properties": {
          "body": {
            "type": "string",
            "description": "The rendered body, under the same rule."
          },
          "json_valid": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the rendered body parses as JSON. `null` when this channel kind sends the body as\nplain text, where the question does not apply."
          },
          "problems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreviewProblem"
            },
            "description": "One entry per field that could not be rendered and fell back. Empty on success."
          },
          "subject": {
            "type": "string",
            "description": "The rendered subject. Yagra's built-in wording when the subject is not overridden, or when\nrendering it failed — which is exactly what would be sent."
          }
        }
      },
      "ProfileBody": {
        "type": "object",
        "description": "Create/update body. `category` is optional on create (defaults to generic SNMP).",
        "required": [
          "name"
        ],
        "properties": {
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "poll_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Per-profile polling-interval override, in seconds. Omitted/`null` ⇒ inherit the global\ndefault; when present it must fall within `[MIN, MAX]`.",
            "minimum": 0
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ProfileId": {
        "type": "string",
        "format": "uuid",
        "description": "Stable identifier for a device profile / device-class (e.g. \"Cisco router\").\n\nProfiles carry the polling templates and default thresholds a node inherits."
      },
      "ProfileRow": {
        "type": "object",
        "description": "A device profile.",
        "required": [
          "id",
          "name",
          "category"
        ],
        "properties": {
          "category": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "poll_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ProfileSummary": {
        "type": "object",
        "description": "A device-class/profile row for the API (id + name + role/vendor metadata).",
        "required": [
          "id",
          "name",
          "category"
        ],
        "properties": {
          "category": {
            "type": "string",
            "description": "Functional role token (kebab-case `ProfileCategory`) — the UI's grouping key."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "poll_interval_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Per-profile polling-interval override (seconds); `None` ⇒ inherit the global default."
          },
          "vendor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Vendor label, if known (descriptive metadata only — never a TSDB label)."
          }
        }
      },
      "ProfileTemplateLink": {
        "type": "object",
        "description": "A profile↔template attachment.",
        "required": [
          "profile_id",
          "template_id"
        ],
        "properties": {
          "profile_id": {
            "type": "string",
            "format": "uuid"
          },
          "template_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ProviderChoice": {
        "type": "object",
        "description": "What the Settings form needs to render one provider choice.\n\nServed from the backend rather than hardcoded in the WebUI so the egress warning cannot drift\nfrom what the code actually does: [`ProviderKind::leaves_operator_boundary`] is the single\ndefinition, and the checkbox that warns about it reads the same value the adapter obeys.",
        "required": [
          "key",
          "suggested_model",
          "leaves_operator_boundary",
          "needs_project",
          "credential_optional"
        ],
        "properties": {
          "credential_optional": {
            "type": "boolean",
            "description": "Whether the credential may be omitted (Vertex on GKE/GCE uses Workload Identity instead)."
          },
          "key": {
            "type": "string"
          },
          "leaves_operator_boundary": {
            "type": "boolean",
            "description": "True when picking this sends hostnames, addresses, topology and syslog outside the\noperator's own cloud."
          },
          "needs_project": {
            "type": "boolean",
            "description": "Whether this provider needs a GCP project + region (Vertex) rather than just an API key."
          },
          "suggested_location": {
            "type": [
              "string",
              "null"
            ]
          },
          "suggested_model": {
            "type": "string"
          }
        }
      },
      "Ranked_AlertNodeCount": {
        "type": "object",
        "description": "A ranked Top-N result.",
        "required": [
          "entries",
          "partial"
        ],
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "One chronic-offender row.",
              "required": [
                "node_id",
                "name",
                "count"
              ],
              "properties": {
                "count": {
                  "type": "integer",
                  "format": "int64"
                },
                "name": {
                  "type": "string"
                },
                "node_id": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "description": "The ranked rows, highest first, at most the requested `limit`."
          },
          "partial": {
            "type": "boolean",
            "description": "`true` when this ranking covers only the groups the calling account may see and entries it\nis entitled to may be missing. Always `false` for an account with unrestricted visibility."
          }
        }
      },
      "Ranked_InterfaceTopEntry": {
        "type": "object",
        "description": "A ranked Top-N result.",
        "required": [
          "entries",
          "partial"
        ],
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "One ranked interface in a fleet interface Top-N.",
              "required": [
                "node_id",
                "node_name",
                "ifindex",
                "value"
              ],
              "properties": {
                "if_alias": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "if_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "if_speed_bps": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "format": "int64",
                  "description": "Configured speed (bits/sec) for util%; `null` if unknown."
                },
                "ifindex": {
                  "type": "integer",
                  "format": "int32"
                },
                "node_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "node_name": {
                  "type": "string"
                },
                "value": {
                  "type": "number",
                  "format": "double",
                  "description": "bits/sec for throughput metrics, errors|discards per second otherwise."
                }
              }
            },
            "description": "The ranked rows, highest first, at most the requested `limit`."
          },
          "partial": {
            "type": "boolean",
            "description": "`true` when this ranking covers only the groups the calling account may see and entries it\nis entitled to may be missing. Always `false` for an account with unrestricted visibility."
          }
        }
      },
      "Ranked_TopEntry": {
        "type": "object",
        "description": "A ranked Top-N result.",
        "required": [
          "entries",
          "partial"
        ],
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "One ranked node in a Top-N result.",
              "required": [
                "node_id",
                "name",
                "value"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Display name, joined from PostgreSQL (ADR-011); falls back to the id string if the node has\nsince been deleted."
                },
                "node_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "value": {
                  "type": "number",
                  "format": "double"
                }
              }
            },
            "description": "The ranked rows, highest first, at most the requested `limit`."
          },
          "partial": {
            "type": "boolean",
            "description": "`true` when this ranking covers only the groups the calling account may see and entries it\nis entitled to may be missing. Always `false` for an account with unrestricted visibility."
          }
        }
      },
      "RcaAnswer": {
        "type": "object",
        "description": "The parsed explanation. **Every field is plain text and must be rendered as text, never as HTML\nor markdown** — this is model output, and the model was itself reading untrusted device output.",
        "required": [
          "summary"
        ],
        "properties": {
          "confidence": {
            "$ref": "#/components/schemas/RcaConfidence",
            "description": "How sure the model says it is."
          },
          "dependents": {
            "type": "string",
            "description": "Whether the other affected nodes are consequences of it."
          },
          "next_steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Concrete things to check next."
          },
          "raw": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the reply was not parseable JSON: the model's text, verbatim and bounded. Its\npresence is what tells the UI to render one prose block rather than empty sections."
          },
          "root_cause": {
            "type": "string",
            "description": "What most likely failed, and why the evidence says so."
          },
          "summary": {
            "type": "string",
            "description": "One sentence an on-call engineer can act on."
          }
        }
      },
      "RcaBody": {
        "type": "object",
        "description": "The `POST /api/v1/rca` body.",
        "required": [
          "node",
          "check"
        ],
        "properties": {
          "check": {
            "type": "string",
            "format": "uuid"
          },
          "force": {
            "type": "boolean",
            "description": "Regenerate instead of serving a cached report. Still rate-limited."
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "UI language tag (`ja`, `en-GB`, …). The instructions stay English; the answer follows the\nreader. Unknown tags fall back to English rather than failing."
          },
          "node": {
            "type": "string",
            "format": "uuid",
            "description": "The alerting node. May be a symptom of an upstream failure — the context builder follows\n`root_cause` to the incident before assembling anything."
          },
          "window_secs": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Timeline window in seconds; clamped by the orchestrator. Defaults to an hour."
          }
        }
      },
      "RcaConfidence": {
        "type": "string",
        "description": "How sure the model says it is. `unknown` means it answered outside this set, or not at all.",
        "enum": [
          "high",
          "medium",
          "low",
          "unknown"
        ]
      },
      "RcaReport": {
        "type": "object",
        "description": "A stored report. `body` carries the answer and its evidence; `summary` is lifted out of it so a\nlist view does not have to fetch the whole thing.",
        "required": [
          "id",
          "node_id",
          "check_id",
          "provider",
          "model",
          "summary",
          "body",
          "generated_at",
          "created_by"
        ],
        "properties": {
          "body": {
            "$ref": "#/components/schemas/ReportBody",
            "description": "The answer and the evidence it was grounded in."
          },
          "cached": {
            "type": "boolean",
            "description": "Whether this response came from the cache rather than a fresh call. Not a column — it\ndescribes *this* delivery of the report, not the report."
          },
          "check_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_by": {
            "type": "string"
          },
          "generated_at": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "model": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "provider": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "ReportBody": {
        "type": "object",
        "description": "A report's contents: the answer, the evidence it was grounded in, and the language it was\nrequested in.",
        "required": [
          "answer",
          "evidence",
          "language"
        ],
        "properties": {
          "answer": {
            "$ref": "#/components/schemas/RcaAnswer"
          },
          "evidence": {
            "$ref": "#/components/schemas/IncidentContext",
            "description": "Everything the model was told, exactly as it saw it."
          },
          "language": {
            "$ref": "#/components/schemas/Language",
            "description": "Which language the answer was requested in."
          },
          "transcript": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolTurn"
            },
            "description": "What the model looked up for itself, in order (ADR-028 WS-G). Empty on a single-shot run,\nand on every report written before agentic retrieval existed."
          }
        }
      },
      "ReportDefinition": {
        "type": "object",
        "description": "A report definition (reusable template), as served to the API.",
        "required": [
          "id",
          "name",
          "spec",
          "created_ms",
          "updated_ms"
        ],
        "properties": {
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "spec": {},
          "updated_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_ms": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ReportDefinitionBody": {
        "type": "object",
        "description": "Create/update body for a report definition.",
        "required": [
          "name",
          "spec"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "spec": {}
        }
      },
      "ReportDefinitionRow": {
        "type": "object",
        "description": "A saved report template.",
        "required": [
          "id",
          "name",
          "spec"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "spec": {}
        }
      },
      "ReportRun": {
        "type": "object",
        "description": "A run row for the saved-reports list (without the heavy `result_*` payloads).",
        "required": [
          "id",
          "name",
          "trigger",
          "state",
          "pct",
          "section_count",
          "created_ms"
        ],
        "properties": {
          "created_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_ms": {
            "type": "integer",
            "format": "int64"
          },
          "definition_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "finished_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "pct": {
            "type": "integer",
            "format": "int32"
          },
          "range_from_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "range_to_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "section_count": {
            "type": "integer",
            "format": "int32"
          },
          "started_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "state": {
            "$ref": "#/components/schemas/ReportRunState"
          },
          "trigger": {
            "$ref": "#/components/schemas/ReportRunTrigger"
          }
        }
      },
      "ReportRunDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ReportRun"
          },
          {
            "type": "object",
            "properties": {
              "result_html": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "result_json": {}
            }
          }
        ],
        "description": "A run plus its rendered result (the viewer / export endpoints)."
      },
      "ReportRunState": {
        "type": "string",
        "description": "Lifecycle of one report run.",
        "enum": [
          "queued",
          "running",
          "succeeded",
          "failed",
          "unknown"
        ]
      },
      "ReportRunTrigger": {
        "type": "string",
        "description": "What started a run.",
        "enum": [
          "manual",
          "scheduled",
          "unknown"
        ]
      },
      "ReportSchedule": {
        "type": "object",
        "description": "A schedule row (joined with its definition's name for display).",
        "required": [
          "id",
          "definition_id",
          "definition_name",
          "frequency",
          "at_hour",
          "at_minute",
          "enabled",
          "next_run_ms"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "definition_id": {
            "type": "string",
            "format": "uuid"
          },
          "definition_name": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "frequency": {
            "$ref": "#/components/schemas/Cadence"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_run_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "last_status": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ReportScheduleStatus"
              }
            ]
          },
          "next_run_ms": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ReportScheduleBody": {
        "type": "object",
        "description": "Create/update body for a schedule (preset cadence).",
        "required": [
          "definition_id",
          "frequency",
          "at_hour",
          "at_minute"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "definition_id": {
            "type": "string",
            "format": "uuid"
          },
          "enabled": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "frequency": {
            "type": "string"
          }
        }
      },
      "ReportScheduleRow": {
        "type": "object",
        "description": "A recurring report run.",
        "required": [
          "id",
          "definition_id",
          "frequency",
          "at_hour",
          "at_minute",
          "enabled"
        ],
        "properties": {
          "at_hour": {
            "type": "integer",
            "format": "int32"
          },
          "at_minute": {
            "type": "integer",
            "format": "int32"
          },
          "day_of_month": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "day_of_week": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32"
          },
          "definition_id": {
            "type": "string",
            "format": "uuid"
          },
          "enabled": {
            "type": "boolean"
          },
          "frequency": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ReportScheduleStatus": {
        "type": "string",
        "description": "Outcome of a schedule's most recent firing.",
        "enum": [
          "queued",
          "missing-definition",
          "error",
          "unknown"
        ]
      },
      "RetentionPolicy": {
        "type": "object",
        "description": "The full retention policy: the editable windows plus every row of the table.",
        "required": [
          "settings",
          "rows"
        ],
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RetentionRow"
            },
            "description": "Every retained subject, including the ones no API can change."
          },
          "settings": {
            "$ref": "#/components/schemas/RetentionValues",
            "description": "The windows this endpoint can change."
          }
        }
      },
      "RetentionRow": {
        "type": "object",
        "description": "One line of the retention table.",
        "required": [
          "subject",
          "store",
          "enforcement",
          "tunable",
          "field",
          "unit",
          "store_configured",
          "note"
        ],
        "properties": {
          "enforcement": {
            "type": "string",
            "description": "How the window is applied: `pg_prune`, `store_ttl`, `store_flag` or `unlimited`."
          },
          "field": {
            "type": "string",
            "description": "Which field of `settings` this row binds to, or `store_owned` / `unlimited`."
          },
          "note": {
            "type": "string",
            "description": "Operator-facing explanation. For a read-only row it names the flag that does change it."
          },
          "store": {
            "type": "string",
            "description": "The store that holds it."
          },
          "store_configured": {
            "type": "boolean",
            "description": "Whether the backing store is configured in this deployment. A row for an unconfigured\noptional store retains nothing."
          },
          "store_reported": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the store itself reports for a `store_flag` row, verbatim (e.g. `12`, `30d`). Absent\nwhen the store is unreachable or is running its own default — in which case the value is\ngenuinely unknown and is not guessed."
          },
          "subject": {
            "type": "string",
            "description": "Stable identifier for the retained data, e.g. `alert_history`."
          },
          "tunable": {
            "type": "string",
            "description": "Where it can be changed: `settings` (here), `store_flag_read_only` (the store's own\ncommand-line flag), or `by_decision` (not retained on a schedule at all)."
          },
          "unit": {
            "type": "string",
            "description": "Unit of `value`: `days`, `hours`, or empty when the row has no configurable number."
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The configured window, for rows this deployment controls.",
            "minimum": 0
          }
        }
      },
      "RetentionValues": {
        "type": "object",
        "description": "The operator-editable retention windows.",
        "required": [
          "alert_linked_days",
          "unmatched_event_hours",
          "report_run_days",
          "flow_days"
        ],
        "properties": {
          "alert_linked_days": {
            "type": "integer",
            "format": "int32",
            "description": "Days to keep alert history, node-state snapshots, DNS chain changes and matched events.",
            "minimum": 0
          },
          "diagnostic_days": {
            "type": "integer",
            "format": "int32",
            "description": "Days to keep on-demand diagnostics: Troubleshoot analysis runs with their findings, and\ngenerated AI root-cause reports. Optional — omitting it sets the default (90).",
            "minimum": 0
          },
          "flow_days": {
            "type": "integer",
            "format": "int32",
            "description": "Days to keep traffic-flow records, applied as a ClickHouse table TTL.",
            "minimum": 0
          },
          "report_run_days": {
            "type": "integer",
            "format": "int32",
            "description": "Days to keep generated report runs.",
            "minimum": 0
          },
          "unmatched_event_hours": {
            "type": "integer",
            "format": "int32",
            "description": "Hours to keep passive events that matched no rule.",
            "minimum": 0
          }
        }
      },
      "Role": {
        "type": "string",
        "description": "Predefined roles, ordered least → most privileged.",
        "enum": [
          "viewer",
          "operator",
          "admin"
        ]
      },
      "RoleInfo": {
        "type": "object",
        "description": "One role in the matrix: its metadata and the permission keys it grants.",
        "required": [
          "key",
          "label",
          "description",
          "builtin",
          "permissions"
        ],
        "properties": {
          "builtin": {
            "type": "boolean",
            "description": "Built-in roles are fixed (custom roles are not configurable yet)."
          },
          "description": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The keys of the permissions this role grants."
          }
        }
      },
      "RolesMatrix": {
        "type": "object",
        "description": "The role-vs-privilege matrix.",
        "required": [
          "permissions",
          "roles"
        ],
        "properties": {
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PermissionInfo"
            }
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RoleInfo"
            }
          }
        }
      },
      "RotatedToken": {
        "type": "object",
        "description": "A freshly rotated ingest token — the second and last place the plaintext appears.",
        "required": [
          "token"
        ],
        "properties": {
          "token": {
            "type": "string"
          }
        }
      },
      "RoutingRule": {
        "type": "object",
        "description": "A routing rule: enabled alerts of `severity` (None = any) fan out to `channel_ids`.",
        "required": [
          "id",
          "name",
          "enabled",
          "channel_ids"
        ],
        "properties": {
          "channel_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "severity": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Severity"
              }
            ]
          }
        }
      },
      "RuleTestResult": {
        "type": "object",
        "description": "The tester's answer. A compile failure is reported **in-band** rather than as a 400: the whole\npoint of the tester is to show the operator what is wrong with the pattern they are typing, and\na 400 would be rendered as a request failure instead of inline next to the field.",
        "required": [
          "matched"
        ],
        "properties": {
          "clear_matched": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "matched": {
            "type": "boolean"
          }
        }
      },
      "SavedFinding": {
        "type": "object",
        "description": "One finding as the cross-run search returns it: the finding, plus the run it came from.",
        "required": [
          "id",
          "job_id",
          "tool",
          "score",
          "severity",
          "node_name",
          "metric",
          "kind",
          "when_label",
          "duration",
          "at"
        ],
        "properties": {
          "at": {
            "type": "string",
            "description": "When the finding was written (RFC 3339). Pass it back as `before`, with `id` as\n`before_id`, to fetch the next page."
          },
          "duration": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "job_id": {
            "type": "string",
            "format": "uuid",
            "description": "The analysis run that produced this finding."
          },
          "kind": {
            "type": "string"
          },
          "metric": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node this finding is about; absent for a fleet-level finding."
          },
          "node_name": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "format": "double"
          },
          "severity": {
            "type": "string",
            "description": "`crit`, `warn` or `info`."
          },
          "tool": {
            "type": "string",
            "description": "Which diagnostic produced it, as that run recorded it (e.g. `anomaly`)."
          },
          "when_label": {
            "type": "string"
          }
        }
      },
      "ScanStatus": {
        "type": "object",
        "description": "A scan's current status returned by the API.",
        "required": [
          "scan_id",
          "done",
          "probed",
          "total",
          "candidates"
        ],
        "properties": {
          "candidates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Candidate"
            }
          },
          "done": {
            "type": "boolean"
          },
          "probed": {
            "type": "integer",
            "format": "int32",
            "description": "Targets probed so far / total targets in the sweep.",
            "minimum": 0
          },
          "scan_id": {
            "type": "string",
            "format": "uuid"
          },
          "scanning": {
            "type": [
              "string",
              "null"
            ],
            "description": "The address the sweep is currently at (the next unprobed target), while running."
          },
          "total": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "SchedulerStatsSnapshot": {
        "type": "object",
        "description": "A point-in-time view of [`SchedulerStats`] for the API.",
        "required": [
          "jobs_last_round",
          "results_total",
          "snapshots_published_total",
          "deltas_published_total",
          "assignment_mirror_writes_total",
          "pools_working_set",
          "pools_legacy"
        ],
        "properties": {
          "assignment_mirror_writes_total": {
            "type": "integer",
            "format": "int64",
            "description": "Redis assignment-mirror rewrites issued since start (S18). Flat across steady-state sweeps —\nan unchanged working set skips the rewrite — so growth tracks real assignment churn.",
            "minimum": 0
          },
          "deltas_published_total": {
            "type": "integer",
            "format": "int64",
            "description": "Working-set deltas core has published to pollers since start (ADR-020).",
            "minimum": 0
          },
          "jobs_last_round": {
            "type": "integer",
            "format": "int64",
            "description": "Jobs published in the most recent round (legacy per-job dispatch only).",
            "minimum": 0
          },
          "last_sweep_unix_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "When the last poll round was dispatched (Unix ms), or `None` if none yet."
          },
          "pools_legacy": {
            "type": "integer",
            "format": "int64",
            "description": "Pools served in legacy per-job mode in the most recent sweep (no live poller).",
            "minimum": 0
          },
          "pools_working_set": {
            "type": "integer",
            "format": "int64",
            "description": "Pools served in working-set mode in the most recent sweep (a live poller owns them).",
            "minimum": 0
          },
          "results_total": {
            "type": "integer",
            "format": "int64",
            "description": "Total poll results consumed since start.",
            "minimum": 0
          },
          "snapshots_published_total": {
            "type": "integer",
            "format": "int64",
            "description": "Working-set snapshots core has published to pollers since start (ADR-020).",
            "minimum": 0
          }
        }
      },
      "Scope": {
        "oneOf": [
          {
            "type": "string",
            "description": "Unrestricted visibility.",
            "enum": [
              "All"
            ]
          },
          {
            "type": "object",
            "description": "Visibility limited to these group identifiers.",
            "required": [
              "Groups"
            ],
            "properties": {
              "Groups": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Visibility limited to these group identifiers.",
                "uniqueItems": true
              }
            }
          }
        ],
        "description": "Which slice of the inventory an account may see: everything, or a named set of node groups.\n\nA node is visible if it belongs to an allowed group or to anything beneath one. A node in **no**\ngroup is visible only under `All` — an unassigned node is not leaked to a scoped account."
      },
      "ScopeLevel": {
        "type": "string",
        "description": "The scope a threshold is defined at, ordered least → most specific so the derived\n`Ord` makes `Node` win over `Group` win over `Profile`.",
        "enum": [
          "profile",
          "group",
          "node"
        ]
      },
      "SecretsMode": {
        "type": "string",
        "description": "How secrets appear in a bundle. See the module docs for why there is only one variant.",
        "enum": [
          "references"
        ]
      },
      "SectionDef": {
        "type": "object",
        "description": "A report-section type the user can add to a report.",
        "required": [
          "kind",
          "title",
          "blurb",
          "group",
          "settings"
        ],
        "properties": {
          "blurb": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SectionSetting"
            }
          },
          "title": {
            "type": "string"
          }
        }
      },
      "SectionSetting": {
        "type": "object",
        "description": "A configurable setting on a section (rendered generically by the builder).",
        "required": [
          "key",
          "label",
          "kind",
          "default"
        ],
        "properties": {
          "default": {},
          "key": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "description": "`number` | `select`."
          },
          "label": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SettingOption"
            }
          }
        }
      },
      "SetPassword": {
        "type": "object",
        "description": "Reset-password request body. The password is hashed before storage and never logged.",
        "required": [
          "password"
        ],
        "properties": {
          "password": {
            "type": "string"
          }
        }
      },
      "SetProfileTemplates": {
        "type": "object",
        "description": "Replace-all body for a profile's attached templates.",
        "required": [
          "template_ids"
        ],
        "properties": {
          "template_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "SetRole": {
        "type": "object",
        "description": "Change-role request body.",
        "required": [
          "role"
        ],
        "properties": {
          "role": {
            "type": "string"
          }
        }
      },
      "SetScope": {
        "type": "object",
        "description": "Change-scope request body.",
        "required": [
          "scope"
        ],
        "properties": {
          "scope": {
            "$ref": "#/components/schemas/Scope"
          }
        }
      },
      "SetStatus": {
        "type": "object",
        "description": "Enable/disable-account request body.",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "SettingOption": {
        "type": "object",
        "description": "One selectable choice for a `select` setting.",
        "required": [
          "value",
          "label"
        ],
        "properties": {
          "label": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        }
      },
      "Severity": {
        "type": "string",
        "description": "How serious an alert is. Variants are declared low → high so the derived\n`Ord` ranks `Critical` above `Warning` above `Info`.",
        "enum": [
          "info",
          "warning",
          "critical"
        ]
      },
      "ShadowAlert": {
        "type": "object",
        "description": "One node whose suppression would change if the deployment moved to the derived graph.",
        "required": [
          "node_id"
        ],
        "properties": {
          "node_id": {
            "type": "string",
            "format": "uuid",
            "description": "The node whose active alert is affected."
          },
          "root_cause": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The node the derived graph blames, when it has one."
          }
        }
      },
      "ShadowEdge": {
        "type": "object",
        "description": "One node whose parent set differs between the two graphs.",
        "required": [
          "child",
          "parent"
        ],
        "properties": {
          "child": {
            "type": "string",
            "format": "uuid",
            "description": "The downstream node."
          },
          "parent": {
            "type": "string",
            "format": "uuid",
            "description": "The upstream node."
          }
        }
      },
      "SourceKind": {
        "type": "string",
        "description": "Which received stream a destination tees. Kept here (rather than in core) so the DB `CHECK`\nstrings, the API validation and the WebUI all agree on one spelling.",
        "enum": [
          "syslog",
          "trap",
          "flow"
        ]
      },
      "StaleNode": {
        "type": "object",
        "description": "A node returning no fresh data (silent failure / blind spot).",
        "required": [
          "node_id",
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "StartScan": {
        "type": "object",
        "description": "Start-scan body: explicit target IPs (the WebUI expands a CIDR), candidate stored credentials by\nid, and ad-hoc communities.",
        "required": [
          "targets"
        ],
        "properties": {
          "communities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "credential_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pool": {
            "type": [
              "string",
              "null"
            ],
            "description": "Poll-pool to run the sweep in (ADR-009/020). Absent/empty = legacy global discovery."
          },
          "targets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "StartedScan": {
        "type": "object",
        "description": "The accepted scan's id, for polling its status.",
        "required": [
          "scan_id"
        ],
        "properties": {
          "scan_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "StoredCollectionItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CollectionItem"
          },
          {
            "type": "object",
            "required": [
              "id",
              "scope_level",
              "scope_id",
              "enabled"
            ],
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "scope_id": {
                "type": "string",
                "format": "uuid"
              },
              "scope_level": {
                "$ref": "#/components/schemas/ScopeLevel"
              }
            }
          }
        ],
        "description": "A stored collection item with its id and scope, for the API (the scheduler ignores id)."
      },
      "StoredEventRule": {
        "type": "object",
        "description": "A stored event rule (API shape; the engine compiles enabled ones).",
        "required": [
          "id",
          "name",
          "enabled",
          "match_kind",
          "pattern",
          "severity",
          "ttl_secs",
          "min_count",
          "window_secs",
          "created_at"
        ],
        "properties": {
          "clear_pattern": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "enabled": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "match_kind": {
            "$ref": "#/components/schemas/EventMatchKind"
          },
          "min_count": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pattern": {
            "type": "string"
          },
          "severity": {
            "$ref": "#/components/schemas/Severity"
          },
          "source_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "source_kind": {
            "type": [
              "string",
              "null"
            ]
          },
          "ttl_secs": {
            "type": "integer",
            "format": "int32"
          },
          "window_secs": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "StoredMute": {
        "type": "object",
        "description": "A stored mute (API shape). A `node` mute silences one node (optionally one check via\n`metric_name`); a `group` mute silences every node under a folder group (recursive). Exactly\none of `node_id` / `group_id` is set, per `scope_kind`.",
        "required": [
          "id",
          "scope_kind",
          "until_at"
        ],
        "properties": {
          "group_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "metric_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope_kind": {
            "$ref": "#/components/schemas/MuteScope"
          },
          "until_at": {
            "type": "string"
          }
        }
      },
      "StoredThreshold": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ThresholdRule"
          },
          {
            "type": "object",
            "required": [
              "id",
              "scope_level",
              "scope_id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "scope_id": {
                "type": "string"
              },
              "scope_level": {
                "$ref": "#/components/schemas/ScopeLevel"
              }
            }
          }
        ],
        "description": "A stored threshold rule with its scope and id (id is for the API; the engine ignores it)."
      },
      "StoredWindow": {
        "type": "object",
        "description": "A stored maintenance window (API shape; times are RFC 3339 text at the edge).",
        "required": [
          "id",
          "name",
          "scope_level",
          "scope_id",
          "starts_at",
          "ends_at",
          "enabled",
          "active"
        ],
        "properties": {
          "active": {
            "type": "boolean",
            "description": "Whether the window covers \"now\" (computed at read time for the UI)."
          },
          "enabled": {
            "type": "boolean"
          },
          "ends_at": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "scope_id": {
            "type": "string"
          },
          "scope_level": {
            "$ref": "#/components/schemas/WindowScope"
          },
          "starts_at": {
            "type": "string"
          }
        }
      },
      "SubjectKind": {
        "type": "string",
        "description": "Which kind of thing an alert is about: a monitored `node`, or a poller `pool` when Yagra is\nreporting on its own polling coverage.",
        "enum": [
          "node",
          "pool"
        ]
      },
      "SystemHealth": {
        "type": "object",
        "description": "Yagra's own health: the reachability of its backing services.",
        "required": [
          "overall",
          "postgres",
          "tsdb",
          "logs",
          "flow",
          "bus",
          "web_tls"
        ],
        "properties": {
          "bus": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "NATS — **inferred** from a recent scheduler sweep, not a direct ping."
          },
          "flow": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "ClickHouse (flow store, ADR-031) — likewise reachable when not configured."
          },
          "logs": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "VictoriaLogs (event log, ADR-024) — reported reachable when not configured (events then live\nin PostgreSQL), so an unconfigured log store never degrades `overall`."
          },
          "overall": {
            "type": "string",
            "description": "`\"ok\"` when every dependency is reachable, else `\"degraded\"`."
          },
          "postgres": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "PostgreSQL (metadata store) — `SELECT 1`."
          },
          "tsdb": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "VictoriaMetrics (TSDB) — `/-/healthy`."
          },
          "web_tls": {
            "$ref": "#/components/schemas/DependencyHealth",
            "description": "The WebUI's TLS certificate. Reported unhealthy only when someone has to act: it has expired,\nor an imported certificate is inside its last 30 days. A self-signed one renews itself."
          }
        }
      },
      "SystemHostsResponse": {
        "type": "object",
        "description": "Core plus every poller that reports host telemetry.",
        "required": [
          "hosts"
        ],
        "properties": {
          "hosts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HostInfo"
            }
          }
        }
      },
      "TableResult": {
        "type": "object",
        "description": "What the import did to one table.",
        "required": [
          "table",
          "created",
          "updated",
          "skipped"
        ],
        "properties": {
          "created": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "skipped": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "table": {
            "type": "string"
          },
          "updated": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "TemplateBody": {
        "type": "object",
        "description": "A channel's notification-template override. Both fields are replaced together; `null` or blank\non a field restores Yagra's built-in wording for it.",
        "properties": {
          "body": {
            "type": [
              "string",
              "null"
            ]
          },
          "subject": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "TemplateItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CollectionItem"
          },
          {
            "type": "object",
            "required": [
              "id",
              "enabled"
            ],
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "id": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        ],
        "description": "One metric in a template, with its id, for the template editor."
      },
      "TemplateSummary": {
        "type": "object",
        "description": "A collection template row for the API (id + name + description + metric count).",
        "required": [
          "id",
          "name",
          "item_count"
        ],
        "properties": {
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "item_count": {
            "type": "integer",
            "format": "int64"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "TemplateVariable": {
        "type": "object",
        "description": "One name a notification template may reference.",
        "required": [
          "name",
          "description",
          "always_present"
        ],
        "properties": {
          "always_present": {
            "type": "boolean",
            "description": "Whether every alert carries it. A variable that is not always present is *undefined* when\nabsent: it renders as empty text, and `{{ name | default(\"…\") }}` supplies a fallback."
          },
          "description": {
            "type": "string",
            "description": "What the value means."
          },
          "name": {
            "type": "string",
            "description": "The name to write between `{{ }}`."
          }
        }
      },
      "TestResult": {
        "type": "object",
        "description": "The outcome of a one-shot delivery test.\n\n`delivered: false` is a *successful* request reporting a failed probe, not a 5xx: the\ndestination's configuration is the caller's, and the transport error is what tells them which\npart of it is wrong. The error text is the transport's, never a payload — syslog bodies carry\ncredentials.",
        "required": [
          "delivered"
        ],
        "properties": {
          "delivered": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ThresholdPage": {
        "type": "object",
        "description": "A capped page of threshold rules.\n\n`total` is the unfiltered row count, not `items.len()`, so the UI can say *how many* it is not\nshowing. `truncated` is derived rather than left to the client comparing the two — a client that\nforgets the comparison shows a complete-looking list.",
        "required": [
          "items",
          "total",
          "truncated"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredThreshold"
            }
          },
          "total": {
            "type": "integer",
            "format": "int64",
            "description": "Rules stored in total, ignoring the cap."
          },
          "truncated": {
            "type": "boolean",
            "description": "Whether `items` is a prefix of the ruleset rather than all of it."
          }
        }
      },
      "ThresholdRow": {
        "type": "object",
        "description": "A threshold rule.",
        "required": [
          "id",
          "scope_level",
          "scope_id",
          "metric",
          "direction",
          "dwell_samples"
        ],
        "properties": {
          "critical": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "direction": {
            "type": "string"
          },
          "dwell_samples": {
            "type": "integer",
            "format": "int32"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "metric": {
            "type": "string"
          },
          "scope_id": {
            "type": "string"
          },
          "scope_level": {
            "type": "string"
          },
          "warning": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          }
        }
      },
      "ThresholdRule": {
        "type": "object",
        "description": "A threshold rule for a single metric.",
        "required": [
          "metric",
          "direction",
          "dwell_samples"
        ],
        "properties": {
          "critical": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Value at/over which the node is `Critical`. `None` = no critical level."
          },
          "direction": {
            "$ref": "#/components/schemas/Direction",
            "description": "Which direction trips the threshold."
          },
          "dwell_samples": {
            "type": "integer",
            "format": "int32",
            "description": "Hysteresis: consecutive samples the breach must hold before transitioning,\nto damp oscillation at the threshold. `0`/`1` = transition immediately.",
            "minimum": 0
          },
          "metric": {
            "type": "string",
            "description": "Stable metric name this rule applies to (e.g. `cpu_util`)."
          },
          "warning": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Value at/over which the node is `Warning`. `None` = no warning level."
          }
        }
      },
      "ThroughputRange": {
        "type": "object",
        "description": "Fleet aggregate ingress and egress, aligned onto one shared timestamp axis.\n\nBoth arrays are the same length as `timestamps`, with `null` where that side has no sample.\nThe chart draws two series against one x-axis, so aligning here rather than client-side is what\nkeeps a missing ingress point from silently shifting egress by one slot.",
        "required": [
          "timestamps",
          "in_bps",
          "out_bps"
        ],
        "properties": {
          "in_bps": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "out_bps": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ],
              "format": "double"
            }
          },
          "timestamps": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int64"
            }
          }
        }
      },
      "TlsCertSource": {
        "type": "string",
        "description": "Where a certificate came from, and therefore whether core may replace it on its own.",
        "enum": [
          "self_signed",
          "imported",
          "unknown"
        ]
      },
      "TokenSurface": {
        "type": "string",
        "description": "Which authentication surface a credential may be presented at.\n\nA personal access token authenticated `/mcp` and nothing else, so there was never a choice to\nexpress. Now that the REST API accepts one too the two surfaces differ enough that \"may\nauthenticate here\" has to be recorded per token: `/mcp` is a curated, mostly-read tool surface,\nwhile REST is the entire configuration API. A token minted for an AI client must not become a\nconfiguration credential because the server learned a new trick — so the surfaces are named on\nthe token, and anything that does not name [`TokenSurface::Rest`] cannot reach `/api/v1`.",
        "enum": [
          "mcp",
          "rest"
        ]
      },
      "ToolTurn": {
        "type": "object",
        "description": "One tool the model asked for, and what it was told.\n\nStored for the same reason `evidence` is: an explanation whose reader cannot check what it was\nbased on is an assertion. Agentic retrieval makes that worse, not better — the evidence is no\nlonger a fixed set somebody chose, so without this nobody can tell whether the model looked at\nthe right thing.",
        "required": [
          "tool",
          "args",
          "result"
        ],
        "properties": {
          "args": {
            "type": "object",
            "description": "The arguments the model chose."
          },
          "result": {
            "type": "string",
            "description": "What the tool answered, as the model saw it."
          },
          "tool": {
            "type": "string",
            "description": "The tool name, from the agent's allow-list."
          }
        }
      },
      "TopEntry": {
        "type": "object",
        "description": "One ranked node in a Top-N result.",
        "required": [
          "node_id",
          "name",
          "value"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name, joined from PostgreSQL (ADR-011); falls back to the id string if the node has\nsince been deleted."
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "TopologyLink": {
        "type": "object",
        "description": "One undirected link in the derived connectivity graph.",
        "required": [
          "id",
          "sources",
          "source",
          "first_seen",
          "last_seen"
        ],
        "properties": {
          "a_if_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Port name on the `a` side, when a source reported one."
          },
          "a_ifindex": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "`ifIndex` on the `a` side, when a source reported one."
          },
          "a_node": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "One endpoint. `null` is reserved for an endpoint that is not a monitored node."
          },
          "b_if_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Port name on the `b` side, when a source reported one."
          },
          "b_ifindex": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "`ifIndex` on the `b` side, when a source reported one."
          },
          "b_node": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The other endpoint. `null` is reserved for an endpoint that is not a monitored node."
          },
          "first_seen": {
            "type": "string",
            "description": "When this link was first derived (RFC 3339)."
          },
          "forced_parent": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The endpoint an operator declared upstream, when one was declared. `null` means the direction\nis worked out from how far each end is from a poller."
          },
          "id": {
            "type": "integer",
            "format": "int64",
            "description": "Stable id, and the keyset cursor."
          },
          "last_seen": {
            "type": "string",
            "description": "When it was last confirmed (RFC 3339)."
          },
          "source": {
            "$ref": "#/components/schemas/LinkSource",
            "description": "The strongest of `sources` — what to label the link with."
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkSource"
            },
            "description": "Every kind of evidence that produced this link."
          },
          "subnet": {
            "type": [
              "string",
              "null"
            ],
            "description": "The subnet behind a shared-subnet link, e.g. `192.168.1.0/24`."
          }
        }
      },
      "TopologyLinkPage": {
        "type": "object",
        "description": "One keyset page of the derived connectivity graph, with what the last derivation run saw.",
        "required": [
          "links",
          "summary",
          "total_links"
        ],
        "properties": {
          "derived_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the graph was last derived (RFC 3339), or `null` before the first run."
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TopologyLink"
            }
          },
          "next_cursor": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Pass back as `cursor` for the next page; `null` ⇒ this was the last one."
          },
          "summary": {
            "$ref": "#/components/schemas/TopologyLinkSummary",
            "description": "Counters for everything the last derivation declined to turn into a link."
          },
          "total_links": {
            "type": "integer",
            "format": "int64",
            "description": "How many links the whole graph holds, not just this page."
          }
        }
      },
      "TopologyLinkSummary": {
        "type": "object",
        "description": "What the last derivation run observed but did not turn into a link.",
        "properties": {
          "ambiguous_mgmt_addrs": {
            "type": "integer",
            "format": "int32",
            "description": "Adjacency rows whose management address matched more than one node, so no link could be\nattributed without guessing which.",
            "minimum": 0
          },
          "bgp_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links produced from a BGP peering session.",
            "minimum": 0
          },
          "bgp_peers_not_adjacent": {
            "type": "integer",
            "format": "int32",
            "description": "BGP peers that matched a monitored node but sit on no network the reporting node terminates,\nso the session is not evidence of a link between them. The normal reading is iBGP between\nloopbacks; a number that stays at zero on a network running iBGP means the reporting node's\ninterface addresses have not been observed.",
            "minimum": 0
          },
          "cdp_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links produced from a CDP adjacency.",
            "minimum": 0
          },
          "duplicate_addresses": {
            "type": "integer",
            "format": "int32",
            "description": "Addresses claimed by two or more nodes — a shared virtual IP, or a duplicate-address\nmisconfiguration.",
            "minimum": 0
          },
          "l3_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links whose strongest evidence is shared-subnet membership.",
            "minimum": 0
          },
          "lldp_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links produced from an LLDP adjacency.",
            "minimum": 0
          },
          "ospf_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links produced from an OSPF neighbour relationship.",
            "minimum": 0
          },
          "oversized_segments": {
            "type": "integer",
            "format": "int32",
            "description": "Segments with more than two members where no member could be identified as routing for the\nothers, so no link was drawn.",
            "minimum": 0
          },
          "route_links": {
            "type": "integer",
            "format": "int32",
            "description": "Links produced from a connected host route — the point-to-point links that share no subnet.",
            "minimum": 0
          },
          "subnet_prefix_mismatch": {
            "type": "integer",
            "format": "int32",
            "description": "Addresses sharing network bits but disagreeing on prefix length.",
            "minimum": 0
          },
          "truncated_nodes": {
            "type": "integer",
            "format": "int32",
            "description": "Nodes whose observation hit a per-node cap, so what is recorded for them is incomplete.",
            "minimum": 0
          },
          "unmatched_cdp_rows": {
            "type": "integer",
            "format": "int32",
            "description": "CDP rows whose management address matched no monitored node.",
            "minimum": 0
          },
          "unmatched_lldp_rows": {
            "type": "integer",
            "format": "int32",
            "description": "LLDP rows whose management address matched no monitored node.",
            "minimum": 0
          },
          "unmatched_routing_peers": {
            "type": "integer",
            "format": "int32",
            "description": "Routing adjacencies whose peer address matched no monitored node.",
            "minimum": 0
          }
        }
      },
      "TopologyMode": {
        "type": "string",
        "description": "Which dependency graph the alert engine uses.",
        "enum": [
          "manual",
          "shadow",
          "derived"
        ]
      },
      "TopologyModeRequest": {
        "type": "object",
        "description": "The topology mode to move the deployment to.",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "$ref": "#/components/schemas/TopologyMode",
            "description": "`manual`, `shadow` or `derived`."
          }
        }
      },
      "TopologyNode": {
        "type": "object",
        "description": "One node in the dependency/topology graph.",
        "required": [
          "id",
          "name",
          "state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Upstream parent in the dependency graph (`null` ⇒ a root)."
          },
          "root_cause": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Upstream node currently identified as the root cause of this node's alert (dependency\nsuppression), if any — lets a client collapse downstream alerts under the cause."
          },
          "state": {
            "$ref": "#/components/schemas/NodeState"
          }
        }
      },
      "TopologyPage": {
        "type": "object",
        "description": "One keyset page of the dependency graph.",
        "required": [
          "nodes"
        ],
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as `cursor` for the next page; `null` ⇒ this was the last one."
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TopologyNode"
            }
          }
        }
      },
      "TopologyShadow": {
        "type": "object",
        "description": "What the derived dependency graph would do, against what the manual one does.",
        "required": [
          "mode",
          "manual_edges",
          "derived_edges",
          "only_in_manual",
          "only_in_derived",
          "would_suppress",
          "would_unsuppress",
          "anchors",
          "unresolved_pools",
          "unresolved_pollers",
          "covered_nodes",
          "total_nodes",
          "opted_out"
        ],
        "properties": {
          "anchors": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Nodes the derived graph treats as roots, because a poller sits on their segment."
          },
          "covered_nodes": {
            "type": "integer",
            "description": "How many nodes the derived graph gives at least one upstream.\n\nRead with `total_nodes`: a low ratio means most of the fleet would keep alerting exactly as\nit does now, which is usually the point rather than a problem.",
            "minimum": 0
          },
          "derived_edges": {
            "type": "integer",
            "description": "Edges in the derived graph.",
            "minimum": 0
          },
          "manual_edges": {
            "type": "integer",
            "description": "Edges in the hand-authored graph.",
            "minimum": 0
          },
          "mode": {
            "$ref": "#/components/schemas/TopologyMode",
            "description": "`manual`, `shadow` or `derived`."
          },
          "mode_since": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the mode was last changed (RFC 3339), or `null` if it never has been."
          },
          "only_in_derived": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShadowEdge"
            },
            "description": "Parent edges only the derived graph has."
          },
          "only_in_manual": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShadowEdge"
            },
            "description": "Parent edges only the hand-authored graph has."
          },
          "opted_out": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Nodes an operator has excluded from derived suppression entirely.\n\nA list rather than a count: the screen that shows the comparison is also where the exclusion\nis toggled, and a count cannot tell a row whether it is the excluded one. Bounded by what an\noperator typed in, not by the fleet."
          },
          "total_nodes": {
            "type": "integer",
            "description": "Nodes in the inventory.",
            "minimum": 0
          },
          "unresolved_pollers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Poller ids that could not be placed, so an operator knows which to give an anchor."
          },
          "unresolved_pools": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Pools with at least one poller whose location could not be resolved.\n\n**Non-empty blocks `derived`.** A pool with no anchor contributes no roots, so none of its\nnodes would ever be suppressed while every screen showed the feature as on."
          },
          "would_suppress": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShadowAlert"
            },
            "description": "Active alerts the derived graph **would suppress** and the manual one does not.\n\nThe number to review before enabling `derived`: each of these is an alert that would stop\nbeing raised."
          },
          "would_unsuppress": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShadowAlert"
            },
            "description": "Active alerts the manual graph suppresses and the derived one would not — the noise\ndirection."
          }
        }
      },
      "UndecryptableCredential": {
        "type": "object",
        "description": "A credential the current KEK cannot open. Carries identity only — never a length, a `key_id`,\nor anything derived from the ciphertext.",
        "required": [
          "id",
          "name",
          "kind"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "UpdateCredential": {
        "type": "object",
        "description": "Update body. `name` is required; `secret` is optional — see the module doc for why omitting it\nis a rename and supplying it requires `kind`.",
        "required": [
          "name"
        ],
        "properties": {
          "kind": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "secret": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateEventSource": {
        "type": "object",
        "required": [
          "name",
          "enabled"
        ],
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "node_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "UrlCheckConfig": {
        "type": "object",
        "description": "A node's URL-monitoring configuration (1:1 with the node). No secrets: the optional auth\n`credential` is a reference; core resolves/inlines the decrypted value (ADR-018/020).",
        "required": [
          "url"
        ],
        "properties": {
          "body_match": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/BodyMatch",
                "description": "Optional keyword rule applied to the response body."
              }
            ]
          },
          "body_max_bytes": {
            "type": "integer",
            "format": "int32",
            "description": "How many bytes of the response body to read (default 65536, range 1024–1048576). Applies to\nboth `body_match` and `json_extract`; the body is not read at all unless one of them is set.",
            "minimum": 0
          },
          "credential": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CredentialId",
                "description": "Optional auth credential (Basic/Bearer/custom header). A reference only — core resolves it\nto an [`HttpAuth`] and inlines that into the poll job, the same path SNMP credentials take."
              }
            ]
          },
          "expected_status": {
            "$ref": "#/components/schemas/ExpectedStatus",
            "description": "Which status codes count as healthy (default: any 2xx)."
          },
          "follow_redirects": {
            "type": "boolean",
            "description": "Follow 3xx redirects (default `true`)."
          },
          "json_extract": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JsonExtract"
            },
            "description": "Values to lift out of a JSON response body and record as operator-named metrics.\n\nEach rule adds one gauge per poll. A rule whose path is missing, or whose value is not a\nnumber, records **nothing** for that poll rather than a zero."
          },
          "method": {
            "$ref": "#/components/schemas/HttpMethod",
            "description": "Request method (default `GET`)."
          },
          "timeout_ms": {
            "type": "integer",
            "format": "int32",
            "description": "Per-request timeout, in milliseconds (default 5000).",
            "minimum": 0
          },
          "url": {
            "type": "string",
            "description": "Full URL to probe, e.g. `https://api.example.com/health`."
          },
          "verify_tls": {
            "type": "boolean",
            "description": "Verify the TLS certificate chain (default `true`; never silently disabled — security.md)."
          }
        }
      },
      "UrlCheckRow": {
        "type": "object",
        "description": "A URL / HTTP endpoint monitor's configuration (1:1 with its node).",
        "required": [
          "node_id",
          "url",
          "method",
          "expected_status",
          "verify_tls",
          "follow_redirects",
          "timeout_ms"
        ],
        "properties": {
          "body_match": {
            "description": "The monitor's response-body keyword rule, if it has one."
          },
          "body_max_bytes": {
            "type": "integer",
            "format": "int32",
            "description": "How many bytes of the response body the monitor reads."
          },
          "credential_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "expected_status": {},
          "follow_redirects": {
            "type": "boolean"
          },
          "json_extract": {
            "description": "The monitor's JSON extraction rules, if it has any."
          },
          "method": {
            "type": "string"
          },
          "node_id": {
            "type": "string",
            "format": "uuid"
          },
          "timeout_ms": {
            "type": "integer",
            "format": "int32"
          },
          "url": {
            "type": "string"
          },
          "verify_tls": {
            "type": "boolean"
          }
        }
      },
      "UserKind": {
        "type": "string",
        "description": "How an account authenticates, which decides whether it can log in interactively at all.\n\n`Service` is the reason this enum exists. An API token needs an owner so that disabling or\ndeleting the owner takes the token with it — but binding an unattended integration to a *person*\nmeans it dies when they change teams. A service account is a machine identity: no password, no\nIdP subject, and therefore no way to sign in. It exists to own tokens.",
        "enum": [
          "local",
          "oidc",
          "ldap",
          "service"
        ]
      },
      "UserSummary": {
        "type": "object",
        "description": "User-account metadata for the API — never includes the password hash.",
        "required": [
          "id",
          "username",
          "role",
          "created_at",
          "enabled",
          "auth_source",
          "scope"
        ],
        "properties": {
          "auth_source": {
            "type": "string",
            "description": "How the account authenticates: `\"local\"` (password), `\"oidc\"` (external identity provider),\n`\"ldap\"` (directory bind), or `\"service\"` (a machine account that cannot sign in)."
          },
          "created_at": {
            "type": "string",
            "description": "Account creation time (RFC 3339 text; no chrono types cross the API edge)."
          },
          "enabled": {
            "type": "boolean",
            "description": "Account status: a disabled account is retained for the audit trail but cannot\nauthenticate (defaults to `true` for accounts created before this column existed)."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Most recent successful login (RFC 3339 text), or `None` if the account has never\nlogged in."
          },
          "role": {
            "type": "string"
          },
          "scope": {
            "$ref": "#/components/schemas/Scope",
            "description": "Which slice of the inventory this account may see: `\"All\"`, or the node groups it is\nlimited to. An Admin account is always `\"All\"` — administration is fleet-wide."
          },
          "username": {
            "type": "string"
          }
        }
      },
      "VersionInfo": {
        "type": "object",
        "description": "Build version for Settings ▸ About.",
        "required": [
          "core"
        ],
        "properties": {
          "core": {
            "type": "string"
          }
        }
      },
      "WebTlsImport": {
        "type": "object",
        "description": "A certificate chain and its private key, in PEM.",
        "required": [
          "certificate",
          "private_key"
        ],
        "properties": {
          "certificate": {
            "type": "string",
            "description": "The full certificate chain in PEM, leaf first. A private key in this field is rejected —\nsend it in `private_key`."
          },
          "private_key": {
            "type": "string",
            "description": "The matching private key in PEM: PKCS#8, PKCS#1 or SEC1, and not passphrase-protected.\nNever returned by any endpoint."
          }
        }
      },
      "WebTlsRegenerate": {
        "type": "object",
        "description": "Which names a regenerated self-signed certificate should cover.",
        "properties": {
          "names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Hostnames and IP addresses to put in the subject alternative name. If empty, the deployment's\ndefaults are used — loopback plus the server's own hostname, which is rarely the address\nbrowsers actually use."
          }
        }
      },
      "WebTlsResponse": {
        "type": "object",
        "description": "The WebUI's TLS certificate, plus one fact about how this deployment is exposed.",
        "required": [
          "api_port_is_public"
        ],
        "properties": {
          "api_port_is_public": {
            "type": "boolean",
            "description": "Whether Yagra's API port is reachable beyond the server itself. When `true`, the API is also\navailable over plain HTTP on that port, so the encrypted WebUI is not the only way in."
          },
          "config": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/WebTlsView",
                "description": "The certificate being served, or `null` if none has been established yet."
              }
            ]
          }
        }
      },
      "WebTlsView": {
        "type": "object",
        "description": "The certificate the WebUI is serving. Never includes the private key.",
        "required": [
          "source",
          "certificate",
          "subject",
          "issuer",
          "sans",
          "not_before",
          "not_after",
          "fingerprint_sha256",
          "key_algorithm",
          "expires_in_days",
          "imported_at",
          "materialized",
          "key_unreadable"
        ],
        "properties": {
          "certificate": {
            "type": "string",
            "description": "The certificate chain in PEM, leaf first. Safe to distribute — this is what a client would\nadd to a trust store or pass to `curl --cacert`."
          },
          "expires_in_days": {
            "type": "integer",
            "format": "int64",
            "description": "Days until expiry; negative once it has passed."
          },
          "fingerprint_sha256": {
            "type": "string",
            "description": "Lowercase hex SHA-256 of the certificate, matching what a browser displays."
          },
          "imported_at": {
            "type": "string",
            "description": "When this certificate was imported or generated, RFC 3339."
          },
          "imported_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account that imported it, if it was imported by a signed-in user."
          },
          "issuer": {
            "type": "string",
            "description": "Distinguished name of the issuer. Equal to `subject` for a self-signed certificate."
          },
          "key_algorithm": {
            "type": "string",
            "description": "Key type and size, for example `RSA-2048` or `ECDSA P-256`."
          },
          "key_unreadable": {
            "type": "boolean",
            "description": "Whether the private key can still be decrypted. `false` means the encryption key has changed\nor been lost: the certificate cannot be served or renewed until it is imported again."
          },
          "materialized": {
            "type": "boolean",
            "description": "Whether the web server is currently serving this certificate. `false` means it is stored but\nhas not reached the web container yet."
          },
          "not_after": {
            "type": "string",
            "description": "End of the validity window, RFC 3339."
          },
          "not_before": {
            "type": "string",
            "description": "Start of the validity window, RFC 3339."
          },
          "sans": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The hostnames and IP addresses this certificate is valid for."
          },
          "source": {
            "$ref": "#/components/schemas/TlsCertSource"
          },
          "subject": {
            "type": "string",
            "description": "Distinguished name of the certificate's subject."
          }
        }
      },
      "WindowScope": {
        "type": "string",
        "description": "How a maintenance window is scoped. The first three mirror threshold scoping (ADR-013):\n`Node` = node id, `Profile` = device-class id, `Group` = a tag value. `FolderGroup` is the\nhierarchical inventory group (resolved recursively, incl. subgroups, ADR-022) — the scope the\nAll Nodes right-click uses. It is *not* a threshold concept, so it stays local to maintenance\nrather than extending the shared [`yagra_common::ScopeLevel`].",
        "enum": [
          "node",
          "profile",
          "group",
          "group_id"
        ]
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Either a session token from `POST /api/v1/auth/login` (short-lived; what the WebUI uses), or a personal access token (`yat_…`, Settings ▸ API tokens) whose surfaces include `rest`. A token issued for `mcp` only is refused here with 401. An API token acts as the account that owns it, so its role **and** its visibility scope are capped at that account's current ones, and it stops working when the account is disabled or deleted; it cannot administer users, and endpoints that identify the signed-in account (`/auth/me`, the personal dashboard) answer 403 to it."
      }
    }
  },
  "security": [
    {
      "bearer": []
    }
  ]
}
